# 04 — Üretim engelleri: liste ve üretim anı dönüşüme ne kadar zarar veriyor? Hazırlayan: Yapay zekâ mühendisi · 22 Eyl 2026 gündüz · Kod değiştirilmedi, commit atılmadı. Kanıt türleri: **[ölçüldü]** = bu oturumda koşturularak (LLM çağrısı YOK, maliyet 0 TL), **[koddan çıkarım]** = yalnızca kod okunarak. Gerçek modelle hiçbir koşu yapılmadı. > **Satır numaraları `main @ bda4d07` referanslıdır.** Çalışma ağacında Bilal'e ait commit'lenmemiş değişiklikler var (`Dockerfile`, `globals.css`, `layout.tsx`, `liste-uretici.tsx`, yeni `src/app/api/saglik/`) — dokunulmadı. `liste-uretici.tsx`'teki satır numaraları o değişikliklerle kayar. > > **O devam eden iş bu raporun 5. maddesiyle doğrudan ilgili:** yeni `sunucuAyaktaMi()` + `kod:"SUNUCUYA_ULASILAMIYOR"` yaması, üretim bittikten hemen sonra konteyner ölünce (ters vekil 502) WebKit'in sayfayı `listem.txt` olarak indirdiği 22 Eyl vakasını kapatıyor. **Bu dalda liste DB'ye yazılmış, kredi harcanmış ve kullanıcı listeyi hiç görmemiş oluyor** — yani "3 liste oluşturuldu" sayısının bir kısmı ekrana hiç ulaşmamış olabilir. Aşağıdaki §5 tablosu bu dalı (g)'nin bir varyantı olarak okumalı. --- ## 5 maddelik karar özeti 1. **Bekleme süresi tek başına 3 listeyi açıklamıyor.** Tipik üretim ~10–20 sn (kod yorumu, `src/lib/ai/cagri.ts:66-67`), havuz SQL'i 2–72 ms [ölçüldü]. Ama **bekleme ekranı 28 saniyede donuyor**: 4 aşama mesajı 7 sn arayla akıyor (`uretim-mesaji.ts:16`), sonra "neredeyse hazır" yazısında kalıyor; "uzun sürdü" uyarısı ise **90 sn**'de geliyor (`liste-uretici.tsx:45`) — yani 28–90 sn arası kullanıcı ilerleme sinyali olmadan bekliyor. En kötü hâl 126 sn (2 deneme × 60 sn + 6 sn geçiş supabı). 2. **Asıl kapı kredi değil, maskedir.** Yeni kullanıcı 5 kredi alıyor (`credits.ts:11`), liste 3 kredi (`credits.ts:14`) — ama paketsiz kullanıcının listesinde **24 satırın 21'inin yapay zekâ metni kilitli** (`rapor-maske.ts:13`, `listem-icerik.tsx:144`). Deneme, kredinin %60'ını harcayıp %87,5'i kilitli bir çıktı üretiyor. Danışman da kilitli 21 satırı görmüyor (`api/soru/route.ts` "kilitli" dalı), yani kalan 2 kredi de yarım değerde. **"Denemeden önce ödeme" hissinin kaynağı burası.** 3. **Bir metin fiilen yanlış vaat veriyor.** `/sonuc`'taki tadımlık CTA'sı: *"24 satırın tamamı için giriş yap — 5 deneme kredin hazır"* (`tadimlik-satiri.tsx`). Giriş yapan kullanıcı 24 satırın tamamını almıyor; 3 açık + 21 kilitli alıyor. Aynı CTA giriş dönüşünde kullanıcıyı `/listem?uret=1`'e değil **düz `/sonuc`'a** bırakıyor (`callback=${sonucHref()}` → `"/sonuc"`), yani üretim başlamıyor, bir tık daha gerekiyor. Yanındaki hazır panel doğru yere (`LISTEM_URET_HREF`) gidiyor — iki CTA aynı sayfada farklı davranıyor. 4. **"Üretmeden gösterme" için elimizde hazır ve bedava bir yol var.** 24'lük iskeletin **gerekçe dışındaki her şeyi zaten deterministik**: program seçimi, dilim, risk notu ve trend cümlesi LLM'siz kuruluyor — **24 satır 2–72 ms'de, 0 LLM çağrısıyla** [ölçüldü]. Üstüne 522 satırlık tadımlık havuzu (`app.db/tadimlik_havuzu`, kova×tür×kategori×tip) duruyor [ölçüldü: 522 satır]. Bugün bu varlığın tamamı **yalnızca `/sonuc`'ta, yalnızca tek satır** olarak kullanılıyor — 30 günde 23 kişinin gördüğü sayfada. Trafiğin %75'i olan katalog sayfaları yapay zekâ çıktısını hiç görmüyor. 5. **3 listenin yanında kaç başarısız deneme olduğu Rybbit'ten ölçülemiyor** — `liste_uretim_hata` olayı 21 Eyl 04:49'da eklendi (`cf19903`) ve prod'a 21 Eyl öğleden sonra çıktı; 23 Ağu–21 Eyl penceresinin tamamında hata dalı ölçüsüzdü. **Ama prod DB'den bugün, kod değişmeden çıkarılabiliyor:** `credit_ledger`'da `report_generate` satırı = deneme, aynı `ref_id`'li `refund` satırı = başarısızlık. Sorgu §5'te. --- ## 1. Üretim anının maliyeti ### Kullanıcı ne yaşıyor (akış, dosya:satır) | # | Adım | Nerede | Süre | |---|---|---|---| | 1 | "Listemi oluştur" → seçimler storage'a yazılır, `/listem?uret=1`'e gidilir | `sihirbaz-cagri-karti.tsx:179-188` | anlık | | 2 | Girişsizse araya `/giris` girer (Google OAuth tur) | `sihirbaz-cagri-karti.tsx:185` | ~5–15 sn (ölçülmedi) | | 3 | `ListeUretici` mount → localStorage/çerez profili okunur → server action | `liste-uretici.tsx:162-176` | anlık | | 4 | **3 kredi düşülür** (LLM'den ÖNCE) | `rapor-actions.ts:119-124` | anlık | | 5 | Aday havuzu SQL + filtre/gevşetme | `rapor-havuzu.ts:93` | **2–72 ms** [ölçüldü] | | 6 | LLM çağrısı (`reasoning_effort:"none"`, `max_tokens:4000`) | `rapor.ts:304-315`, `cagri.ts:90-115` | tipik ~10–20 sn [kod yorumu, `cagri.ts:66`], üst sınır 60 sn | | 7 | Şema/adet tutmazsa **2. deneme** (yeni 60 sn bütçesi) | `rapor.ts:303-332` | +0–60 sn | | 8 | Rapor DB'ye yazılır, `router.replace("/listem")` | `rapor-actions.ts:181-195`, `liste-uretici.tsx:114` | anlık | | 9 | Geçiş olmazsa emniyet supabı tam sayfa yükler | `liste-uretici.tsx:41,136-150` | +6 sn | **Toplam:** tipik **15–30 sn**, gerçekçi kötü hâl **60–70 sn**, teorik en kötü **~126 sn**. ### Ekranda ne görüyor - İki kolonlu iskelet (8 satır skeleton + danışman paneli) + shimmer'lı aşama metni (`liste-uretici.tsx:239-341`). - Metinler: 4 aşama, 7000 ms arayla, **sonuncuda duruyor** (`uretim-mesaji.ts:11-17,19`). → **28 sn sonra ilerleme sinyali yok.** - Altta: *"Bu işlem yarım dakika kadar sürebilir, sayfayı kapatma."* (`liste-uretici.tsx:271`). - "Beklenenden uzun sürdü" mesajı **90 sn**'de (`liste-uretici.tsx:45`). 60 sn'de ilk deneme abort olup ikinci deneme sessizce başlıyorsa kullanıcı 60–90 sn arası hiçbir şey öğrenmiyor. **Bir ilk kullanıcıyı kaçırır mı?** Ortalama (15–30 sn) için hayır; bu ekran iyi tasarlanmış. Kaçırdığı yer **kuyruk**: girişsiz kullanıcı için tıklama → OAuth → yeniden yükleme → 15–30 sn bekleme zinciri, ödül 3 açık satırsa orantısız. Mobilde `/sonuc`'tan çıkışa medyan 33 sn (03 raporu §2) — bu sabırla, girişten sonra 30 sn daha bekleme talep ediliyor. ### "Sayfayı kapatma" gerçek bir tehdit `cagri.ts:63-67` kendi notunda söylüyor: *"fonksiyon dışarıdan öldürülürse harcanan kredi iade edilemiyor."* Kredi LLM'den önce düşüyor (`rapor-actions.ts:119`), iade yalnızca `catch` bloğu koşarsa oluyor (`rapor-actions.ts:169-178`). Kullanıcı sekmeyi 20. saniyede kapatırsa **5 deneme kredisinin 3'ünü hiçbir şey görmeden kaybetme riski var** ve bu dal hiçbir yerde sayılmıyor. [koddan çıkarım] ### Maliyet (token; TL yazılmadı — fiyat OpenRouter panelinden okunmalı) Model: `deepseek/deepseek-v4-flash` varsayılan (`client.ts:6`); env ile değişebilir. | Profil | Havuz | Hedef (h/d/g) | Gevşetildi | Havuz JSON | ~token | |---|---|---|---|---|---| | 5.000 / say / müh + İstanbul | 40 | **8/6/10** | **il** | 9.606 char | ~2.9k | | 30.000 / say / müh | 51 | 5/13/6 | — | 12.350 | ~3,7k | | 75.000 / ea / hukuk (devlet) | 60 | 5/13/6 | kategori | 14.185 | ~4,3k | | 175.000 / söz / seçimsiz | 60 | 5/13/6 | — | 14.324 | ~4,3k | | 375.000 / tyt / sağlık | 60 | 5/13/6 | kategori | 14.477 | ~4,4k | | 750.000 / tyt / seçimsiz | 60 | 5/13/6 | — | 14.749 | ~4,5k | [ölçüldü] — `havuzOlustur` + `havuzuKompaktJson`, LLM'e gidilmedi. Token ≈ char/3.3 (Türkçe+JSON için kaba katsayı, doğrulanmadı). - **Girdi/çağrı:** havuz (~2,9–4,5k) + sistem prompt'u (~600) + kullanıcı sarmalayıcı (~200) ≈ **3,7–5,3k token**. - **Çıktı/çağrı:** 24 × (id + ~15 kelimelik gerekçe) + genel + uyarılar ≈ **~1,1–1,5k token** (tavan `max_tokens: 4000`). - **Başarılı üretim = 1 çağrı.** En kötü hâl **6 çağrı**: dış döngü 2 deneme (`rapor.ts:303`) × iç geçici-hata tekrarı 3 (`cagri.ts:43`). - Revizyon aynı maliyet + önceki liste özeti (24 satır ≈ +1k token). --- ## 2. Kredi kapısı | Soru | Cevap | Kanıt | |---|---|---| | Liste kaç kredi? | **3** | `credits.ts:14` | | Yeni kullanıcıda kaç kredi? | **5**, kayıt anında otomatik | `credits.ts:11`, `auth.ts:148-157` | | Ücretsiz deneme var mı? | Evet ama **maskeli**: 24 satırın ilk 3'ü açık | `rapor-maske.ts:13`, `listem-icerik.tsx:144` | | Revizyon deneme kredisiyle yapılabilir mi? | **Hayır** — paket şartı var | `rapor-actions.ts:215` | | Sohbet? | 1 kredi/mesaj → kalan 2 kredi = 2 soru | `credits.ts:88-120` | | Kredi bitince ne görüyor? | "Kredin bu liste için yetmiyor" + paket CTA (299 TL) ya da top-up (129 TL) | `liste-uretici.tsx:180-206` | | `kredi_bitti` ölçülüyor mu? | Evet, istemcide; ayrıca `krediBittiIsaretle` 48 saatlik e-posta zamanlayıcısını kuruyor | `liste-uretici.tsx:121`, `credits.ts:206-225` | ### "Denemeden önce ödeme" hissi nerede 1. **Maske.** Deneme kullanıcısının aldığı yapay zekâ metni toplamda ~5 cümle: 3 gerekçe (her biri ≤15 kelime) + kırpılmış genel değerlendirme (ilk 2 cümle, `rapor-maske.ts:26-30`) + 1 uyarı. Kalan 21 satırda "Bu tercih için kişisel gerekçe paketle açılır." yazıyor. Yani **deneme, ürünü göstermiyor; paywall'u gösteriyor**. 2. **Sayfa başlığı.** Paketsiz kullanıcının liste sayfasının H1'i: *"Veriyi ücretsiz incele. Kararı Yapay Zeka ile netleştir."* (`listem-govde.tsx:186-188`) — kullanıcı az önce 3 kredisini yaktı, karşılandığı cümle bir satış cümlesi. 3. **Danışman kısıtı.** Kilitli satırları danışman da görmüyor ve sorulursa 299 TL'yi söylüyor (`api/soru/route.ts` kilitli dalı). Kalan 2 kredi yarım değerde. 4. **Yanlış vaat.** `/sonuc` tadımlık CTA'sı "24 satırın tamamı için giriş yap" diyor; teslim edilen 3/24. Bu hem dönüşüm hem güven sorunu. --- ## 3. Değeri üretmeden gösterme — **en önemli madde** ### Bugün elimizde ne var | Varlık | Durum | Nerede gösteriliyor | |---|---|---| | **Tadımlık havuzu** — 522 satır, kova×tür×kategori×tip; genel 178 / devlet 170 / vakıf 174 [ölçüldü] | Dolu, **elle yazılmış** (LLM değil; KARARLAR 21 Eyl) | Yalnız `/sonuc`, **tek satır**, yalnız girişsize (`tadimlik-bolumu.tsx:12-13`) | | **Deterministik 24'lük iskelet** — seçim + dilim + risk notu + trend cümlesi | Kod hazır, LLM gerekmiyor | **Hiçbir yerde** ürün öncesi gösterilmiyor | | Ham dilim tablosu (hayal/dengeli/garanti) | Çalışıyor | `/sonuc`, `/universite/*`, `/bolum/*` | | Ana sayfada örnek liste | **Yok** | — | | `/meraklisina` demo | Var ama sayı/şema anlatımı, liste değil | `meraklisina-demo.tsx` | **Sorun:** tadımlık, huninin en dar kapısının **arkasında**. 30 günde `/sonuc`'u 23 kişi gördü; katalogdan gelen 464 oturum yapay zekâ çıktısını hiç görmedi. `tadimlik_goruntulendi` 30 günde 0 (03 raporu §2) — gösterildiğine dair kanıt da yok. ### Öneri: "Senin 24'lük iskeletin" — 0 LLM çağrısı, 0 ek veri Ölçüm [ölçüldü]: `havuzOlustur` + `dilimHedefiHesapla` + `riskNotuMetni` + `trendOzetiMetni` ile **24 satırın tamamı 2,1–72 ms'de, hiç LLM çağrısı yapmadan** kuruluyor. Örnek çıktı (750k/tyt): ``` 1. [hayal] İnşaat Teknolojisi risk : Son taban sıralaması senin sıranın üstünde kapandı; hayal tercihi olarak düşün. trend: 2021-2026 arasında taban 1,1M düzeyinden 746B düzeyine indi; taban sıkılaştı. ``` Bunlar **kullanıcının kendi sıralamasına göre hesaplanmış gerçek cümleler** — jenerik örnek değil. Eksik olan tek şey `gerekce` (LLM'in tek cümlesi). **Teknik yol:** - **Veri kaynağı:** mevcut `yokatlas.db` + `rapor-havuzu.ts`. Yeni tablo, yeni betik, yeni env yok. - **Üretim zamanı:** istek anında, sunucuda (RSC). SQL 2–72 ms. - **Maliyet:** **0** — LLM'e hiç gidilmiyor, anonim istek zaten LLM'e gitmiyor (`tadimlik-havuzu.ts:1-4` kuralı korunur). - **Ekran:** `/sonuc`'ta bugünkü tek tadımlık satırının yerine 24 satırlık gerçek iskelet; 1–3. satırların gerekçesi **tadımlık havuzundan** (kova×tür×kategori×tip anahtarıyla zaten eşleşiyor), 4–24 arası gerekçe alanı bulanık + "Giriş yap, yapay zekâ 24 gerekçeyi senin için yazsın". Yani bugünkü kilit deneyiminin **ücretsiz, dürüst ve kredi harcamayan** prova hâli. - **Katalog sayfalarına taşınabilir hâli:** `/universite/*` ve `/bolum/*`'da sıra girildikten sonra aynı iskeletin ilk 5 satırı — 464 oturumluk trafiğe yapay zekâ çıktısının ne olduğunu ilk kez gösterir. **Neden bu, LLM'li bir "örnek liste"den iyi:** kişiselleştirilmiş (kendi sırası, kendi illeri), bayatlamaz (canlı veriden), 0 TL, ve KARARLAR 21 Eyl'deki "tadımlık için LLM koşusu varsayılan yol değildir" kararıyla çelişmez. **Alternatif (daha pahalı, önerilmez):** 6 kova × 5 tür = 30 hazır örnek listeyi batch üretmek ≈ 30 çağrı, ~135k girdi + ~45k çıktı token, tek seferlik. Prod veriye yazdığı için `[BİLAL]`. Elle yazım yolu (522 satırda yapıldığı gibi) bundan da ucuz. --- ## 4. Kalite ve güven ### Havuz-dışına çıkamama — **sağlam** `normalizeEt` (`rapor.ts:120-137`) modelin döndürdüğü her id'yi `havuzMap`'te doğruluyor; havuzda olmayan ve tekrar eden id'ler **sessizce atılıyor**, dilim ise havuzdaki gerçek değerden **yeniden atanıyor**. Kurtarma dalı (`rapor.ts:349-385`) eksik dilimleri yine havuzdan deterministik dolduruyor. Modelin uydurduğu bir program kullanıcıya **ulaşamaz**. Bu korumaya dokunulmamalı. ### 24'lük iskelet — garanti edilen şey "24" değil `dilimHedefiHesapla` ideal 5/13/6'dan sapabiliyor ve sapma sessiz: - **5.000 / say / Mühendislik + İstanbul → 8 hayal / 6 dengeli / 10 garanti** [ölçüldü]. Bu listeye "dengeli ağırlıklı" demek mümkün değil. - Aynı profilde **il filtresi tamamen düşürüldü** (`gevsetildi: ["il"]`): kullanıcı İstanbul seçti, havuz Türkiye geneline açıldı. `havuzOlustur` bunu `gevsetildi` olarak döndürüyor ama `raporUret` bunu yalnızca prompt'a not düşüyor (`rapor.ts:255-264`) — **`RaporKapsam`'a konmuyor** (`rapor.ts:105-111`), yani kullanıcı hiç öğrenmiyor. `uyarlandi` bayrağı yalnızca sayıların kaydığını söylüyor, **hangi seçiminin feda edildiğini söylemiyor.** ### "Bu bana özel" hissini taşıyan tek alan: `gerekce` - `gerekce`: tek cümle, ≤15 kelime, sistem prompt'unda "METİN DİYETİ" olarak sıkıştırılmış (`rapor.ts:79-81`). - `riskNotu` ve `trendOzeti` **deterministik** — aynı sıra bandındaki herkeste birebir aynı cümle. Kişisel okunmuyor. - Kullanıcının sihirbazda girdiği **iller ve öncelikler çıktıda hiçbir yerde geri yansımıyor**; prompt'a giriyor ama satır düzeyinde görünür karşılığı yok. - Paketsizde bu yüzeyin %87,5'i maskeli. ### Vaat dili denetimi — **prompt var, çıktı denetimi yok** Prompt "garanti / kesin / yüzde yüz" diyor (`rapor.ts:80-86`), sohbet prompt'u da yasaklıyor (`api/soru/route.ts`). Ama **çıktı tarafında hiçbir denetim yok**: `gerekceServisEdilebilir` / `YASAK_GEREKCE_DILI` yalnızca tadımlıkta kullanılıyor (`tadimlik-havuzu.ts:62,91,126`). Rapor metinleri DB'ye yazılıyor (`rapor-actions.ts:181-195`) ve her `/listem` açılışında yeniden servis ediliyor — bir kez sızan "yüksek ihtimalle" cümlesi kalıcı. PROTOKOL/ilke 3'e aykırı ("prompt tek başına yetmez"). ### İki iyileştirme önerisi (prompt/şema seviyesi) **İ1 — Şemaya doğrulanabilir kişiselleştirme alanı ekle.** `AiTercihSchema`'ya `esles: z.enum([...kullanıcının gerçek kategorileri, illeri, öncelikleri, "genel"])` ekle. Enum kullanıcının kendi girdisinden üretildiği için model **uyduramaz**, kod çapraz doğrulayabilir ve UI satırın yanında bir çip basabilir ("İstanbul" / "Burs önceliğin" / "Mühendislik"). Maliyet: satır başına ~10 token (+~240 token/liste). Kazanç: kişiselleştirme **görünür** ve **denetlenebilir** hâle gelir. `[KARAR]` — ama iskelet değişikliği olduğu için `/meraklisina` şeması aynı commit'te güncellenmeli (AGENTS.md). **İ2 — Çıktı denetimi + gevşetme dürüstlüğü.** (a) `gerekceServisEdilebilir`'i `lib/risk.ts` ya da ortak bir modüle taşıyıp rapor `gerekce` / `genelDegerlendirme` / `uyarilar` alanlarına da uygula; takılan satırın gerekçesi deterministik şablona düşsün ve sayaç tutulsun (§5'teki tek olay). (b) `gevsetildi`'yi `RaporKapsam`'a ekleyip UI'da tek cümle: "İstanbul'da 24 program çıkmadı; listeye yakın illerden de eklendi." Bu hem dürüstlük hem "beni gerçekten dinlemiş" sinyali. `[KARAR]`. --- ## 5. Sessiz hatalar ### Dallar ve ölçüm durumu | # | Dal | Kod | Kredi | Ölçülüyor mu | |---|---|---|---|---| | a | Şema iki denemede de tutmadı | `rapor.ts:334-348` | iade | `liste_uretim_hata{kod:"HATA"}` — **yalnız 21 Eyl'den beri** | | b | 429/5xx, 3 tekrar tükendi | `cagri.ts:41-59` | iade | aynı | | c | 60 sn zaman aşımı | `cagri.ts:68,90` | iade | aynı | | d | `AI_KEY_MISSING` | `client.ts:34` | iade | aynı (kullanıcıya altyapı sızmıyor — doğru) | | e | Havuz < 3 program | `rapor.ts:236-240` | iade | aynı | | f | **Kurtarma dalı: liste kuruldu ama satırlar şablon** | `rapor.ts:349-385` | harcandı | **HAYIR** — yalnız `console.warn`. `liste_olusturuldu` atılıyor, başarı sayılıyor | | g | **Kullanıcı sekmeyi üretim sırasında kapattı** | `cagri.ts:63-67` notu | **iade edilemeyebilir** | **HAYIR** — hiç olay yok | | h | İstemci tarafı istisna | `liste-uretici.tsx:95` | belirsiz | `kod:"ISTISNA"` | | i | Kredi yetersiz | `liste-uretici.tsx:121` | harcanmadı | `kredi_bitti` | | j | Oturum düşmüş (AUTH) | `liste-uretici.tsx:123-124` | harcanmadı | **HAYIR** — sessizce `/giris`'e atıyor | ### 3 listenin yanında kaç başarısız deneme var? **Rybbit'ten ölçülemiyor.** `liste_uretim_hata` olayı `cf19903` (21 Eyl 2026 04:49) ile eklendi ve 03 raporu §0'a göre prod'a 21 Eyl ~15:20'de çıktı. 23 Ağu–21 Eyl penceresinin tamamı ölçüsüz. **Ama prod DB'den bugün, kod değişmeden çıkarılabilir** — `credit_ledger`'da her deneme bir `report_generate` satırı, her başarısızlık aynı `ref_id`'li bir `refund` satırı bırakıyor (`rapor-actions.ts:119-124`, `171-176`). Salt okuma, Bilal koşar: ```sql -- 30 günde liste üretim denemesi / başarısız (iade edilmiş) oranı SELECT date(g.created_at,'unixepoch','localtime') AS gun, COUNT(*) AS deneme, SUM(CASE WHEN r.id IS NULL THEN 0 ELSE 1 END) AS basarisiz_iade FROM credit_ledger g LEFT JOIN credit_ledger r ON r.reason='refund' AND r.ref_id = g.ref_id WHERE g.reason='report_generate' AND g.created_at >= strftime('%s','now','-30 days') GROUP BY 1 ORDER BY 1; ``` ```sql -- Kurtarma dalına düşmüş (şablon gerekçeli) liste sayısı SELECT COUNT(*) FROM reports WHERE result LIKE '%Sıralamana ve seçimlerine uygun olduğu için listene eklendi.%'; ``` `deneme − basarisiz_iade` sayısı Rybbit'teki `liste_olusturuldu` = 3 ile de çapraz doğrulanır; aradaki fark sekme kapatan kullanıcıları (dal g) gösterir. ### Eklenecek tek olay **`liste_uretim_kalite`** — üretim başarıyla bittiğinde sunucudan değil, mevcut `liste_olusturuldu` olayına **iki özellik ekleyerek** (yeni olay adı gerektirmez, `OlayAdi` birliği büyümez): ``` liste_olusturuldu { tur, sira_kovasi, kurtarma: 0|1, // rapor.ts:349 dalına düşüldü mü ai_satir: } // AI'nın verdiği, havuzda doğrulanan satır sayısı ``` Bu tek ek, (f) dalını görünür kılar: "liste kuruldu" ile "yapay zekâ gerçekten 24 gerekçe yazdı" arasındaki farkı ölçer. `ListeSonuc`'a iki alan eklemek yeterli; prompt/model değişmez. --- ## Eval seti — bugün yok, kurulması öneriliyor Repoda eval yok. Bu turda yalnız **iki maliyetsiz ölçüm** koşuldu (havuz boyutu; deterministik iskelet süresi). Gerçek modelle hiçbir koşu yapılmadı. Önerilen: `scripts/eval-liste.ts` (`tsx`), girdi 12 temsilî profil (6 kova × say/ea/söz/tyt karışık, il-filtreli ve filtresiz, seçimsiz dahil). Ölçülecekler: | Metrik | Hedef | Bugün nasıl ölçülür | |---|---|---| | Şema geçerliliği (1. denemede) | %100 | `yapilandirilmisUret` null dönüşü | | Havuz-dışı program sayısı | **0** | `normalizeEt` öncesi/sonrası fark | | Kurtarma dalına düşme oranı | 0 | `rapor.ts:353` warn'ı sayaca çevrilir | | Yasak ifade sayısı (gerekce/genel/uyarılar) | **0** | `gerekceServisEdilebilir` | | Dilim dağılımı ideale uzaklık | raporlanır | `dilimHedefiHesapla` vs `IDEAL_HEDEF` | | p50/p95 gecikme | p95 < 30 sn | çağrı süresi | | Girdi/çıktı token | raporlanır | API yanıtı `usage` | `anahtarVar()` yoksa mock yolu koşar ve rapora "gerçek modelle koşulmadı" yazılır. Gerçek modelle bir tam koşu = **12 çağrı** (retry'la en kötü 24) — 50 çağrı sınırının altında, ayrı onay gerekmez; prod DB'ye yazmaz. --- ## Maliyet ve gecikme etkisi (önerilerin) | Öneri | LLM çağrısı | Gecikme | Not | |---|---|---|---| | §3 "Senin iskeletin" önizlemesi | **0** | +2–72 ms SSR | Yeni tablo/betik yok | | İ1 `esles` alanı | değişmez (1) | ihmal | +~240 token/liste (~%5 çıktı) | | İ2 çıktı denetimi + `gevsetildi` | **0** | <1 ms (regex) | Saf fonksiyon | | §5 iki olay özelliği | 0 | 0 | Yalnız ölçüm | | Aşama mesajı + 90 sn eşiği | 0 | 0 | Metin/sabit | Hiçbir öneri model, sağlayıcı ya da env değiştirmiyor; kredi başına maliyet aynı kalıyor. --- ## Önerilen değişiklikler | # | Değişiklik | Dosya | Yetki | |---|---|---|---| | 1 | **Tadımlık CTA'sının vaadini ve hedefini düzelt:** metin "24 satırın tamamı" demesin (maske 3/24); `callback` `sonucHref()` yerine `LISTEM_URET_HREF` olsun | `tadimlik-satiri.tsx` | `[KARAR]` — metin marka/vaat içerdiği için son hâli Bilal onaylamalı | | 2 | **§3 "Senin 24'lük iskeletin" önizlemesi** — 0 LLM, kendi sırasıyla, gerekçe bulanık | yeni bileşen + `sonuc/page.tsx` | `[KARAR]` (uygulama `cto`/`yazilimci` şartnamesiyle); `/meraklisina` şeması aynı commit'te | | 3 | **İ2 çıktı denetimi:** yasak dil filtresi rapor metinlerine de | `rapor.ts`, `tadimlik-havuzu.ts`→ortak modül | `[KARAR]` | | 4 | **`gevsetildi`'yi `RaporKapsam`'a ekle** ve UI'da tek cümle söyle | `rapor.ts:105`, `listem-govde.tsx` | `[KARAR]` | | 5 | **Aşama mesajları 28 sn'de donmasın; "uzun sürdü" eşiği 90→55 sn** (ilk abort'tan önce) | `uretim-mesaji.ts`, `liste-uretici.tsx:45` | `[KARAR]` | | 6 | **İ1 `esles` alanı** — şema + `/meraklisina` senkronu | `rapor.ts`, `huni-semasi.tsx` | `[KARAR]`, önce eval | | 7 | **Deneme maskesini gevşet** (ör. ilk 3 yerine ilk 8 satır açık, ya da deneme listesinin tamamı açık + revizyon/PDF ücretli) | `rapor-maske.ts:13` | **`[BİLAL]`** — doğrudan gelir modeli kararı | | 8 | Prod DB'de §5 sorgularını koş | — | **`[BİLAL]`** | --- ## Bilal'den istenen 1. **§5'teki iki SQL'i prod'da koş** (salt okuma) ve sonucu paylaş — "3 liste"nin yanında kaç deneme ve kaç şablon-gerekçeli liste olduğunu ancak bu söyler. (~5 dk) 2. **Karar ver: deneme kullanıcısı 24 satırın kaçını görecek?** Bugün 3; bu, denemenin ürünü değil paywall'u göstermesine yol açıyor ve `/sonuc`'taki CTA metnini fiilen yanlış kılıyor. (~10 dk, gelir modeli kararı) 3. **§3 önizlemesini (0 maliyet, 0 LLM) sıraya al mı?** Katalogdaki 464 oturuma yapay zekâ çıktısının ne olduğunu ilk kez gösterecek tek ucuz hamle bu. (~5 dk onay)