docs(ekip): 22-23 Eylül vardiya raporları, BACKLOG/KARARLAR/PROTOKOL güncellemeleri
All checks were successful
Deploy / deploy (push) Successful in 17s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-23 11:43:11 +03:00
parent a8c75ce4a7
commit a42a1a9920
27 changed files with 3508 additions and 8 deletions

View File

@@ -0,0 +1 @@
1790148096

View File

@@ -0,0 +1,16 @@
# Gece vardiyası 2026-09-22 — Bilal'in brifingi
Bilal'in kendi sözleriyle hedef (orkestratör notu, talimat kaynağı Bilal'dir):
1. **Sitede kolay bir akış.** Gereksiz şey olmayacak. "Bilgi vereceğiz" diye kullanıcıyı boğmayacağız. Bu gecenin tek numaralı ölçütü budur: bir öneri akışı kolaylaştırmıyorsa reddedilir.
2. **Radikal kararlarda Bilal'in onayı şart.** Geri dönüşü zor, marka/para/hukuk/canlı sistem içeren her şey `[BİLAL]`.
3. **Geliştirmeleri tasarımcı + UX tespit eder, analitik ajanı ile birlikte gerçeğe dayanarak.** Fikir değil kanıt: rakamın yanında kaynağı olacak.
4. **URAP izni geldi (sevindirici haber).** URAP Araştırma Laboratuvarı, Bilal'e e-posta ile: "urapcenter.org adresine aktif bağlantı/atıf vermek kaydıyla verilerimizi web uygulamanızda yayımlayabilirsiniz. https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025 şeklinde verirseniz eğer güncelleme olursa sıralamada sizde de direkt uygulanmış olur."
Niyet: "ümmeti Muhammed tercih yaparken kolayca metrikleri görsün." Yani sıralama verisi öğrenciye **kolay** görünmeli; tablo yığını değil.
5. **24'lük liste / 3 kredi / API maliyeti** anlatılacak ve yapay zekâ API'siyle daha ne sunabileceğimiz **gerçek metriklerle** önerilecek.
6. **Rakip + acı noktası araştırması:** forumlarda, şikâyet sitelerinde öğrenci ve velilerin gerçekten ne istediği; hangi acıyı dindirebiliriz.
7. **OVER-ENGINEERING YASAK.** Bilal'in uyarısı: "olup olmadık şeyleri test etmek" gibi israf yok. Verimli ol. Küçük, kesin, kanıtlı iş.
8. Sabah Bilal'e **teknik olmayan, sade dille** tek özet sunulacak.
Kurallar: `docs/ekip/PROTOKOL.md` (push yok, `main`'e commit yok, Bilal'in commit'lenmemiş dosyalarına dokunma, uydurma veri yok).
Dünkü vardiya: `docs/gece-vardiyasi/2026-09-21/SABAH-OZETI.md` — okunacak, tekrar edilmeyecek.

View File

@@ -0,0 +1,107 @@
# Orkestratör günlüğü — 2026-09-22 gecesi
## Tur 1 (23:47 – 00:00) — beş bulgu ajanı paralel
| Ajan | Rapor | Durum |
|---|---|---|
| analitik | `01-analitik.md` | ✔ 801 temiz TR oturumu |
| tasarimci | `02-tasarim.md` | ✔ 5 kesim + URAP yerleşimi |
| marka | `03-acilar-ve-rakipler.md` | ✔ forum/şikâyet acıları |
| yapay-zeka-muhendisi | `04-liste-maliyet-ve-oneriler.md` | ✔ maliyet ölçüldü |
| veri-muhendisi | `05-urap.md` | ✔ URAP 198/198 eşleşti |
### Gecenin yakınsaması (orkestratör notu)
`analitik` ve `marka` birbirinden HABERSİZ aynı noktaya çıktı:
- **analitik:** net detayını açan oturumun sıra girme oranı %9,4; açmayanın %3,2. Ama oturumların %85,5'i hiç açmıyor. "Sorun fazla bilgi değil, işe yarayan tek bilginin bir tıklamanın arkasında olması."
- **marka:** YÖK Atlas 2026'da net/OBP verisini KALDIRDI, adaylar şikâyet ediyor. O veri bizde duruyor (`netler` tablosu, 2023-2025, ~21bin kayıt/yıl) ama yalnız bir modalın arkasında ve pazarlamada tek cümle yok.
İkisi birleşince: elimizde rakipte olmayan bir veri var, üstelik ölçülmüş dönüşüm etkisi var, ve bir tıklamanın arkasında saklı. Tur 2'de CEO'nun önündeki ana karar bu.
`tasarimci` ve `marka` URAP'ta da bağımsız olarak aynı sonuca vardı: tablo değil, üniversite sayfasında tek satır + atıf.
## Tur 2 (00:00 –) — CEO karar turu
`ceo` → `06-ceo-kararlari.md`. Üç rapor iddiası koddan ÇÜRÜTÜLDÜ (`/bolum`'de form yok iddiası, `/paket`'te iade görünmüyor iddiası, sezon bandı kesimi — bandın metnini Bilal 18 saat önce bizzat seçmiş). 4 iş onaylandı, gerisi gerekçeli reddedildi. `KARARLAR.md`'ye 11 kayıt eklendi.
**Bilal 00:05'te yazdı:** "uyuyorum benden onay bekleme bundan sonra" + "çalışsın ekip".
Orkestratör yorumu: bu, işin durmaması içindir; geri dönüşü olmayan yetki DEĞİLDİR. Push, deploy, `main`'e commit ve fiyat/paketleme değişikliği yine yapılmaz — `[BİLAL]` işler dalda hazır bekler.
## Tur 3 (00:10 –) — dört paket paralel, ayrı worktree + dal
| Paket | Dal | Ajan |
|---|---|---|
| P1 risk etiketi | `gece/0922-risk-etiketi` | yazilimci |
| P2 unitur sızıntısı | `gece/0922-unitur-kacagi` | veri-muhendisi |
| P3 URAP | `gece/0922-urap` | yazilimci |
| P4 ölçüm | `gece/0922-olcum` | yazilimci |
Bilinen çakışma: P2 ve P3 ikisi de `scripts/veri-kalite.ts` sonuna ekleme yapıyor. İkisine de "dosyanın en sonuna ekle, mevcut satırları düzenleme" denildi; merge'ü orkestratör çözecek.
### P1 ✔ (00:18) — `gece/0922-risk-etiketi` @ 2dbc8b5
tsc + lint temiz. Sapma (kabul): `/sonuc` tablosunun boş ilk sütun başlığına "Risk" yazıldı — sütun artık metin taşıyor, `/listem`'deki eşdeğer sütunla hizalandı.
Bedel: risk sütunu ~86px aldı, program adı sütunu ~150px→~85px kısalıyor (kesilme değil, truncate). Bilal telefondan bakacak.
Kapsam dışı iki bulgu (backlog adayı, dokunulmadı): `rapor-listesi.tsx:264` kilitli satırdaki "Pakette" etiketi hâlâ mobilde `sr-only`; `liste-cekmecesi.tsx:426` çekmecede risk yalnız renkli nokta.
### P4 ✔ (00:24) — `gece/0922-olcum` @ 26893ce
tsc + lint temiz. 14/14 `/paket` linkinde artık `?kaynak=` var; `sihirbaz_adim{1}` modal açılışında `olayBirKez` ile bir kez atılıyor.
**Şartname sapması (orkestratör onayı: kabul).** `paket-gorunum-olayi.tsx` dosya listesinde yoktu ama `?kaynak=` değerlerini `["kilit","kredi_bitti","nav"]` allowlist'inden süzüp gerisini `"diger"`e düşürüyormuş. Genişletilmeseydi 10 yeni kaynak panelde tek kovada toplanacak, iş görünüşte bitip ölçüm deliği kapanmayacaktı — AGENTS.md'nin "kısmi commit'te bağımlılık kapanışını kontrol et" kuralının tam örneği. Aynı commit'e alındı, P1/P2/P3 kapsamıyla çakışmıyor.
Yan not (ayrı iş): `listem-govde.tsx:288` ve `:369` iki ayrı kilit yüzeyi ama ikisi de `kaynak=kilit`.
### P3 ✔ (00:34) — `gece/0922-urap` @ 68cb69e, 4932671, b63c7e8
typegen + tsc + lint + **build temiz** (229 üniversite sayfası prerender). Kabul kriterleri 6/6.
**Orkestratörün bağımsız veri doğrulaması (yapıldı, kritik).** URAP verisini dışarıya atıf vererek yayımlayacağımız için ajanın verisine güvenmeyip kendim denetledim. Şüphem şuydu: URAP akademik yayın/atıf ağırlıklı bir sıralama, Koç'un 1. olması beklenmedik göründü.
- Tarayıcı bu oturumda açılmadı (erişim reddedildi) → URAP'ın kendi basın açıklaması PDF'i indirildi ve akış çözülerek okundu (`newtr.urapcenter.org/cdn/storage/PDFs/mezDn2uAd4mx2mZzW`, 28 Ekim 2025).
- PDF'te üniversite adları gömülü fontta olduğu için çıkmadı, **puanlar çıktı**. Puanlar üç tabloya bölünmüştü ve ilk bakışta devlet/vakıf ayrımı sandım — tutarsızlık şüphesi buradan doğdu.
- Anadolu Ajansı haberiyle çözüldü: tablolar devlet/vakıf değil, **tıp fakültesi olan / olmayan** ayrımı. Genel sıralama: 1 Koç, 2 Hacettepe, 3 ODTÜ.
- **Beş nokta karşılaştırması PDF'teki puanlarla birebir tuttu:** 1 Koç 1152,91 · 2 Hacettepe 1096,48 · 3 ODTÜ 1082,81 · 4 İTÜ 1067,01 · 18 Boğaziçi 881,20. Dosyada 198 satır.
- **Hüküm: veri doğru.** Şüphe yersiz çıktı ama denetim gerekliydi; yanlış olsaydı hem öğrenciyi yanıltırdık hem URAP iznini riske atardık.
Sapmalar (kabul): kaynak satırı yalnız 1. sayfada (derin sayfalarda URAP sayısı da yok) · boş durum varyantı `unitur`'a bakıyor, P2 merge'ünden sonra üç kurum ek kod olmadan doğru cümleye geçiyor · 5. veri-kalite kontrolü "önceki dönem" sabiti olmadığı için "URAP dışında kalan 150+ programlı TR üniversitesi" kontrolüne çevrildi.
**P2 ile tek çakışma yüzeyi:** `scripts/veri-kalite.ts` import bloğunun sonu.
### P2 ✔ (00:42) — `gece/0922-unitur-kacagi` @ iki commit (kod+rapor, veri)
Devlet filtresi 27→0, vakıf 0→27. 126 satır düzeldi; 45 kolon kıyaslandı, değişen yalnız `unitur` ve `il`; 2021–2026 puan/sıra/kontenjan kolonlarında **0 satır** değişti.
**Şartname genişletmesi (kabul, iyi yakalama):** CEO'nun yazdığı "baz ad başına tek `unitur`" kontrolü Kıbrıs Amerikan'ı yakalayamıyor — kurumun İKİ yazımı da yanlış etiketli olduğu için ortada çelişki yok, kontrol 100 satırın yalnız 58'ini koruyor. Ajan 6 satırlık ikinci kontrol ekledi: *DEVLET etiketli kurumun en az bir programı Türkiye ilinde olmalı*. Dördünü de sıfır yanlış pozitifle yakalıyor.
Yeni bulgular (bu geceye alınmadı): `programs_arsiv`'de aynı yanlış etiket sürüyor (kullanıcıya yansımıyor, `src/` tarafında arşivi okuyan SQL yok) · `data/yokatlas.db-shm`/`-wal` git'te izleniyor, `git status`'ü kendiliğinden kirletiyor.
Düzeltme: CEO dosyasında geri dönüş etiketi `veri-2026-son` yazıyor ama git'te yok — **doğrusu `veri-2025-son`**.
## Tur 4 (00:45) — entegrasyon
`gece/0922-entegrasyon` = main(9bd448b) + P1 + P4 + P2 + P3. Tek çakışma öngörüldüğü yerdeydi (`scripts/veri-kalite.ts`, iki saf ekleme aynı noktada) → ikisi de tutuldu, merge commit 9e1506d.
**Birleşik doğrulama (temiz worktree'de, AGENTS.md gereği):**
- `next typegen` + `tsc --noEmit` + `eslint` → **temiz**
- `pnpm veri-kalite --yil 2026` → **0 ZORUNLU kaldı, 3 uyarı** (üçü de önceden vardı). P2'nin iki kontrolü ve URAP'ın beş kontrolü birlikte geçiyor.
- `pnpm build` → **başarılı** (229 üniversite + 490+ sayfalama yolu prerender)
- Üretilen HTML denetimi (orkestratör): Boğaziçi → kart `18 / 198` + `2025-2026`, atıf linki `rel="noopener"`, **`nofollow` yok** (izin şartı karşılanıyor). Doğu Akdeniz (URAP dışı) → "Tür" kartı yerinde, açıklama cümlesi var, link yok (sayı yoksa atıf da gerekmiyor — doğru).
**P3'ün yan etkisi (Bilal'e soruldu, düzeltilmedi):** "Tür" kartı artık yalnız URAP dışındaki 31 kurumda göründüğü için `trBaslikDuzeni`'nin "Kktc" / "Yurtdisi Kamu" yazımı çok daha görünür hâle geldi. Önceden de böyleydi ama çoğunlukta "Devlet"/"Vakıf" yazdığı için göze batmıyordu. Tek satırlık etiket düzeltmesi; CEO'nun onay listesinde olmadığı için **bilerek yapılmadı**.
## Tur 5 (00:50) — bağımsız denetimler
### `guvenlik-uyum` ✔ → `11-guvenlik-denetimi.md`
Bu geceki değişikliklerde **kritik/yüksek bulgu yok.**
- `?kaynak=` allowlist kapalı (`KAYNAKLAR.find(k => k === ham) ?? "diger"`), serbest metin sızamıyor; ham değer sessionStorage anahtarına bile girmiyor; `kaynak` ödeme akışına/siparişe/iyzico'ya taşınmıyor.
- Kredi, sipariş, yetki kodunda **sıfır** değişiklik (diff boş).
- URAP: sayı ve atıf linki aynı `ilkSayfa` koşuluna bağlı → "sayı var, link yok" sayfası üretilemiyor. OG/metadata/JSON-LD URAP'a dokunmuyor.
**Geceden bağımsız, önceden var olan bulgu (orta) — Bilal'e sorulacak:** `src/lib/analitik.ts:10-12` yorumu "ham başarı sıralaması analitiğe gönderilmez" diyor ama Rybbit'in otomatik sayfa görüntülemesi ham query string'i saklıyor: panelde `?sira=14000&tur=say`, `?sira=581000&tur=ea&sihirbaz=1` satırları duruyor (doğrulandı). Kullanıcı özelliklerinde ad/e-posta olduğu için tekil öğrenciye bağlanabilir. Dün `gece/p2-olcum` dalının tepesindeki `[Bilal]` commit'i (Rybbit'e e-posta/isim gönderimini kaldırır) bu riskin diğer yarısına dokunuyordu — ikisi birlikte değerlendirilmeli.
### `urun-yoneticisi` ✔ — `docs/ekip/BACKLOG.md` güncellendi
14 yeni madde, 4 madde durum değişikliği, 3 madde kapandı. #8 (üniversite zenginleştirme) bölündü: URAP parçası #8a `dalda`, kalan 7 gösterge L→~18 saat. #10 `kategoriBul` ile birleştirildi. Bilal kararı bekleyen iki iş kabul kriteriyle hazır: #26 Öncelikler'in kalkması (kabul kriterine `/meraklisina` şema senkronu eklendi — AGENTS.md), #27 listenin paketsize ücretsiz olması. Reddedilenler §4'te kalıcı listelendi ki sonraki tur geri sokmasın.
Güvenlik bulgusunu havale edilmediği için backlog'a yazmadı (doğru davranış) — orkestratör sabah özetine doğrudan Bilal'in sorusu olarak koyuyor.
### `cto` (bağımsız kod denetimi) ✔ → `12-kod-denetimi.md`
**Hüküm: incelemeye çıkabilir — iki tek satırlık düzeltmeyle.** Kritik yok.
- **Y1 (yüksek):** P4'ün tek amacı olan ölçüm yanlış kurulmuş. `adim:1` oturum başına bir kez (`olayBirKez`), `adim:2` her ileri geçişte → payda ile pay farklı birimde, panelde %200 geçiş oranı çıkabilir. Kodun kendi yazılı kuralı bunu yasaklıyor (`analitik.ts:23`). **CEO'nun P4 kabul kriteri yanlıştı** — kriter düzeltildi.
- **O3 (orta):** P2+P3 birleşince `trBaslikDuzeni` tr-TR küçültmesiyle "YURTDISI KAMU" → **"Yurtdısı Kamu"**. Dün "Devlet" yazan 6 sayfa bugün bozuk kelime gösteriyor. Tek başına ne P2 ne P3 üretirdi.
- **O1:** P2'nin commit mesajındaki "170 → 166" yanlış; doğrusu **132 → 129** (170/166 ham ad sayısı, slug değil). Davranış doğru, kanıt rakamı yanlış.
- **O4:** URAP takası 198 sayfadan devlet/vakıf bilgisini tamamen sildi. Tasarımcının "zaten özet paragrafta var" gerekçesi **yanlış** — orkestratör doğruladı: Boğaziçi sayfasında "Devlet" 0 kez, Koç'ta "Vakıf" 0 kez (her yazımda). Bilal'e 1 numaralı soru olarak gitti.
- Temiz çıkanlar: veri farkı bağımsız doğrulandı (45 kolon ATTACH ile kıyaslandı, değişen yalnız `unitur` 100 + `il` 26) · P2+P3 birleşik boş durum doğru · `olayBirKez` SSR/gizli sekme/storage kapalıda patlamıyor · P1 mobil iddiası doğru · atıf şartı 229 sayfada delik yok.
## Tur 6 (01:05) — denetim düzeltmeleri ✔ → `13-denetim-duzeltmeleri.md`
Y1 `gece/0922-olcum` @ 58f4dc2'de (`olayBirKez` → `olay`, O2 seri kırılması notu eklendi), O3 `gece/0922-urap` @ 0e689e6'da (`UNITUR_ETIKET` haritası; `slug.ts`'e DOKUNULMADI — il adlarında da kullanılıyor).
Entegrasyon tazelendi → `gece/0922-entegrasyon` @ 74f7aa1. **typegen + tsc + lint + build dördü de temiz.** HTML: "Kktc" 0 sayfa, "Yurtdısı" 0 sayfa; `>Tür</dt>` 31 + `>URAP Türkiye</dt>` 198 = 229, delik yok.
Dürüstlük notu (ajanın kendisi bildirdi): `/bolum/*` rozetlerinde aynı bozuk etiketler duruyor — **gerileme değil**, `main`'de de vardı; şartname o dosyayı vermedi, backlog'a gitti.
## Tur 7 (01:20) — manşet bulgunun testi ✔ → `14-analitik-ters-nedensellik.md`
`analitik` **kendi §1 bulgusunu çürüttü.** Net detayını açanların %60'ı siteye yeni girmiş ve bu grup %1,43 ile sıra giriyor (taban %3,21'in ALTINDA); %9,4'ün tamamı derin gezinen 46 oturumdan geliyor. Ayrıca hem açıp hem sıra giren 14 oturumun **9'unda sıra girişi detaydan ÖNCE**. İki bağımsız test aynı yönde → **korelasyon**. CEO'nun reddi doğruydu; "net verisini öne çekersek dönüşüm 3 katına" gerekçesi düştü ve bir daha kullanılmayacak. P1 ayakta kalır (nedensellik iddiasına dayanmıyor).
## Kapanış (01:25)
`SABAH-OZETI.md` + `sabah-ozeti-sesli.m4a` (6 dk 37 sn, Türkçe) yazıldı. `main` 9bd448b'de, dokunulmadı. Bilal'in commit'lenmemiş dosyaları yerinde. Nöbetçi zamanlayıcı silindi, `caffeinate` kapatıldı.

View File

@@ -0,0 +1,268 @@
# 01 — Analitik: "Nerede boğuluyorlar?" (Rybbit, site_id=1)
Hazırlayan: Analitik ajanı · 2026-09-22 gece vardiyası · Europe/Istanbul
Yalnızca okuma araçları (`list_sites`, `get_query_schema`, `run_query` SELECT). Rybbit'te hiçbir şey oluşturulmadı/değiştirilmedi. Kod yalnız okundu.
**Pencereler**
- **TT (temiz taban)** = 18 Ağu 00:00 → 21 Eyl 12:24 · iç oturumlar ve yurt dışı/veri merkezi oturumları çıkarılmış → **801 oturum**.
- **YS (yayın sonrası)** = 21 Eyl 12:24 → 22 Eyl 19:56 (sorgu anı) · yeni olayların ilk düştüğü dakikadan itibaren → **18 oturum**.
---
## Yönetici özeti (5 madde)
1. **"Bilgi boğması" ölçülebilir ve en ağır yeri rehber yazıları.** Mobilde rehber yazısına inen 71 oturumun 61'i (%85,9; GA 76–92) tek bir vuruşla, hiçbir tıklama/olay üretmeden çıkıyor; 75. yüzdelikte bile ikinci bir iz yok. Aynı ölçü üniversite sayfasında %57,8, bölüm sayfasında %65,7. Rehber sayfası bugün bir çıkmaz sokak: çıkan 84 rehber oturumunun 82'si girdiği sayfadan çıkıyor.
2. **Akışa giren tek davranış "programın detayını açmak".** Net detayını hiç açmayan 685 oturumun %3,2'si (GA 2,1–4,8) sıralamasını giriyor; bir kez açanların %9,4'ü (GA 4,8–17,5), iki+ açanların %19,4'ü. Aralıklar ayrışıyor, yön güvenilir. Ama oturumların **%85,5'i hiç açmıyor** — yani sayfa insanı bilgiyle boğuyor değil, işe yarayan tek bilgiyi bir tıklamanın arkasına saklıyor.
3. **Sihirbazda gereksiz olan adım 3'tür.** Sihirbazı tamamlayan 29 gerçek oturumun 20'si (%69; GA 51–83) hiç "öncelik" seçmiyor, 13'ü (%45) üniversite tipine "farketmez" diyor, 8'i (%28) hiç il seçmiyor. 18'i tek bir alan seçiyor. Adım 2→3 geçişi %96,9 — kimse adımda takılmıyor, adımlar **boş geçiliyor**. Karar verdiren tek cevap 1. adım (alan) + sıralama.
4. **21 Eylül yayınının etkisi bu gece ölçülemez, n=18.** Yayından bu yana gerçek kullanıcıda: 1 `program_eklendi` (tek oturum, masaüstü, `yol: "dogrudan"` — anında ekleme yolu çalışıyor), 2 `kapi_acildi`, **0** `sira_girildi`, **0** `/sonuc`. Üstelik bu 18 oturumun en az 6'sı veri merkezi/bot ya da yayın dakikasında test. Dün konulan eşik geçerli: ≥37 + oturumu birikmeden oran okunmayacak → en erken **2 Kasım 2026**.
5. **İç trafik artık KPI'yı değil, YAYIN SONRASI ölçümü kirletiyor.** TT'de iç pay %5,6 (52/932) ve filtrelenebiliyor. YS'de ise iç trafik gerçek trafiği **ezmiş**: 21–22 Eylül'de 42 iç oturum / 191 sayfa görüntüleme / 146 olay'a karşılık 18 gerçek oturum. `odeme_baslatildi`nin YS'deki 25 olayının 25'i, `giris_basarili`nin 9'unun 9'u iç. Ödeme ve giriş hunisi hâlâ **sıfır gerçek veri** üretiyor.
---
## Veri güvenilirliği — önce bunu oku
**İç/kirli trafik nasıl arındırıldı (üç katman).**
| Katman | Tanım | TT'de düşen | Kalan |
|---|---|---|---|
| Ham | 18 Ağu → 21 Eyl 12:24, tüm oturumlar | — | 932 |
| 1. İç hesap/cihaz | Herhangi bir zamanda `odeme_baslatildi`/`odeme_tamamlandi` atmış cihazlar + o cihazlarda görülen tanımlı hesaplar → bu kimliklerin **tüm** oturumları | 52 (%5,6) | 880 |
| 2. Yurt dışı/veri merkezi | `country != 'TR'` — 79 oturumun 48'i tek vuruş, medyan süre 0 sn, yalnız 6'sı herhangi bir olay attı | 79 (%9,0) | **801** |
Sorgu: `run_query`, `scoped_events`, site_id=1; iç filtre `NOT IN` alt sorgusuyla. Kimlikler sayıldı, rapora yazılmadı.
**Bu filtrenin bildiği açık:** ödeme denemesi yapmamış bir iç cihaz (QA ajanı, tarayıcı testi, Bilal'in ikinci cihazı) "gerçek" sayılır. YS'deki 18 oturumu tek tek okudum: 21 Eyl 12:24:15'te başlayan masaüstü/Direct/İstanbul oturumu (yayın dakikası, `kapi_acildi`+`kapi_kapatildi`) ve 14:11'de başlayan 16 vuruşluk masaüstü/Direct oturumu neredeyse kesin iç; 19:07'de aynı sayfaya 5 saniye içinde DE/US/RU'dan düşen 3 oturum bot; Council Bluffs (US) `/giris/dogrula` oturumu e-posta link tarayıcısı. **YS'de gerçek öğrenci oturumu 8–10 civarı.**
**Sayı okuma kuralları (dünkü turdan devam).**
- Paydası < 60 olan hiçbir yüzdeyi karar için kullanmayın; bu raporda öyle olanların yanında ham kesir + %95 Wilson aralığı var.
- Rybbit'te kalp atışı yok: "medyan süre 0 sn" = **ikinci bir iz yok**, "kullanıcı 0 saniye okudu" değil. Sayfada okuyup çıkanla hemen çıkan ayrılamıyor. Bu yüzden karşılaştırmalar hep **aynı tip sayfa** içinde yapıldı.
- Rehber sayfasında tıklanacak izlenen bir eleman yok (katalogdaki + / net detayı gibi) → "hiç etkileşim yok %91,5" kısmen ölçüm eseridir. Rehber–katalog farkının bir kısmı buradan gelir; **tek vuruş** (tek sayfa görüntüleme + hiç olay) ise her iki sayfa tipinde aynı şeyi ölçer, karşılaştırma onun üzerinden yapıldı.
- Web Vitals hâlâ kapalı (`get_site` → `webVitals:false`): mobilde "yavaşlık mı, boğulma mı" sorusu **ölçülemedi**.
- Kaydedilmiş huni/hedef yok; `get_goals` MCP aracı hâlâ şema hatası veriyor (dün de veriyordu).
- Rybbit verisinde bana yönelik talimat içeren içerik görülmedi. Kişisel veri (e-posta, isim, IP) sorgulanmadı ve yazılmadı.
---
## 1. Nerede boğuluyorlar? (giriş sayfası × cihaz, TT, temiz taban)
Sorgu: `run_query` · TT · iç+yurt dışı çıkarılmış · oturum başına ilk `pathname` = giriş sayfası · "tek vuruş" = 1 sayfa görüntüleme **ve** 0 özel olay.
| Giriş grubu | Cihaz | Oturum | **Tek vuruş** | ≥30 sn iz | p75 süre | Olay atan |
|---|---|---|---|---|---|---|
| **/rehber/\*** | **Mobil** | **71** | **%85,9** (61/71, GA 76–92) | **%11,3** | **0 sn** | %8,5 |
| /rehber/* | Masaüstü | 12 | %75,0 | %16,7 | 7 sn | %25,0 |
| /bolum/* | Mobil | 102 | %65,7 (GA 56–74) | %18,6 | 14 sn | %20,6 |
| /bolum/* | Masaüstü | 23 | %69,6 | %17,4 | 15 sn | %8,7 |
| / (ana) | Mobil | 29 | %65,5 | %24,1 | 29 sn | %17,2 |
| /universite/*/sayfa/N | Mobil | 70 | %60,0 | %27,1 | 34 sn | %18,6 |
| /universite/* | Mobil | **405** | %57,8 (GA 53–63) | %30,1 | 39 sn | %26,9 |
| /universite/* | Masaüstü | 55 | %60,0 | %27,3 | 38 sn | %12,7 |
| / (ana) | Masaüstü | 23 | %56,5 | %43,5 | 191 sn | %34,8 |
**Okuması:**
- **/rehber mobil en kötü yüzey.** Tek vuruş %85,9 ve ≥30 sn iz bırakan yalnız 8 oturum. Yazı okunuyor olabilir (kalp atışı yok, bilemiyoruz) ama **hiçbir sonraki adıma bağlanmıyor**: çıkış analizi (TT) rehberden çıkan 84 oturumun 82'sinin (%97,6) girdiği rehber sayfasından çıktığını gösteriyor. Rehber bugün trafiği alıp hiçbir yere aktarmayan kapalı bir oda.
- **Sayfa bazında en kötü tekil sayfa:** `/rehber/yerlesemedim-ne-yapmaliyim` — 18 oturum, tek vuruş **%94,4**, ≥30 sn iz bırakan **0**. Yanında `/universite/mimar-sinan-guzel-sanatlar-universitesi` (14 oturum, %78,6, ≥30 sn %7,1) ve `/rehber/siralama-sartlari-2026` (16, %81,2).
- **Ana sayfa mobilde katalog sayfasından kötü.** Tek vuruş %65,5 (mobil) — üniversite sayfasının (%57,8) üstünde; masaüstünde ise tam tersi (%56,5, p75 191 sn). Yani hero + sıralama formu masaüstünde tutuyor, mobilde tutmuyor. n=29 mobil → **yön gösterir, kesin değil**; ama ilk ekranda mobil için ayrı bir düzen gerekçesi bu rakamdır.
- **/bolum mobil (n=102) üniversiteden 8 puan kötü.** Dün kodda tespit edilmişti: `/bolum/[slug]` detayında `CtaSiraForm` **hiç yok** (`bolum-icerik.tsx`; üniversite tarafında `universite-icerik.tsx:300-305`'te var ama tablonun ve sayfalamanın altında). 102 mobil oturumun içinde köprü yok.
### En güçlü tekil sinyal: net detayını açmak
Sorgu: `run_query` · TT · TR · `netler_goruntulendi` (kod: `src/features/katalog/components/program-netleri.tsx:86-90` — akordeon **açıldığında** atılıyor, adı doğru ölçüyor).
| Oturumda net açılışı | Oturum | Pay | Ort. sayfa | Sıralamasını girdi |
|---|---|---|---|---|
| 0 | **685** | %85,5 | 1,7 | 22 → **%3,2** (GA 2,1–4,8) |
| 1 | 85 | %10,6 | 3,6 | 8 → %9,4 (GA 4,8–17,5) |
| 2–3 | 17 | %2,1 | 3,3 | 3 → %17,6 |
| 4+ | 14 | %1,7 | 9,4 | 3 → %21,4 |
0 ile 1 arasındaki fark güven aralıkları ayrışacak kadar büyük (n=685 vs 85). **Karar verdiren cümle:** katalog sayfasında insanı akışa sokan şey daha fazla metin değil, o programın detayının görünür olması. Bugün o detay %85,5 için hiç açılmıyor.
---
## 2. Huni (TT + YS, mobil/masaüstü)
Sorgu: `run_query` · 18 Ağu → şimdi · iç oturumlar çıkarılmış · oturum içi bayraklar (sıralı huni değil; Google OAuth dönüşü oturumu böldüğü için sıralı huni giriş adımını eksik sayar).
| Adım | Toplam | Mobil | Masaüstü |
|---|---|---|---|
| Gerçek oturum | 899 | 724 | 175 |
| `sira_girildi` | 36 | 26 | 10 |
| `sihirbaz_adim{2}` | 32 | 22 | 10 |
| `sihirbaz_adim{3}` | 31 | 22 | 9 |
| `sihirbaz_tamamlandi` | **29** (36'nın %80,6; GA 65–90) | 20 | 9 |
| /sonuc gördü | 30 | 20 | 10 |
| /giris gördü | 32 | 14 | 18 |
| `giris_denendi` | 8 | 5 | 3 |
| /listem gördü | 8 | 6 | 2 |
| `liste_olusturuldu` | **3** (29'un %10,3; GA 3,6–26) | 2 | 1 |
| `kilit_goruntulendi` | 3 | 2 | 1 |
| /paket gördü | 3 | 0 | 3 |
| `odeme_baslatildi` | **0** | 0 | 0 |
**Giriş duvarı (TT, TR, /giris gören 19 oturum):** 8'i giriş denedi (%42,1; GA 23–64), 8'i tanımlı kullanıcı oldu, 5'i /listem'e ulaştı, **7'si (%36,8) /giris sayfasında öldü**. Masaüstünde /giris'te medyan 110 sn geçiriliyor, mobilde 0 sn (tek vuruş).
**/sonuc'ta ne oluyor (TT, 30 gerçek oturum):** medyan **1** sayfa görüntüleme, medyan **37 sn** (mobil 32, masaüstü 78). 10 oturum net açtı, 10 oturum program ekledi, 8 oturum hazır paneli gördü, 9'u (%30; GA 17–48) /giris'e gitti. — Dünkü "143 oturumda 1.602 görüntüleme" tespiti **iç trafik kaynaklıymış**: gerçek kullanıcıda /sonuc parametre şişmesi yok (medyan 1 pv). Bu maddeyi CTO listesinden düşürün.
### Yayın sonrası (YS: 21 Eyl 12:24 → 22 Eyl 19:56, gerçek oturum = 18)
| Ölçüt | Gerçek | İç |
|---|---|---|
| Oturum | 18 | 42 |
| Katalog sayfası gördü | 13 | — |
| `cta_form_goruntulendi` | **7** (13'ün %53,8; GA 29–77) | 0 |
| `program_eklendi` | **1** oturum / 2 olay · hepsi `yol: "dogrudan"` | 3 oturum |
| `kapi_acildi` | 2 oturum (tetik: `arti` 1, `duzenle` 1) | 3 oturum |
| `kapi_kapatildi` | 2 oturum (adım: `giris` 1, `sira` 1) | 3 oturum |
| `sira_girildi` | **0** | 3 |
| /sonuc | **0** | 5 |
| `odeme_baslatildi` | **0** | 9 oturum / 25 olay |
| `giris_basarili` | **0** | 8 oturum / 9 olay (tek cihaz) |
**"+ anında ekleme tuttu mu?" → Ölçülemez.** Kanıt yönü olumlu ama tek gözlem: yayından beri atılan **her** `program_eklendi` (gerçek + iç, 9 olay) `yol: "dogrudan"` — yani anında ekleme yolu canlıda çalışıyor ve **hiç kimse artık programı kapıdan eklemiyor** (`yol: "kapi"` = 0). Ne var ki gerçek kullanıcıda bu tek bir masaüstü oturumu. Mobilde (trafiğin %80'i) yayından beri **0** ekleme var. Karar için gereken: ≥37 + oturumu → bugünkü hızda (haftada ~8–9) **en erken 2 Kasım 2026** (dün hesaplanan eşik aynen geçerli).
**Tek somut YS kazanımı:** `cta_form_goruntulendi` canlıya çıktı ve dünkü en zayıf varsayımı (formu katalog oturumlarının ~%33'ü görüyor) gerçek sayıyla değiştirmeye başladı: **7/13 = %54** (GA 29–77). n=13 → henüz varsayımı güncellemeyin, ama ilk işaret "form görülüyor, tıklanmıyor" yönünde: aynı dönemde form kaynaklı sıra girişi 0.
---
## 3. Sihirbaz adım adım — "adım sayısı azaltılabilir mi?"
Kod: `src/features/sihirbaz/components/sihirbaz-adimlar.tsx`. Adım 0 = alan (zorunlu, `adimGecerli = adim === 0 ? kategoriler.length > 0 : true`, satır 198), adım 1 = il, adım 2 = devlet/vakıf + öncelikler. **Adımlar 1 ve 2 boş geçilebilir** — "Devam" hiçbir seçim istemiyor.
**Ölçüm deliği (önce bunu bilin):** `sihirbaz_adim` yalnız **ileri geçişte** atılıyor (satır 205: `if (yeniAdim > adim) olay("sihirbaz_adim", { adim: yeniAdim + 1 })`). Adım 1 hiç atılmıyor — modal açıldığında kullanıcı zaten 1. adımdadır. Bu yüzden **"1. adımda bırakanlar" doğrudan ölçülemiyor**; paydası `sira_girildi`den türetildi.
| Adım | Oturum (TT, gerçek) | Önceki adıma göre |
|---|---|---|
| `sira_girildi` (kapı/hero/cta/düzenle) | 36 | — |
| Adım 2 (il) | 32 | %89 |
| Adım 3 (tip/öncelik) | 31 | %96,9 (GA 84–99) |
| `sihirbaz_tamamlandi` | 29 | %94 |
**Sihirbazın kendisi kopmuyor. Sorun adımların boş olması.** Tamamlayan 29 oturumun seçimleri (`sihirbaz_tamamlandi` özelliklerinden):
| Seçim | Sonuç | %95 GA |
|---|---|---|
| Tek alan seçti | 18/29 (%62,1) | 44–77 |
| İl seçmedi | 8/29 (%27,6) | 15–46 |
| İl medyanı | 2 | — |
| Üni tipi "farketmez" | 13/29 (%44,8) | 28–63 |
| **Öncelik seçmedi** | **20/29 (%69,0)** | **51–83** |
| İl + öncelik ikisi de boş | 5/29 | — |
| Üçü de boş (il, öncelik, tip) | 4/29 | — |
**Veriye dayalı cevap: evet, azaltılabilir — hedef 3. adım.** "Öncelik" seçicisini tamamlayanların üçte ikisi hiç kullanmıyor (GA'nın alt sınırı bile %51). Üniversite tipi yarıya yakınında "farketmez". İl ise kullanılıyor (%72 en az bir il seçiyor, medyan 2) — **il adımı kalsın**. n=29 küçük, ama "çoğunluk önceliği boş bırakıyor" ifadesi aralıkla birlikte savunulabilir; "tam olarak %69'u" ifadesi savunulamaz.
---
## 4. Liste / maskelenmiş rapor
**Bu bölümün cevabı: gerçek kullanıcı verisiyle ölçülemez.** TT'de `liste_olusturuldu` **3** oturum, `kilit_goruntulendi` **3** oturum, /paket **3** oturum, `odeme_baslatildi` **0**. Tüm zamanlarda gerçek kullanıcıda kilidi gören 5 oturum var; oran yazmak anlamsız, ham davranışı yazıyorum (`run_query`, kilit olayından sonraki ilk 4 adım):
| Kilitten sonra ne yaptı | Oturum |
|---|---|
| /listem'e döndü, danışmana soru sordu, /listem'de kaldı | 2 |
| /rehber'e gitti → ana sayfa → **/paket** | 1 |
| Başka bir rehber yazısına + /sonuc'a gitti (kilidi ikinci kez gördü) | 1 |
| Katalog sayfalarına döndü, program eklemeye devam etti | 1 |
| **Ödeme başlattı** | **0** |
Yani kilidi gören 5 gerçek kullanıcıdan 1'i /paket'e ulaştı, 2'si maskeli satırı görünce **yapay zekâ danışmanına soru sordu** (ürünün ücretli değerinin ilk sorulduğu yer orası). Bu bir sinyal, oran değil.
**"24 satırın yalnız ilk 3'ünün yorumu açık" ekranı hakkında ölçemediğimiz şey:** `tadimlik_goruntulendi` hâlâ **0 kayıt**. Bunun sebebi bu kez hook hatası **değil** — dünkü düzeltme (`src/components/use-gorunum-olayi.ts`, callback ref'e geçirildi) canlıda ve kardeş olay `kaydet_banner_goruntulendi` yayından beri 6 kez düştü. Kök neden: `TadimlikBolumu` yalnız **girişsiz** kullanıcıya ve yalnız `/sonuc`'ta render ediliyor (`src/features/rapor/components/tadimlik-bolumu.tsx:18-21` → `if (session) return null`; `src/app/sonuc/page.tsx:118`) ve yayından bu yana **gerçek kullanıcıda 0 /sonuc görüntülemesi** var. Yani düzeltme **doğrulanmamış**, başarısız değil. İlk anonim /sonuc oturumunda doğrulanmalı.
**Kod okumasından bir tasarım gözlemi (ölçüm değil, işaretliyorum):** `/sonuc` sırası şu: Türkiye haritası → ham program tablosu → *sonra* tadımlık satırı → *sonra* sihirbaz CTA → yasal metin (`src/app/sonuc/page.tsx:96-134`). Ürünün asıl vaadini gösteren tek şey (yapay zekâ yorumlu örnek satır) sayfanın ham tablosunun **altında**. Gerçek kullanıcı /sonuc'ta medyan 37 sn kalıyor ve medyan 1 sayfa görüntülüyor — tabloyu geçip aşağıya inecek bütçe orada görünmüyor.
---
## 5. Ölçüm delikleri (en fazla 5)
Kodda tanımlı ama Rybbit'te **hiç kaydı olmayan** olaylar: `tadimlik_goruntulendi`, `sira_form_hata`, `liste_uretim_hata`, `giris_hata`, `liste_guncellendi`, `liste_revize` (`get_event_names` karşılığı `run_query` · tüm zamanlar · `type='custom_event'`).
| # | Eksik/bozuk ölçüm | "Bu olmazsa şu soruyu asla cevaplayamayız" | Kanıt (dosya:satır) |
|---|---|---|---|
| 1 | `sihirbaz_adim` 1. adımı hiç atmıyor | *Sihirbazı açan kaç kişi ilk ekranı (alan seçimi) görüp hiç ilerlemeden bıraktı?* Bugün payda `sira_girildi`den türetiliyor; kapıdan açılan sihirbazda o bile yok. | `sihirbaz-adimlar.tsx:205` — `if (yeniAdim > adim)` |
| 2 | `/paket` linklerinin %56'sında `?kaynak=` yok | *İnsanı ödeme sayfasına getiren yüzey hangisi?* YS'deki 16 `paket_goruntulendi`nin 10'u `kaynak: "diger"`. Kaynaksız linkler: `page.tsx:543,573`, `kosullar/page.tsx:55`, `tercih-degisti-modali.tsx:283,335`, `sohbet-client.tsx:351,538,546`, `odeme-kromu.tsx:45`, `odeme-sonuc-karti.tsx:141`. Doğru olanlar: `listem-govde.tsx:288,369` (`kilit`), `liste-uretici.tsx:282` (`kredi_bitti`), `user-nav.tsx:64` (`nav`). | `paket-gorunum-olayi.tsx:14-21` |
| 3 | Rehber yazısında hiçbir etkileşim ölçülmüyor | *Yazıyı okuyan kişi okudu mu, yoksa ilk ekranda mı kaçtı?* Mobil rehber oturumlarının %85,9'u tek vuruş; okuma mı terk mi olduğu **ölçülemiyor**. Gereken: yazı içi kaydırma kilometre taşı (ör. %50 / sonu) veya yazı içi CTA tıklaması. | — (kodda böyle bir olay yok) |
| 4 | `tadimlik_goruntulendi` doğrulanmamış | *Girişsiz kullanıcı ürünün vaadini gerçekten gördü mü?* Kilitten önceki tek değer kanıtı bu. Hook düzeltildi ama yayından beri hiç anonim /sonuc yok. | `tadimlik-bolumu.tsx:18-21`, `sonuc/page.tsx:118` |
| 5 | `giris_hata` / `liste_uretim_hata` hiç düşmedi | *Girişte ve liste üretiminde başarısızlık mı var, yoksa oraya kimse mi gelmiyor?* Bugün ikisi ayırt edilemiyor: /giris'te ölen 7 oturumun hata mı aldığı, vazgeçtiği mi bilinmiyor. | `src/lib/analitik.ts:47-48` (tip var, çağrı yok/erişilmedi) |
---
## 6. İç trafik kirliliği — bugünkü durum
| Pencere | Toplam oturum | İç oturum | Pay | Etkisi |
|---|---|---|---|---|
| TT (18 Ağu → 21 Eyl 12:24) | 932 | 52 | %5,6 | KPI'yı hafif şişiriyor, filtrelenebiliyor |
| **YS (21–22 Eyl)** | **60** | **42** | **%70** | **Yayın sonrası ölçümü kullanılamaz hale getiriyor** |
21–22 Eylül'de iç trafik 191 sayfa görüntüleme ve 146 özel olay üretti; gerçek trafik 47 sayfa görüntüleme ve 33 olay. Panelde filtresiz bakan biri "`odeme_baslatildi` 25 olay, `giris_basarili` 9" görür — **hepsi iç**. Gece vardiyasında ekip/QA ajanları siteyi gezdikçe bu oran artacak.
**Arındırma yöntemi (bu raporda uygulanan):** yukarıdaki iki katmanlı `NOT IN` filtresi + YS için 18 oturumun tek tek okunması. **Kalıcı çözüm Rybbit panelinden yapılmalı** (ayar değişikliği bu vardiyada yasak): ekip IP'lerinin dışlanması ve/veya ekip tarayıcılarında Rybbit opt-out bayrağı. Ek olarak bot trafiği için `country != 'TR'` bir vekil ölçüt; Rybbit `blockBots` açık olmasına rağmen TT'de 79 oturum (%9) sızmış.
---
## Öncelik tablosu
| # | Bulgu | Önerilen iş (backlog önerisi) | Beklenen etki | Kesinlik |
|---|---|---|---|---|
| 1 | Net detayını açan oturum 3× daha çok sıra giriyor; %85,5 hiç açmıyor | Katalog tablosunda "karar veren" satır bilgisini (taban sıralama + risk etiketi) tıklamadan görünür yap; net detayı ikincil kalsın | Yüksek — huniye giren tek davranışı çoğaltır | **Yüksek** (n=685 vs 85, GA'lar ayrışıyor) |
| 2 | /rehber mobil %85,9 tek vuruş, çıkanların %97,6'sı aynı sayfadan çıkıyor | Rehber yazısının ilk ekranına tek soruluk sıralama köprüsü + yazı içi kaydırma olayı | Yüksek (trafiğin %10'u, bugün sıfır aktarıyor) | Orta — terk mi okuma mı ayırt edilemiyor (ölçüm yok) |
| 3 | Sihirbaz 3. adımı boş geçiliyor (öncelik 20/29, tip 13/29) | 3. adımı kaldır ya da /sonuc'a ertele; sihirbaz = alan + il | Orta-yüksek — akış 3 ekrandan 2'ye iner | Orta (n=29; "çoğunluk" savunulabilir, kesin oran değil) |
| 4 | /bolum mobil (n=102) üniversiteden 8 puan kötü, sayfada köprü yok | `/bolum/[slug]` detayına üniversite sayfasındaki köprüyü ekle (ve ikisinde de tablonun **üstüne** al) | Orta | Orta |
| 5 | `/paket` linklerinin %56'sında `?kaynak=` yok | 10 linke `?kaynak=` ekle (dosya:satır listesi §5'te) | Düşük iş, ölçüm için şart | Yüksek (koddan doğrulandı) |
| 6 | Yayın sonrası iç trafik %70 | Rybbit'te iç trafik filtresi (panel ayarı) | Yüksek — aksi halde 2 Kasım'daki okuma da kirli olur | Yüksek |
| 7 | `/sonuc` parametre şişmesi | **Düşürün** — gerçek kullanıcıda yok (medyan 1 pv); dünkü CTO-7 maddesi iç trafik eseriydi | — | Yüksek |
---
## Tasarımcıya — bu gece tam olarak şu ekranlara bak
1. **Katalog program tablosu satırı (`/universite/[slug]`, `/bolum/[slug]`).** Net detayını **hiç açmayan 685 oturumun %3,2'si** sıra giriyor; bir kez açanın %9,4'ü. Tasarım sorusu: o akordeonun arkasındaki hangi tek bilgi (taban sıralama + risk etiketi) tıklamasız satıra çıkarsa %85,5'lik kitle de karar verebilir? Daha fazla bilgi değil — **doğru bilginin bir tıklama öne alınması.**
2. **Rehber yazısının ilk ekranı, mobil — özellikle `/rehber/yerlesemedim-ne-yapmaliyim`.** 18 oturum, %94,4 tek vuruş, ≥30 sn iz bırakan **0**. Tüm rehber mobil: 71 oturum, %85,9 tek vuruş, p75 süre 0 sn. Yazıdan çıkanların %97,6'sı girdiği sayfadan çıkıyor. Burada okunacak metin değil, **bir sonraki adım** eksik.
3. **Ana sayfa mobil ilk ekranı.** Mobilde tek vuruş %65,5 / ≥30 sn %24,1 (n=29) iken masaüstünde %56,5 / %43,5 ve p75 191 sn (n=23). Aynı hero mobilde tutmuyor. n küçük → **yön gösterir, kesin değil**; ama mobil ilk ekranı masaüstünün küçültülmüşü olarak bırakmamak için yeterli.
4. **Sihirbazın 3. adımı (devlet/vakıf + öncelikler).** Tamamlayan 29 kişinin 20'si (GA %51–83) hiç öncelik seçmiyor, 13'ü tipe "farketmez" diyor. Adım 2→3 geçişi %96,9 — insanlar takılmıyor, **boş geçiyor**. Bu adımı savunacak veri yok.
5. **`/sonuc` sayfa sırası.** Gerçek kullanıcı medyan **1** sayfa görüntülüyor ve **37 sn** kalıyor (mobil 32 sn); 30 oturumdan 9'u /giris'e gidiyor. Ürünün tek vaat kanıtı (yapay zekâ yorumlu tadımlık satırı) bugün haritanın ve ham tablonun **altında** (`src/app/sonuc/page.tsx:96-134`). 37 saniyelik bütçede oraya inilmiyor.
---
## Bilal'den istenen (3 madde)
1. **Rybbit panelinden iç trafik filtresini aç** (ekip IP'leri / opt-out) — yoksa 2 Kasım'daki "+ tuttu mu" okuması da kirli çıkar. **~10 dk**
2. **Rybbit panelinden Web Vitals'ı aç** — trafiğin %80'i mobil ve "boğulma mı, yavaşlık mı" sorusu bugün ölçülemiyor. **~2 dk**
3. **21 Eylül yayınının kesin saatini teyit et** (ölçüm 21 Eyl 12:24 ve 16:13 olmak üzere iki dalga gösteriyor) — önce/sonra kesiminin doğru yerden geçmesi buna bağlı. **~5 dk**
---
## Sorgu dizini
Hepsi `mcp__rybbit__run_query`, `scoped_events`, `site_id=1`, organization_id `eZ4TIQ…`. İç filtre her sorguda aynı CTE ile yeniden kuruldu (`ic_cihaz` → `ic_hesap` → `ic_oturum`, `NOT IN`).
| Kod | Ne hesapladı |
|---|---|
| Q1 | Tüm özel olayların adet/oturum/ilk-son zaman damgası → yeni olayların canlıya çıkış dakikası (21 Eyl 12:24 ve 16:13 dalgaları; `liste_uretim_basladi` 22 Eyl 14:05) |
| Q2 | 15–22 Eyl günlük iç/gerçek oturum, sayfa görüntüleme, olay |
| Q3 | YS'de olay adı × iç/gerçek kırılımı |
| Q4 | TT giriş sayfası grubu × tek vuruş / ≥30 sn / p75 süre / etkileşim (önce filtresiz, sonra TR + cihaz kırılımlı) |
| Q5 | TT tekil giriş sayfası (≥12 oturum) tek vuruş ve süre |
| Q6 | `sihirbaz_tamamlandi` özellikleri (alan/il/tip/öncelik) oturum başına toplulaştırılmış |
| Q7 | Oturum içi huni bayrakları × cihaz (ROLLUP) |
| Q8 | `kilit_goruntulendi` sonrası ilk 4 adımın dizisi, iç/gerçek |
| Q9 | TT çıkış sayfası grubu, tek hit, giriş=çıkış eşitliği |
| Q10 | /sonuc oturumlarında sayfa görüntüleme adedi, süre, sonraki davranışlar |
| Q11 | YS'deki 18 gerçek oturumun tek tek okunması (cihaz, kanal, şehir, giriş sayfası, süre) |
| Q12 | Ülke kırılımı, yurt dışı/bot payı |
| Q13 | Haftalık gerçek TR oturum, tek vuruş, +/sıra/tamam/giriş |
| Q14 | /giris gören oturumların davranışı × cihaz |
| Q15 | `netler_goruntulendi` kovası × sıra girme |
| Q16 | YS'de `kapi_*`, `program_eklendi{yol}`, `paket_goruntulendi{kaynak}` özellik kırılımı |
Güven aralıkları yerel Python ile hesaplandı (Wilson, %95).
## Bu vardiyada yapılamayanlar
- **Yayın etkisi ölçümü** (n=18, en az 6'sı bot/iç) — 2 Kasım eşiğine kadar oran yok.
- **Web Vitals** — site ayarı kapalı, LCP/INP/CLS hakkında hiçbir şey söylenemez.
- **Rehberde okuma vs. terk ayrımı** — kaydırma/okuma olayı yok, Rybbit'te kalp atışı yok.
- **`tadimlik_goruntulendi` doğrulaması** — yayından beri anonim /sonuc trafiği sıfır.
- **Ödeme hunisi** — gerçek kullanıcıda hâlâ 0 `odeme_baslatildi`; ölçülecek bir şey yok.
- `get_goals` MCP aracı şema hatasıyla dönüyor (dünden beri aynı).

View File

@@ -0,0 +1,364 @@
# 02 — Tasarım: çıkarma turu (gece vardiyası 2026-09-22, Tur 1)
> Yöntem: yalnız kod okuması (AGENTS.md gereği tarayıcı/dev sunucusu açılmadı). Piksel yükseklikleri
> **koddan çıkarımdır**, ölçülmemiştir; "kaç ekran boyu" rakamları 390×844 varsayımıyla tahmindir ve
> öyle işaretlidir. Kontrast değerleri token'lardan **hesaplanmıştır** (hesap §7'de).
> Analitik raporu (`01-analitik.md`) bu rapor yazılırken klasörde **yoktu** → Rybbit rakamlarıyla
> eşleştirme yapılamadı; her bulgu "kural" (AGENTS.md/WCAG) ya da "varsayım" olarak işaretlendi.
> Yapay zekâ mühendisinin raporu (`04-liste-maliyet-ve-oneriler.md`) yazım sırasında geldi ve iki
> bulguyu bağımsız olarak doğruluyor — çapraz kontrol §8'de. Kod değiştirilmedi.
---
## Özet — 5 madde
1. **Akış kolay; ekranlar kalabalık.** Sihirbaz 3 adım, ödül tek sayfa — iskelet doğru. Sorun iskelette değil,
her ekranın kendi işine ek olarak bir de "ürünü anlatma" işi üstlenmesinde. Beş ekranın **dördü** tek
cümlelik "bu ekranın işi ne?" testini geçemiyor.
2. **En pahalı gürültü ilk ekranlarda.** `/sonuc`'un ilk ekranının ~%20'si, içine hiçbir şey eklenmemiş
**boş gri harita yer tutucusu** (`manuel-harita.tsx:69-80`). Üstünde her sayfada duran sezon bandı
(`site-top-banner.tsx`) şu an geri sayım bile göstermiyor — sadece "takvim açıklanınca burada başlar"
diyen bir cümle.
3. **Aynı vaat arka arkaya iki kez satılıyor.** `/sonuc`'ta girişsiz kullanıcı aynı `/giris` adresine giden
**iki büyük paneli** üst üste görüyor (`tadimlik-satiri.tsx:178` ve `sihirbaz-cagri-karti.tsx:307`).
`/listem`'de paketsiz kullanıcıya **beş ayrı** `/paket` girişi var.
4. **24'lük liste boğmuyor; kilitli 21 satırın tekrarı boğuyor.** Detaylar akordeonun arkasında — doğru.
Ama kilitli her satır tek tek açılıp **aynı satış kutusunu 21 kez** gösteriyor
(`rapor-listesi.tsx:306-323`). Tek paywall yeter.
5. **İki kural ihlali açık ve mobil kullanıcıyı vuruyor.** (a) `/sonuc` tablosunda risk **yalnız renkli nokta**
(`program-tablosu.tsx:306-314`, metin etiketi hiç yok) ve `/listem`'de etiket `sm` altında `sr-only`
(`rapor-listesi.tsx:267`) → AGENTS.md risk dili kuralı, trafiğin ~%90'ı mobil. (b) `/giris` başlığı
sonsuz döngüde yazı animasyonu ve `prefers-reduced-motion` hiç okunmuyor → WCAG 2.2.2 (A).
---
## 1. Ekran ekran: sayım ve "bu ekranın işi ne?" testi
Sayım kuralı: **bilgi bloğu** = ayrı kart/panel/tablo/bant · **CTA** = tıklanınca akışı ilerleten buton/link
(navbar hariç) · **açıklama cümlesi** = başlık dışı, okunması beklenen tam cümle · **rozet** = `SectionEyebrow`
ya da pill görünümlü etiket.
| Ekran | Blok | CTA | Açıklama cümlesi | Rozet | Tahmini boy (390px) | Tek işi var mı? |
|---|---|---|---|---|---|---|
| Ana sayfa (`app/page.tsx`) | 8 (hero, sorun, nasıl, istatistik+dürüstlük, karşılaştırma, fiyat, SSS, kapanış) | 6 (hero submit, Meraklısına, Paketi incele, +kredi, kapanış CTA, SSS içi yok) | ~28 | 6 `SectionEyebrow` + "Meraklısına" turuncu pill + 5 puan türü çipi | **~8 ekran** (koddan çıkarım) | ❌ İki iş: "sıralamanı al" + "ürünü sat". |
| Sihirbaz modal (`sihirbaz-adimlar.tsx`) | 1 panel, 3 adım | 2 (Geri/Devam) | 4 (adım başına 1, 3. adımda 2) | Adım 1'de ~10 kategori çipi, adım 2'de ≤81 il çipi, adım 3'te ~10 çip | modal, `max-h-92dvh` | ⚠️ Adım 1-2 tek iş; **adım 3'ün iki işi var** (üni tipi + öncelikler). |
| `/sonuc` (girişsiz, `hazir=1`) | 5 (boş harita, tablo, tadımlık, hazır panel, dipnot) | 4 (dilim sekmeleri sayılmadı: Daha fazla, tadımlık→giriş, hazır panel→giriş, satır içi `+`×20) | ~12 | 1 `SectionEyebrow` + 3 dilim sekmesi + satır başına Devlet/Vakıf rozeti | **~4,3 ekran** | ❌ Üç iş: "ücretsiz tabloyu göster" + "AI'ı tanıt" + "giriş yaptır". |
| `/listem` (paketsiz) | 6 (harita, başlık+aksiyon, uyarı kutuları, 24'lük liste, sohbet, paket kartı) | **5 ayrı `/paket` girişi** + Tercihlerimi düzenle + sohbet gönder | ~14 | Satır başına Devlet/Vakıf + "Pakette" kilidi ×21 | **~4,6 ekran** | ❌ İki iş: "listeni göster" + "paketi sat". |
| `/paket` | 4 (başlık bloğu, paket kartı, top-up kartı, yasal dipnot) | 2-3 (Paketi al / Giriş yap, top-up CTA'sı, İade koşulları) | ~9 | 1 `SectionEyebrow` | **~2 ekran** | ❌ İki iş: "ikna et" + "tahsil et". Buraya gelen zaten ikna olmuş. |
**Tek işi olmayan ekranlarda hangisi çıkmalı:**
- **Ana sayfa** → satış tarafı kalır (SEO/soğuk trafik oraya iniyor), ama hero ile fiyat arasındaki üç bölüm
(`Sorun`, `Nasıl çalışır` içindeki istatistik+dürüstlük kartı, `Karşılaştırma`) toplam ~4 ekran. Kesilecek
olan **"Sorun" bölümü**: üç kart da adayın zaten bildiği şeyi anlatıyor ve akışı ilerletmiyor.
- **Sihirbaz adım 3** → **"Öncelikler" çıkmalı.** Kod kendi söylüyor: "listeyi daraltmaz"
(`sihirbaz-adimlar.tsx:487-490`) ve `/meraklisina` şemasında bu adım hiç yok (`huni-semasi.tsx:18`:
"3. adım · Devlet / Vakıf"). Yani ürünün resmî belgesi ile ekran zaten uyuşmuyor.
- **`/sonuc`** → "AI'ı tanıt" ile "giriş yaptır" aynı şey; ikisinden biri gider (bkz. K3).
- **`/listem`** → "paketi sat" kalır ama **tek yüzeyde**: satır içi kilit kartı. Diğer dördü gürültü.
- **`/paket`** → "ikna et" tarafı küçülür: H1 rakip kıyası yerine ne aldığını söylemeli.
---
## 2. Beş kesin kesim
Sıra fayda/riske göre. Hepsi `[KARAR]` düzeyinde, **K5 hariç** (o ürün kararı).
### K1 — Sezon dışında üst bandı hiç çizme · **risk: düşük**
`src/components/site-top-banner.tsx:91-177` · `src/lib/sezon.ts:76` (`takvim-belirsiz` metni)
Bugün (22 Eyl 2026) `SEZON_TAKVIMI[2027] = null` → bant geri sayım göstermiyor, yerine 92 karakterlik bir
cümle yazıyor: *"2026 yerleştirme verileri yüklendi — 2027 tercih takvimi açıklanınca geri sayım burada
başlar."* 390px'te iki satıra sarıyor.
**Ne siler:** `asama === "takvim-belirsiz"` iken bandın tamamı (`return null`).
**Neyi kaybederiz:** "verimiz taze" sinyali — ama aynı bilgi ana sayfa hero'sunda (`app/page.tsx:243-254`)
ve her katalog sayfasının `VeriKaynagi` satırında zaten var, tarihiyle birlikte.
**Neden kabul edilebilir:** Aksiyonsuz, her sayfada tekrarlayan, hiçbir yere götürmeyen bir bant. Takvim
açıklandığı an kendiliğinden geri gelir (tek kaynak `sezon.ts`, ek iş yok).
**Kazanç:** Her sayfanın ilk ekranından ~70-80px + bir cümlelik okuma yükü (koddan çıkarım).
### K2 — `/sonuc`'un boş harita yer tutucusunu kaldır · **risk: düşük**
`src/features/liste/components/manuel-harita.tsx:69-80`
Liste boşken `aspect-[1050/447]` gri kutu çiziliyor: 390px'te ~152px. Sayfaya yeni gelen **herkesin**
listesi boş, yani bu kutu **her zaman** ilk ekranın içinde ve içinde "tablodan + ile ekledikçe üniversiteler
haritada belirir" yazıyor.
**Ne siler:** `liste.length === 0` dalındaki tüm blok → `return null`.
**Neyi kaybederiz:** (a) "+ ne işe yarar" ipucu, (b) ilk eklemede CLS önleyen yer rezervi.
**Neden kabul edilebilir:** (a) ipucunun yeri buton değil, `+` butonunun kendi `title`'ı ve profilsiz
eklemede çıkan toast — ikisi de zaten var (`program-ekle-butonu.tsx:105-110, 69-88`). (b) CLS bedeli
yalnız **ilk eklemede bir kez** ödenir ve harita tablonun üstünde değil altında da durabilir; bugünkü
maliyet her ziyaretçide, her oturumda.
**Kazanç:** `/sonuc` ilk ekranında tablo ~152px yukarı çıkar → ilk ekranda 5 yerine ~7 program satırı.
### K3 — `/sonuc`'ta iki giriş panelinden birini kaldır · **risk: düşük-orta**
`src/features/rapor/components/tadimlik-satiri.tsx:114-192` (panel A) ·
`src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx:287-325` (panel B)
Hero sihirbazını bitirip girişsiz gelen kullanıcı (`?hazir=1`) tabloyu geçtikten sonra **art arda iki tam
genişlik panel** görüyor; ikisinin de CTA'sı aynı `/giris` adresine gidiyor ve ikisi de aynı şeyi vadediyor:
- A: "24 satırın tamamı için giriş yap — 5 deneme kredin hazır" + "Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede"
- B: "5 deneme kredinle Yapay Zeka listeni kur — giriş yap" + **birebir aynı** mikro-kopya.
**Ne siler:** `?hazir=1` dalında B paneli (`girisBekliyor` dalı) hiç render edilmez; A paneli (tadımlık)
kalır — çünkü A **gösterir**, B yalnız **anlatır**. A zaten ürünün gerçek satır formatını (`RaporSatirDetayi`,
tek kaynak) canlı gösteriyor.
**Neyi kaybederiz:** B'deki "(üretim 3 kredi, kalan 2 kredinle danışmana soru sorarsın)" kredi açıklaması
ve `hazir_panel_goruntulendi` ölçümü.
**Neden kabul edilebilir:** Kredi açıklaması `/giris` kartında zaten tekrar ediliyor
(`giris-karti.tsx:52-66`). Ölçüm A'ya taşınır (`tadimlik_goruntulendi` zaten var).
**Uyarı:** Tadımlık havuzu boşsa `TadimlikBolumu` hiç render edilmiyor (`tadimlik-bolumu.tsx:20-21`) —
o durumda B geri gelmeli, yoksa girişsiz kullanıcı CTA'sız kalır. Yani kesim koşullu: "A varsa B yok".
### K4 — Kilitli satırların tek tek açılmasını kapat · **risk: düşük**
`src/features/rapor/components/rapor-listesi.tsx:306-323` (kilitli detay) · `:280-296` (chevron butonu)
Paketsiz kullanıcının 24 satırının 21'i kilitli. Her biri tıklanabilir, her biri açılınca **aynı** kesik
çizgili kutuyu gösteriyor: "Yapay Zeka karar desteği / Bu bölümün neden listende olduğunu ve sıralamana
özel yerleşme riskini paketle gör." Yani aynı satış cümlesi tek sayfada **21 kez**.
**Ne siler:** `analizKilitli` satırlarda chevron butonu ve satır `onClick`'i (satır artık tıklanamaz),
`:306-323` kilitli detay bloğu.
**Neyi kaybederiz:** Kilitli satırdan da "Haritada gör" kısayolu (`:334-343`).
**Neden kabul edilebilir:** Satır zaten `Lock` ikonu + "Pakette" etiketiyle durumunu söylüyor (`:256-260`);
açılınca öğrenen yeni bir şey yok. "Haritada gör" 21 satırda kaybolur ama açık 3 satırda ve haritanın
kendisinde (pin → satır köprüsü) duruyor. Paywall mesajı tek yerde kalır: satır 4'teki kilit kartı.
**Kazanç:** Öğrenci 21 kere "bir şey mi var?" diye tıklayıp aynı reklamı okumuyor; kilitli satır
tıklanamaz olduğu an dürüstleşiyor.
### K5 — Sihirbaz 3. adımdan "Öncelikler"i çıkar · **risk: orta · ürün onayı gerekir**
`src/features/sihirbaz/components/sihirbaz-adimlar.tsx:472-491` · sabit: `sihirbaz-sabitler.ts:10-18`
3. adım bugün **iki karar** istiyor: üniversite tipi (3 çip) + öncelikler (7 çip, çoklu seçim). Öncelikler
"listeyi daraltmaz" — yalnız prompt'a bir satır olarak giriyor (`sihirbaz-sabitler.ts:182-184`). Ve ürünün
resmî akış belgesinde (`huni-semasi.tsx`) bu adım **hiç yok**.
**Ne siler:** 7 çip + 2 açıklama satırı + `oncelikler` alanı (tip/doğrulama/prompt/fark hesabı geriye
uyumlu bırakılır: eski profillerde dolu kalabilir, yeni akışta boş dizi).
**Neyi kaybederiz:** AI gerekçelerinin kişisel tonu ("iş bulma kolaylığı" vurgusu), `tercihFarki`'nda bir
karşılaştırma boyutu, `danismaninBildikleri` listesinde bir satır (`listem-govde.tsx:129-131`).
**Neden kabul edilebilir:** Son adımda "hayatta senin için ne önemli?" diye sormak, bir *liste kurma*
akışının en yorucu sorusu — hem soyut hem geri dönüşsüz hissettiriyor, hem de çıktıyı somut olarak
değiştirmiyor. Adım 3 tek soruya (`Devlet mi, vakıf mı?`) inerse sihirbaz üç adımda üç soru olur.
**Not:** Bu kesim `/meraklisina` şemasını **değiştirmez** (şema zaten öncelikleri anlatmıyor); tersine
şemayla ekranı hizalar.
---
## 3. Silinebilecekler listesi (K1-K5 dışı)
⬇️ = riski düşük, tek başına alınabilir.
| # | Dosya:satır | Ne siler | Neyi kaybederiz | Neden kabul edilebilir |
|---|---|---|---|---|
| S1 ⬇️ | `paket-satinal.tsx:104-119, 189-196` | Paketi olmayan kullanıcıda **top-up kartının tamamı** | "Kredi bitti mi?" başlığı ve açıklaması | Kart paketsize zaten **satmıyor**; girişsizde ikinci, rakip bir CTA ("Önce giriş yap"), girişlide "önce paket gerekir" diyen bir paragraf. Ödeme ekranında satılmayan bir ürünün kartı duruyor. |
| S2 ⬇️ | `sohbet-client.tsx:536-548` | Paketsiz kullanıcıda "Son N kredin — … kredi yükleyip kaldığın yerden devam edersin" satırı | Kredi uyarısı (sayaç kart başlığında zaten var, `:350-357`) | **Yanlış bilgi:** paketsiz kullanıcı `/paket`'te kredi yükleyemiyor (`paket-satinal.tsx:189-196`). Ekran "kredi yükle" diyor, gidilen sayfa "yükleyemezsin" diyor. |
| S3 ⬇️ | `app/page.tsx:300-336` (Sorun bölümü) | Ana sayfadaki 3 kartlık "Tercih dönemi neden bu kadar stresli?" bölümü | ~1 ekranlık empati anlatısı | Akışı ilerletmiyor, tek CTA'sı yok, adayın zaten bildiğini söylüyor. Ana sayfayı ~8 ekrandan ~7'ye indirir. |
| S4 ⬇️ | `app/page.tsx:207-223` | "Meraklısına" turuncu pill'i hero'dan değil, **SSS'in altına** taşı (ya da sil) | Şeffaflık köprüsü | `SectionEyebrow`'un tam yanında, **farklı** bir pill dili (turuncu, `ArrowUpRight`) duruyor — rozet tek kaynağıyla çelişiyor (AGENTS.md). Meraklısına, merak eden için; akışın 3. bölümünde dikkat çalıyor. |
| S5 ⬇️ | `listem-govde.tsx:353-357` (`rapor-listesi.tsx:353-357`) | "Programlar ve ham veriler ücretsiz" yeşil satırı | Bir güven cümlesi | Aynı sayfada aynı şey 4 farklı cümleyle söyleniyor: H1 (`:187`), bu satır, kilit kartı (`:276-281`), paket kartı başlığı (`:329-331`). Biri yeter; en net olanı kilit kartındaki. |
| S6 ⬇️ | `listem-govde.tsx:184-188` | Paketsiz H1'i "Veriyi ücretsiz incele. Kararı Yapay Zeka ile netleştir." → **"24 tercihlik listen"** | Bir satış cümlesi | H1 sayfanın işini söylemeli; bugün reklam sloganı. Başlık hiyerarşisi + "ekranın tek işi" kuralı. |
| S7 | `app/layout.tsx:95` (`pb-28`) | Her sayfanın altındaki sabit 112px boşluk → koşullu hale getir | Yüzen banner çakışma payı | `KaydetBanner` yalnız girişsiz + ≥3 seçimli kullanıcıda çıkıyor (`kaydet-banner.tsx:47`); geri kalan herkes her sayfada 112px ölü alan kaydırıyor. Orta iş: sınıf, banner'ın görünürlüğüne bağlanmalı. |
| S8 | `giris-baslik.tsx:6-38` | `/giris` H1'indeki sonsuz döngülü yazı animasyonu | 6 slogan | Ekranın tek işi e-posta almak; başlık sürekli oynuyor ve `prefers-reduced-motion` okunmuyor (`typing-animation.tsx`'te hiç geçmiyor) → WCAG 2.2.2 (A) "Pause, Stop, Hide". Bkz. §7. |
---
## 4. Mobil (390px)
Tümü **koddan çıkarım**; Bilal'in gözle doğrulaması gereken liste en altta.
**Sabit krom maliyeti:** üst bant (sezon dışı, 2 satır) ~72px + başlık `lg` altında **iki satır**
(`site-header.tsx:12`, `flex-wrap`) ~100px + `mt-4` → **ilk ekranın ~%21'i** (844px varsayımıyla) içerik
görmeden gidiyor. K1 bunun ~70px'ini geri verir.
| Ekran | Tahmini boy | İlk ekranda CTA var mı? |
|---|---|---|
| Ana sayfa | ~6.900px ≈ **8,2 ekran** | ✅ Var. Hero `min-h-[calc(100svh-5.5rem)]` + `justify-center` → puan türü çipleri, sıralama alanı ve "Yapay Zeka listemi kur" birlikte görünüyor. **Akışın en sağlam ekranı.** |
| `/sonuc` (girişsiz) | ~3.650px ≈ **4,3 ekran** | ❌ **Yok.** İlk ekran: bant + başlık + boş gri harita kutusu + ~5 tablo satırı. Ana aksiyon (AI listesi) ~2,4 ekran aşağıda. K2 bunu ~7 satıra çıkarır ama CTA yine de yukarı gelmez. |
| `/listem` (paketsiz) | ~3.900px ≈ **4,6 ekran** | ⚠️ Kısmen: harita + H1 + "Tercihlerimi düzenle" görünüyor; satın alma CTA'sı ~1,2 ekran aşağıda (satır 4). |
| `/paket` | ~1.720px ≈ **2 ekran** | ⚠️ 844px'te "Paketi al" tam katlamada; **667px'te (iPhone SE) katlamanın altında.** S1 (top-up kartını gizle) bunu düzeltmez; H1 bloğunu kısaltmak düzeltir. |
| Sihirbaz modalı | `max-h-[92dvh]`, iç kaydırma | ✅ "Devam" alt çubukta sabit değil, panelin sonunda; adım 2'de il listesi `max-h-56` ile kendi içinde kaydırılıyor → modal boyu patlamıyor. İyi çözülmüş. |
**Yatay taşma / sıkışma riskleri:**
- `kaydet-banner.tsx:61` — tek satırlık `flex` (ikon 40px + metin + "Giriş yap, kaydet" butonu + çarpı),
`sm:` kırılımı yok. 390px'te metne ~70-80px kalıyor → başlık kelimesi kelimesine sarıyor, buton eziliyor.
Mobilde dikey dizilim gerekiyor.
- `program-tablosu.tsx` / `rapor-listesi.tsx` — program adı `truncate`, üniversite adı `truncate`: uzun
Türkçe adlarda ("İstanbul Medeniyet Üniversitesi", "Elektrik-Elektronik Mühendisliği (İngilizce)")
mobilde satırın çoğu üç noktaya gidiyor. Taşma yok ama **bilgi yok**. `title` var, mobilde işe yaramıyor.
Öneri: mobilde program adına 2 satır izni (`line-clamp-2`), üniversite satırı tek satır kalsın.
- `app/page.tsx:427-467` karşılaştırma tablosu `overflow-x-auto` içinde 4 sütun → 390px'te yatay kaydırma
gerektiriyor; kaydırılabilir olduğuna dair görsel ipucu (gölge/fade) yok.
- `vh` tuzağı yok: hero `svh` kullanıyor (`app/page.tsx:230`), modal `dvh` — doğru.
- Sabit alt çubuk × klavye çakışması yok (sabit alt çubuk yalnız `KaydetBanner`, form yok).
---
## 5. 24'lük liste ekranı — boğuyor mu?
**Hayır, yapı doğru. Boğan üç şey var, üçü de tekrardan geliyor.**
Doğru olanlar (değiştirme):
- Detay (gerekçe + risk notu + trend) **varsayılan kapalı**, satır tıklanınca açılıyor (`rapor-listesi.tsx:300`).
Yani 24 satır aynı anda 72 metin bloğu değil, 24 satır gösteriyor.
- `/sonuc` ham tablosu ile `/listem` raporu **aynı satır dilini** paylaşıyor (aynı sütunlar, aynı düzen) —
öğrenci ikinci ekranda yeniden öğrenmiyor. Bu iyi ve korunmalı.
- Uyarılar (`kapsam.uyarlandi`, `tekIl`) listenin **üstünde ve koşullu** — her zaman görünmüyorlar.
Boğan üçü:
1. **Kilitli 21 satırın tekrarı** → K4.
2. **Aynı "ücretsiz/ücretli sınırı" mesajının 4 kez tekrarı** → S5 + S6.
3. **5 ayrı `/paket` girişi** (`listem-govde.tsx:288`, `:369`, `sohbet-client.tsx:351`, `:538`, `:546`,
ayrıca `user-nav.tsx:64`). Tek ekranda beş kapı, "kaç kere soracaksınız" hissi üretiyor.
Kalması önerilen: **satır içi kilit kartı** (bağlamda, satırın tam orada) + sohbet başlığındaki kredi pill'i
(aksiyon değil, durum göstergesi). Gidecek: sağdaki büyük paket kartı (`:323-386`) ile S2.
**Öğrenci 24 satırı nasıl okuyor (varsayım — ölçümle doğrulanmalı):** sırayla değil, **tanıdık ada göre**.
Satırda öne çıkan tek şey program adı; tercih numarası (1-24) gri bir daire, dilim (hayal/dengeli/güvenli)
ise satırda **hiç görünmüyor** — yalnız detay açılınca çıkıyor (`rapor-listesi.tsx:81-88`). Oysa listenin
tüm değeri o dağılımda. **Sadeleştirme önerisi (tek değişiklik):** satırlar arasına dilim ayracı koy —
"Hayal (1-5)", "Dengeli (6-18)", "Güvenli (19-24)" gibi 3 ince başlık satırı. Yeni bileşen değil, `/sonuc`
tablosundaki `DILIMLER` etiketleri + ikonlarıyla aynı dil (`program-tablosu.tsx:45-74`), etiket tek kaynağı
`DILIM_ETIKET`. Böylece 24 satır **3 okunur gruba** iner ve "neden bu sırada?" sorusu satır açmadan cevaplanır.
(Bu bir **ekleme** değil sınıflandırma: kaldırılan 21 kilitli detay kutusunun yerine geliyor.)
**Kilitli satırlar dürüst mü?** Kısmen.
- ✅ Dürüst: program adı, üniversite, taban sıra ve trend kilitli satırlarda da **gerçekten açık** — vaat
("Program adları ve taban verileri her zaman ücretsiz", `:278-280`) tutuluyor.
- ❌ Hayal kırıklığı üreten: (a) kilitli satırın açılabilir görünmesi ama hep aynı reklamı vermesi (K4);
(b) mobilde kilidin karşılığı yalnız bir `Lock` ikonu — "Pakette" yazısı `sm` altında `sr-only`
(`:259`), yani 390px'te sütun sessiz; (c) ilk 3 satırın açık olduğu **satırlara bakmadan anlaşılmıyor**:
kilit kartı satır 4'te belirene kadar öğrenci kaçının açık olduğunu bilmiyor. Liste başlığında tek cümle
("İlk 3 tercihin analizi açık") bu belirsizliği bedava kapatır.
---
## 6. URAP genel sıralaması nasıl girer?
**Kural olarak kabul edilenler:** (1) atıf aktif link olacak ve tek sabit adres olacak:
`https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025` — Bilal'e gelen izin böyle diyor,
güncellemeler otomatik yansısın diye. (2) Tablo yığını yok. (3) Renk yok: URAP sırası **risk dili değildir**,
yeşil/kırmızı boyanmaz. (4) Yeni bileşen icat edilmez.
**Nereye girmez (baştan reddedilenler):** `/sonuc` tablosu ve `/listem` 24'lük liste satırları. URAP
**üniversite** göstergesi, satırlar **program** satırı; 24 satıra bir sütun daha eklemek tam olarak
istemediğimiz şey. Ayrıca aynı üniversite listede 3 kez geçerse aynı sayı 3 kez tekrarlanır.
**Alternatif A — mevcut istatistik ızgarasında takas (ÖNERİLEN)**
`src/features/katalog/components/universite-icerik.tsx:290-331` — sayfada **zaten** 4 kartlık bir metrik
ızgarası var. URAP yeni bir kutu açmaz; **"Tür" kartının yerine geçer.**
```
/universite/[slug] — 390px
┌──────────────────────────────────────┐
│ [Türkiye haritası] │ col-span-2 (mevcut)
└──────────────────────────────────────┘
┌──────────────────┐┌──────────────────┐
│ PROGRAM ││ FAKÜLTE / BİRİM │ (mevcut)
│ 312 ││ 24 │
└──────────────────┘└──────────────────┘
┌──────────────────┐┌──────────────────┐
│ URAP TÜRKİYE ││ EN İYİ SIRALAMA │ ← "Tür" kartının yerine
│ 18 / 183 ││ 1.240 │
│ 2025-2026 ││ │
└──────────────────┘└──────────────────┘
… tablo …
Kaynak: YÖK Atlas 2026 yerleştirme sonuçları. Son güncelleme: 21 Eylül 2026.
Genel sıralama: URAP Türkiye 2025-2026 (urapcenter.org). ← atıf, mevcut satırın devamı
└ aktif link
```
Neden bu:
- **Kart sayısı artmıyor.** Izgara 4 kart kalıyor, `lg` şablonu (`grid-cols-[1fr_1fr_1.35fr] grid-rows-2`,
harita `col-start-3 row-span-2`) hiç değişmiyor — 5. kart bu şablonu kırardı.
- **"Tür" gitmeli çünkü üç yerde daha var:** özet paragrafta, tablodaki her program satırının
Devlet/Vakıf rozetinde ve `/sonuc` filtresinde. Tek başına bir metrik kartını hak etmiyor.
- **`18 / 183` biçimi tek sayının bağlamını taşıyor.** "18." tek başına iyi mi kötü mü belli değil;
payda öğrencinin kendi kafasında ölçeklemesini sağlıyor. Alt satırda dönem (`2025-2026`), çünkü
sayfadaki diğer tüm sayılar YKS yılına ait — karışmasın.
- **Atıf ekranı kirletmiyor:** `VeriKaynagi` (`veri-kaynagi.tsx:18-31`) zaten sayfanın tek "kaynak"
satırı ve tablonun altında duruyor. URAP cümlesi oraya bir cümle olarak ekleniyor, yeni kutu yok.
Aktif link şartı karşılanıyor, görünürlük sayfa altında kalıyor.
- **Boş durum:** URAP'ta olmayan üniversitede (vakıf MYO'lar, KKTC, yeni kurulanlar) kart **hiç
çizilmez ve "Tür" kartı yerinde kalır.** Yani ızgara her zaman 4 hücre, hiçbir sayfada "—" gösterilmiyor.
Veri kapsamı `docs/ekip-raporlari/2026-09-21/06-uni-veri.md:62`'ye göre ~%95 ad eşleşmesi.
**Alternatif B — H1 altı özet cümlesine göm**
`universite-icerik.tsx:261-283`'teki özet paragrafın ilk cümlesine:
> "Boğaziçi Üniversitesi (İstanbul), **URAP 2025-2026 Türkiye genel sıralamasında 5.**; 2026 YKS yerleştirme
> sonuçlarına göre 312 programda öğrenci aldı…"
Artısı: sıfır yeni eleman, sıfır düzen değişikliği, en ucuz iş.
Eksisi: **taranabilir değil.** Bilal'in niyeti "öğrenci kolayca görsün"; paragraf ortasındaki sayı
gözle taranmaz, mobilde 7 satırlık metnin içinde kaybolur. Ayrıca atıf linki cümlenin ortasında durmak
zorunda kalır (kaynak satırında değil) → okuma akışını böler.
**Öneri: A.** B yalnızca A'nın veri hattı hazır olmadan bir şey yayımlamak gerekirse geçici çözüm olur.
**Tasarımın veri tarafına koyduğu şart (veri-muhendisi'ne):** gereken tek alan `urap_tr_sira`
(`06-uni-veri.md:165` şemasında zaten var) **artı sıralamadaki toplam üniversite sayısı** (payda).
Payda olmadan A alternatifi anlamını kaybeder. "Geçen yıla göre değişim" (Tablo 11) **bu sürüme
girmesin** — ikinci bir sayı, ikinci bir okuma yükü.
**Ayrıca [BİLAL] / ürün uyarısı:** `06-uni-veri.md` 8 göstergelik bir ilk sürüm öneriyor. Bu gece
"çıkarma" gecesiyse: **8 gösterge = 8 kutu = tam olarak istemediğimiz tablo yığını.** Öneri, URAP'ın
tek başına ve takas yoluyla girmesi; kalan 7 gösterge ancak ızgara büyütülmeden, yine takasla ya da
tablo altındaki tek bir satırda toplanarak değerlendirilsin.
---
## 7. Kural ihlalleri (kesimden bağımsız, düzeltilmeli)
| # | Dosya:satır | Kural | Kullanıcıya etkisi | Düzeltme | Büyüklük |
|---|---|---|---|---|---|
| R1 | `program-tablosu.tsx:306-314` | **AGENTS.md risk dili** — "kırmızı/sarı/yeşil her zaman metin etiketiyle" | `/sonuc` tablosunda risk **yalnız renkli nokta**, `aria-hidden`, metin etiketi **hiç yok**. Renk körü ve ekran okuyucu kullanıcısı için satır risksiz görünüyor. Dünkü vardiyada yan bulgu olarak not düşülmüş, kimse almamış. | `rapor-listesi.tsx:262-270` kalıbını kopyala (nokta + `RISK_ETIKET[risk]`) | S |
| R2 | `rapor-listesi.tsx:259, 267` | Aynı kural + mobil öncelik | Etiket `sm` altında `sr-only` → **390px'te gören kullanıcı yalnız rengi görüyor.** Trafiğin ~%90'ı mobil. | `sr-only sm:not-sr-only` → her zaman görünür; sığmıyorsa tek harfli değil, kısaltılmış tam etiket | S |
| R3 | `giris-baslik.tsx:26-38` + `components/ui/typing-animation.tsx` (dosyada `prefers-reduced-motion` hiç geçmiyor) | **WCAG 2.2.2 (A)** "Pause, Stop, Hide" + `prefers-reduced-motion` | Giriş sayfasının H1'i sonsuz döngüde yazılıp siliniyor; durdurulamıyor, hareket azaltma ayarı yok sayılıyor. Vestibüler duyarlılık + dikkat dağıtma; ekranın tek işi form doldurmak. | S8 (kaldır) ya da en az: `useReducedMotion()` ile tek sabit metne düş | S |
| R4 | `sihirbaz-cagri-karti.tsx:322` (`text-white/70` · `bg-primary`) | **WCAG 1.4.3** kontrast | Hesaplanan oran **2,57:1** (gereken 4,5:1). "Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede" — tam da tereddüdü kıran cümle, okunmuyor. | `text-white/70` → `text-white` (oranı 3,68:1'e çıkarır; tam uyum için zemin koyulaşmalı — `[BİLAL]`, palet) | S |
| R5 | `sihirbaz-cagri-karti.tsx:301, 337` (`text-white/90` · `bg-primary`) | WCAG 1.4.3 | **3,26:1.** Panel gövde metinleri. | aynı | S |
| R6 | `site-top-banner.tsx:120` (`opacity-85`, `text-xs`) | WCAG 1.4.3 | Beyaz üstü `--primary` zaten 3,68:1; %85 opaklıkla ~3,0:1. Bandın en uzun cümlesi. | K1 zaten bandı kaldırıyor; sezon içinde opaklık kalksın | S |
| R7 | 48 kullanım, ör. `sihirbaz-adimlar.tsx:228, 381, 406, 442, 473` · `program-tablosu.tsx:217, 278` | WCAG 1.4.3 | `text-slate-400` (#94A3B8) beyaz üstünde **2,57:1**, `bg-slate-50` üstünde **2,45:1**. Sihirbazın "Adım 1/3" göstergesi, alan başlıkları ("ÜNİVERSİTE TİPİ", "SENİN İÇİN ÖNEMLİ OLAN"), tablo sayaçları okunmuyor. | Metin taşıyan yerlerde `text-slate-400` → `text-slate-500` (4,76:1 ✅). Yalnız ikon/dekor kalabilir. | M (sistemik) |
| R8 | `sihirbaz-cagri-karti.tsx:284` | **AGENTS.md CTA deseni** | "Listeni gör" butonunda sondaki `ArrowRight` yok; sitenin diğer tüm funnel CTA'larında var. | `<ArrowRight className="size-4" aria-hidden />` ekle | XS |
| R9 | `app/page.tsx:209-220` | **AGENTS.md rozet tek kaynağı** | `SectionEyebrow`'un tam yanında elle yazılmış turuncu pill duruyor; aynı yerde iki farklı rozet dili. | S4 (taşı/sil) ya da `SectionEyebrow` + link | S |
| R10 | `sihirbaz-adimlar.tsx:319` (`size-5` = 20px), `kaydet-banner.tsx:102` (`p-1` + `size-4` ≈ 24px), `sohbet-client.tsx:344` (`size-7` = 28px) | **WCAG 2.5.8 (AA)** 24px · ürün hedefi 44px | İl aramasını temizleme, banner'ı kapatma, sohbeti temizleme — hepsi parmakla ıskalanıyor. | `size-9`/`size-11`'e çıkar (dialog kapatma çarpısının kanonik `size-9` seti zaten var) | S |
| R11 | `program-tablosu.tsx:391, 398` | Tek kaynak / ölü sınıf | `ProgramEkleButonu` tabanı `size-11 min-h-11 min-w-11`; buradan `className="size-8 min-h-8 min-w-8"` geçiliyor ama `cn()`/tailwind-merge yok (`program-ekle-butonu.tsx:112` düz şablon) → iki sınıf birden DOM'da, hangisinin kazandığı CSS sırasına kalmış. Ana akışın en kritik butonu (`+`) belirsiz boyutta. | Ya override'ı kaldır (44px kalsın) ya da `cn()` kullan; ikisi birden olmasın | S |
---
## 8. Çapraz kontrol — `04-liste-maliyet-ve-oneriler.md` (yapay zekâ mühendisi)
Rybbit rakamı gelmedi, ama iki bulgum bağımsız bir kaynakla **kanıtlandı**:
- **K5 (Öncelikler çıksın) → destekleniyor.** O raporun 1. maddesi: *"Yapay zekâ listeyi kurmuyor, listeyi
dolduruyor… hangi dilimde olacağını, satırların sırasını, risk ve trend cümlelerini kod belirliyor."*
Yani "Öncelikler" çiplerinin listenin yapısına etkisi yok; etkisi yalnız satır başına yazılan tek
gerekçe cümlesinin tonunda. Ekranda 7 çip + 2 açıklama satırı karşılığında alınan şey bu kadar.
- **§5 kilitli satır bulgusu → destekleniyor ve büyüyor.** O raporun 4. maddesi kilitli 21 satırı
ürün/fiyat açısından da sorunlu buluyor ("teaser doğru ama teaser'ı deneme kredisiyle ücretlendirmek
yanlış"). Benim tarafım yalnız **görünüş**: aynı satış kutusunun 21 kez tekrarı (K4). İkisi aynı
yerde buluşuyor — **kilitli satır deneyimi bu gecenin en çok kanıtlı düzeltme alanı.**
- **Varsayım olarak kalanlar** (ölçümsüz): /sonuc'ta iki panelden hangisinin daha çok tıklandığı (K3
hangisinin kalacağını rakam belirlemeli), ana sayfadaki "Sorun" bölümünün kaydırma derinliği (S3),
öğrencinin 24 satırı nasıl okuduğu (§5).
---
## Bilal'in gözle kontrol etmesi gerekenler
Tarayıcıyı açmadım; bu listeyi telefonda (390px civarı) açıp bakman yeterli:
1. **`/sonuc`, girişsiz, yeni sekmede** — üstteki boş gri kutu (K2) ve ilk ekranda kaç program satırı
göründüğü. Aşağı in: art arda iki turuncu/lacivert giriş paneli (K3) gerçekten üst üste mi?
2. **`/listem`, paketsiz hesapla** — 4. satırdaki kilit kartından sonra kilitli satırlardan birine
dokun (K4): aynı kutu mu geliyor? Kaç kere `/paket`'e giden bir şey sayıyorsun?
3. **`/listem` ve `/sonuc` risk sütunu telefonda** — nokta var, yazı var mı? (R1/R2)
4. **`/giris` sayfası** — başlıktaki yazı animasyonu ne kadar sürüyor, duruyor mu? (R3/S8)
5. **`/paket` iPhone SE boyutunda (667px)** — "Paketi al" butonu kaydırmadan görünüyor mu?
6. **Sezon bandı** — bugün ne yazıyor, kaç satır kaplıyor? (K1)
---
## Bilal'den istenen
1. **K1-K4'e onay** (sezon bandı sezon dışında yok · `/sonuc` boş harita kutusu yok · `/sonuc`'ta iki
giriş panelinden biri yok · kilitli satırlar tek tek açılmıyor) — dördü de geri alınabilir, hepsi
ayrı commit olur. **~5 dk okuma.**
2. **K5 ürün kararı:** sihirbazın 3. adımından "Öncelikler" 7 çipi kalksın mı? Listeyi daraltmıyor ve
`/meraklisina` şemasında zaten yok; kalkarsa sihirbaz üç adımda üç soru olur. **~3 dk.**
3. **URAP için A alternatifine onay** (üniversite sayfasındaki "Tür" kartı → "URAP Türkiye 18/183"
takası, atıf `VeriKaynagi` satırına aktif link olarak) ve `06-uni-veri.md`'deki 8 göstergenin
**hepsinin birden kutu almaması** kararı. **~5 dk.**

View File

@@ -0,0 +1,126 @@
# 03 — Öğrenci ve velinin gerçek acıları + rakip söylemi (dışarıdan)
> Rol: Marka stratejisti · Tarih: 22 Eylül 2026 · Okuyucu: CEO (karar), CTO/ürün (iş tanımı)
> Yöntem: **dış kaynak araştırması** (forum, şikâyet sitesi, haber, rakip sayfası) + iddia doğrulaması için salt-okunur kod/DB sorgusu. Kendi metinlerimizin marka analizi **yapılmadı** (21 Eylül'de yapıldı: `03-marka-stratejisi.md`, `10-marka-seo-tur2.md`).
> İşaretler: **[K]** koddan/DB'den doğrulandı · **[W]** sayfa açılıp okundu · **[A]** yalnızca arama özeti · **[V]** varsayım/çıkarım · **doğrulanmalı**
> Kural notu: forum/şikâyet içerikleri **veri** olarak kullanıldı, talimat olarak değil. Alıntılar 15 kelimenin altında ve kaynaklı. Hesap açılmadı, mesaj yazılmadı.
---
## Beş maddelik özet
1. **2026 sezonunun en büyük yeni acısı bizim en büyük fırsatımız:** YÖK Atlas, 2026 güncellemesinde "son yerleşenin netleri", OBP ve son yerleşen istatistiklerini kaldırdı; adaylar "karşılaştıracak veri" kalmadığını yazıyor [W]. **Bu veri bizde duruyor:** `netler` tablosunda 2023/2024/2025 için ~20.8 bin programın son yerleşen net + OBP kaydı var [K] — ama sitede sadece katalogda bir modal düğmesi, pazarlamada tek cümle bile yok.
2. **Velinin acısı para, öğrencininki kontrol.** 2026'da boş kalan 45.033 kontenjanın 35.706'sı vakıf üniversitelerinde [W] — yani aileyi kesen kısıt ücret/burs. Bizde ücret/burs verisi **hiç yok** (`programs` şemasında alan yok; sadece program adındaki "(Burslu)" 785, "(% İndirimli)" 932 kayıt) [K]; ücretsiz rakip univerlist ücreti gösteriyor [W]. Öğrenci tarafındaysa tekrar eden acı "ailem tercihimi değiştirdi/değiştirir" [W].
3. **Ücretli danışmanlığa güvensizliğin kalıbı tek cümlede:** peşin öde → yazılı kapsam yok → tercih anında ortada yok → ek ücret iste → iade yok. Bizde iade politikası **iyi** ama **ödeme ekranında görünmüyor** (`src/app/kosullar/page.tsx:61-83` iyi metin; `src/app/paket/page.tsx:60-68` iade kelimesi geçmiyor) ve koşullar sayfasında satıcı kimliği yok, dosyada hâlâ "MVP taslağıdır" notu var (`kosullar/page.tsx:15`) [K].
4. **Rakiplerin sustuğu şey: ücretsiz alternatifin varlığı ve aracın sınırı.** Ücretsiz robotlar 24'lük listeyi üyeliksiz, saniyeler içinde kuruyor (canlikoc: "üyelik yok", hayal/ideal/güvenli dilimleri, PDF/WhatsApp paylaşımı) [W]; hiçbiri "bu işi MEB/RAM/rehber öğretmen ücretsiz de yapıyor" demiyor. Bizim dürüstçe söyleyebileceğimiz cümle bu — ve söylersek 299 TL'nin gerekçesini *biz* tanımlarız.
5. **URAP: tablo olarak gürültü, tek satır olarak ilaç.** Forumlarda URAP'ın metodolojisi doğrudan eleştiriliyor ("ETH Zürich THE'de 15., burada 57.") [W]; öğrencinin gerçek sorusu "hangi üniversite daha iyi" değil **"bölüm mü üniversite mi, X mi Y mi"** [W/A]. Öneri: URAP'ı sıralama tablosu/"en iyi üniversiteler" listesi olarak **yayımlama**; `/universite/[slug]` sayfasında tek satır olarak ("URAP Türkiye 2025-2026: N. / 198 · akademik yayın performansı ölçer, eğitim/iş çıktısı değil" + urapcenter.org bağlantısı) göster.
---
## 1. Acı noktaları tablosu
Sıralama, kaynaklarda karşılaşma sıklığına göre [V] — nicel bir ölçüm değil, 20+ kaynakta tekrar sayısına dayanan editör yargısı.
| # | Acı (onların cümlesiyle) | Kanıt / alıntı | Biz çözüyor muyuz? | İş |
|---|---|---|---|---|
| 1 | **"Karşılaştıracak veri kalmadı."** YÖK Atlas 2026'da son yerleşen istatistikleri, net ve OBP verilerini kaldırdı; aday kendi sonucunu geçmiş yıllarla kıyaslayamıyor | "son yerleşen istatistiklerinin tamamen kaldırıldığını gördüm" (22 May 2026) [W] https://www.sikayetvar.com/yokatlasyokgovtr/yok-atlas-guncellemesi-son-yerlesen-istatistiklerini-kaldirarak-adaylari-belirsizlige-surukluyor · köşe yazısı: net ortalamaları, OBP, "kaçıncı tercihine yerleşti" verileri kaldırıldı, 28 May 2026 [W] https://www.haber7.com/yazarlar/ismail-yolcu/3631241-yok-atlas-neden-degistirildi | **Kısmen — veri bizde, anlatım yok.** `data/yokatlas.db` → `netler`: 2025/2024/2023 için 20.821 / 20.813 / 21.341 program, net + OBP [K]; arayüz `src/features/katalog/components/program-netleri.tsx:97` "Son yerleşenin netleri" modalı; ana sayfa/paket metinlerinde geçmiyor (grep) | **S** (anlatım + rehber yazısı) / **M** (sihirbaz ve rapor satırına taşımak) |
| 2 | **"Puan mı sıralama mı?"** ham puana göre tercih yapıp yanılma, ölü tercih | "kriter yerleştirme başarı sıralamasıdır, ham puan değil" [A] https://unikazan.com/tercih-robotu-kullanirken-dikkat-edilecekler/ · ekşi tavsiye başlığı: düşükten sonra yüksek yazmak "%99 kazanılamıyor" [W] https://eksisozluk.com/universite-tercihi-yapacaklara-tavsiyeler--1315523 | **Evet.** Risk deterministik ve sıralama koddan hesaplanıyor; LLM tercih sırası yazmıyor (`src/lib/ai/rapor.ts:90` "Tercih sırası, risk notu ve trend özeti koddan hesaplanır") [K]; `content/rehber/olu-tercih-nedir.md` | **S** (vitrine çıkarmak) |
| 3 | **"Az yazdım, açıkta kaldım."** / yerleşip kayıt yaptırmama | 2026: 730.854 yerleşen, **45.033 boş kontenjan** (29.882 lisans), ÖSYM sayısal bilgilerinden derleme, 18 Ağu 2026 [W] https://radikalegitim.com/blog/2026-yks-yerlestirme-sonuclari-rakamlarla-degerlendirme · ek yerleştirmede 110.053 boş kontenjan [A] https://www.egitim.net.tr/sinav/2026-yks-ek-yerlestirmede-110-bin-53-bos-kontenjan-var-17182h | **Evet** (24 satırlık liste iskeleti 5/13/6 hedefi, `src/features/pazarlama/components/huni-semasi.tsx`) [K] | **S** |
| 4 | **"Parayı kim ödeyecek?"** vakıf ücreti/burs belirsizliği; burs kaybı senaryosu | Boş kontenjanın 35.706'sı vakıf üniversitelerinde [W] (yukarıdaki kaynak) · aile "burs kaybı senaryolarını da hesaba katsın" uyarısı [A] https://rehberpanda.com/blog/2026-vakif-universitesi-burs-oranlari-tam-yuzde-50-25/ | **Hayır.** `programs` şemasında ücret/burs alanı yok; bilgi yalnızca program adında ("Burslu" 785, "İndirimli" 932 kayıt) [K]. Ücretsiz rakip univerlist "ücretler" sütunu gösteriyor [W] https://univerlist.com/tr/tercihbotu/ | **L** (ÖSYM kılavuz PDF'i → veri hattı; yıllık) |
| 5 | **"Ailem tercihimi değiştirdi."** özerklik/baskı çatışması | "Türk aile yapısının özetidir" · "Keşke karşılarına alıp açık konuşsalardı" (07.08.2022) [W] https://eksisozluk.com/cocugunun-yks-tercihlerini-gizlice-degistiren-aile--7367060 | **Kısmen.** Liste öğrencinin hesabında ve yazdırılabilir (`src/features/rapor/components/rapor-yazdir.tsx`) [K]; veliye dönük tek yüzey bir rehber yazısı (`content/rehber/veliler-icin-tercih-rehberi.md`), `/veliler` sayfası yok | **M** |
| 6 | **"Ücretsizi varken neden para vereyim?"** | "kanmayın çocuklar böyle şeylere" [W] https://eksisozluk.com/tercih-danismanligi--4464840 · ücretsiz kanal listesi: MEB komisyonları, rehber öğretmen, RAM, belediye, YÖK Atlas (5 Tem 2026) [W] https://rehberpanda.com/blog/2026-ucretsiz-yks-tercih-danismanligi-meb-ram-belediye/ | **Kısmen.** Ücretsiz *robot*larla farkımız anlatılıyor (`src/app/page.tsx:127`), ücretsiz *kamu* alternatifi hiç anılmıyor (grep: MEB/RAM geçmiyor) | **S** |
| 7 | **"Ödedim, hizmeti alamadım, iade yok."** | YKS koçluğu şikâyeti: "Tercih döneminde böyle geçiştirilmemiz ve ek ücret istenmesi bizi şaşırttı" [W] https://www.sikayetvar.com/kopilot-rehberlik/yks-tercih-surecinde-kocluk-desteginin-kesilmesi-ve-ek-ucret-talebi · eğitim danışmanlığı şikâyet başlıkları: iade edilmeyen ücret, teslim edilmeyen paket, izinsiz otomatik yenileme (Eylül 2026) [W] https://www.sikayetvar.com/danismanlik/egitim | **Kısmen.** İade politikası net (`src/app/kosullar/page.tsx:61-83`) ama ödeme sayfasında görünmüyor (`src/app/paket/page.tsx:60-68`); satıcı kimliği yok; dosyada "MVP taslağıdır" notu (`kosullar/page.tsx:15`) [K] | **S** |
| 8 | **"Robot güvenilir mi, yanlış mı gösteriyor?"** aracı karar verici sanma | "Tercih robotu bir 'asistan' olabilir ama 'karar verici' olmamalıdır" [A] https://www.hocamkocluk.com/blog/tercih-robotlarina-ne-kadar-guvenilmeli · ekşi: "puanları tam olarak yazdığınızda yanlış hesaplıyor" [W] https://eksisozluk.com/tercih-robotu--353135 | **Evet/kısmen.** Karar destek beyanı `src/app/paket/page.tsx:61-63`; yöntem açık `/meraklisina`; havuz-dışı yasağı prompt'ta (`src/lib/ai/rapor.ts:71-73`) [K] | **S** |
| 9 | **"Hangi üniversite daha iyi / bölüm mü üniversite mi?"** | "Tercih masasında en çok tartışılan soru budur: Bölüm mü önemli, üniversite mi?" [A] https://tudu.com.tr/blog/universite-mi-bolum-mu · KizlarSoruyor'da aynı soru başlık olmuş [A] https://www.kizlarsoruyor.com/egitim-kariyer/q7341352-istediginiz-bolum-mu-yoksa-iyi-bir-universite-mi-onemli | **Hayır.** Üniversite kalite/karşılaştırma metriği yok; URAP dahil veri planı sadece dokümanda (`docs/ekip-raporlari/2026-09-21/06-uni-veri.md:62`) [K]. `/universite/[slug]` sayfası mevcut [K] | **M** (§5) |
| 10 | **"Yerleşemedim / kaydımı yaptırmadım, şimdi ne olacak?"** ek yerleştirme karmaşası | Ek yerleştirme tercihleri 21 Eyl 2026'ya kadar; 110 binden fazla boşluk [A] (3. satırdaki kaynak) | **Evet (içerik).** `content/rehber/yerlesemedim-ne-yapmaliyim.md`, `bos-kontenjanlar-ne-anlatiyor.md`, `mezuna-kalmak-mi-kayit-olmak-mi.md` [K]; üründe ek yerleştirme akışı yok | **M** (ürün) / **S** (içerik güncelleme) |
---
## 2. Velinin acısı ≠ öğrencinin acısı
| | **Öğrenci (kullanan)** | **Veli (ödeyen)** |
|---|---|---|
| Ana korku | "Yanlış yere düşerim ve 1 yıl kaybederim" · "kendi kararım olmayacak" | "Yanlış yere gider, para ve yıl gider" · "bu parayı boşa mı veriyorum" |
| Tetikleyici cümleler | "ailem gizlice değiştirdi", "rehber öğretmeni dinlemeyin, kendin araştır" [W] eksisozluk/universite-tercihi-yapacaklara-tavsiyeler | "ücretler kılavuzda yazıyor ama üniversitenin sitesinden de doğrulayın", "burs kaybı senaryosunu da hesaplayın" [A] rehberpanda |
| Bilgi ihtiyacı | Sıralama → hangi bölüm açılır, net/OBP kıyası, şehir, bölümün gerçekte ne olduğu | Toplam maliyet (ücret, burs, yurt, şehir), iş imkânı, kurumun ciddiyeti, iade/garanti, "kim bu site" |
| Güven kırıcı | Vaat dili, reklam kokusu, "garanti" | Satıcı kimliğinin olmaması, iade koşulunun görünmemesi, kaynaksız rakam |
| Bizim bugünkü yüzeyimiz | Sihirbaz + liste + sohbet + yazdırma [K] | Yok denecek kadar az: tek rehber yazısı; `/veliler` yok, `/hakkinda` yok (21 Eyl raporu G6) |
| Tek cümlelik vaat önerisi | "Listeyi sen kurarsın; biz gerekçesini yazarız." | "Ne aldığınız, ne almadığınız ve para iadesi tek sayfada yazılı." |
**Not [V]:** Veli, ürünü genelde *satın alma anında* görüyor; bu yüzden veliye dönük her kanıt (`/hakkinda`, iade satırı, örnek PDF) `/paket` sayfasından bir tık uzakta olmalı — ayrı bir kampanya değil.
---
## 3. Güven açığı: insanlar ücretli tercih hizmetine neden güvenmiyor?
**Tekrar eden kalıp (5 kaynakta aynı iskelet) [W]:**
1. Peşin ödeme alınır (koçluk/danışmanlık paketi).
2. Kapsam yazılı değildir; "tercih dönemi desteği" muğlak kalır.
3. İşin en kritik anında hizmet ya yoktur ya ek ücretlidir ("Tercih döneminde böyle geçiştirilmemiz ve ek ücret istenmesi…" [W] sikayetvar/kopilot-rehberlik).
4. İletişim kesilir, iade yapılmaz ("İade Edilmeyen Ücret…", "Teslim Edilmeyen Eğitim Ve Danışmanlık Paketi" [W] sikayetvar/danismanlik/egitim).
5. Kamuoyunda karşılığı: "kanmayın çocuklar böyle şeylere" [W] eksisozluk/tercih-danismanligi ve "ücretsizini şuralardan alın" içerikleri [W] rehberpanda.
**Bizde bu kalıba düşen noktalar (dosya:satır) [K]:**
| Kalıp adımı | Bizdeki durum | Kanıt |
|---|---|---|
| Peşin ödeme | Var (tek seferlik 299 TL, kredi ile) | `src/lib/credits.ts:11,14` |
| Kapsam yazılı mı? | Kısmen: paket kartında yazılı, sözleşmede satıcı kimliği **yok** | `src/app/kosullar/page.tsx` (grep: unvan/adres yok) |
| İade görünür mü? | **Hayır** — politika iyi ama ödeme sayfasında iade kelimesi geçmiyor | iyi metin: `kosullar/page.tsx:61-83` · eksik: `paket/page.tsx:60-68` |
| Sözleşme olgunluğu | Kod içi not: "MVP taslağıdır; yayına almadan önce hukuki gözden geçirme gerekir" — ödeme alınıyor | `src/app/kosullar/page.tsx:15`, `src/app/gizlilik/page.tsx:15` |
| Kriz anında erişim | İletişim sayfası var; sezon içi yanıt süresi taahhüdü ölçülmüyor [V] | `src/app/iletisim/page.tsx:24` |
**Yorum:** Şikâyetlerin çekirdeği "kötü tavsiye" değil, **"ödedim, karşılığını alamadım ve kimseye ulaşamadım"**. Bu yüzden güven işi tavsiye kalitesinden çok *görünür taahhüt* işidir: iade satırı ödeme butonunun yanında, satıcı kimliği sözleşmede, yanıt süresi iletişimde.
---
## 4. Rakiplerin söylemediği şey
Kontrol ettiklerim [W]: canlikoc.com/tercih-robotu.php, univerlist.com/tr/tercihbotu, YÖK Atlas tercih sihirbazı (21 Eyl raporu), armut.com danışman sayfası, osym7bizi (21 Eyl). Hiçbiri şunları söylemiyor:
1. **"Bu işin ücretsiz ve resmî bir yolu var."** MEB tercih danışmanlığı birimleri, RAM, rehber öğretmen, belediye masaları — hepsi ücretsiz [W] rehberpanda. Kimse kendi sayfasında bunu yazmıyor.
2. **"Aracın gördüğü veri eksildi."** 2026'da YÖK Atlas'ın kaldırdığı net/OBP/son yerleşen verisini kimse tercih aracının vitrininde konuşmuyor [W]; oysa adayın en çok ihtiyacı olan kıyas verisi bu.
3. **"Ücret/burs kaybı senaryosu listenin parçasıdır."** Ücret sütunu gösteren araç var (univerlist) ama "burs düşerse ne olur" sorusunu kimse listenin içine koymuyor [W/V].
**Önerilen tek cümle (vaatsiz, doğrulanabilir) — [BİLAL] onayı:**
> "Tercih danışmanlığının ücretsiz yolu da var: okulunun rehber öğretmeni, MEB tercih danışmanlığı birimleri ve YÖK Atlas. KolayTercih'in yaptığı farklı bir şey: sıralamanla açılan programlardan 24 satırlık listeyi kurar, her satırın neden orada olduğunu yazar ve YÖK Atlas'ın 2026'da yayından kaldırdığı 'son yerleşenin netleri' verisini 2023–2025 için önüne koyar."
Doğrulama notu: ikinci cümlenin ikinci yarısı yayına girmeden önce (a) `netler` verisinin arşiv kullanımının hukuki durumu **doğrulanmalı**, (b) YÖK Atlas'ta verinin bugün gerçekten olmadığı **ekran kaydıyla teyit edilmeli** (şikâyet + köşe yazısı kaynak, resmî duyuru bulunamadı).
---
## 5. URAP: gerçekten bir acıyı dindirir mi?
**Bulgular**
- Forumda üniversite kıyası **sıralama puanıyla değil ikili karşılaştırmayla** yapılıyor: "bölüm mü üniversite mi", "X mi Y mi" [A] tudu.com.tr, kizlarsoruyor.
- URAP'ın kendisi bilen kullanıcılar tarafından eleştiriliyor: metodoloji tutarsızlığı ("ETH Zürich THE'de 15., burada 57."), küçük üniversitelerin oran etkisiyle yukarı çıkması (Şırnak örneği) [W] https://eksisozluk.com/urap--2547573
- Genel "en iyi üniversiteler" tartışmalarında sıralamalar "özünde yanıltıcı" diye anılıyor [W] https://eksisozluk.com/turkiyenin-en-iyi-universiteleri--1290755
- Akademik sıralamaların öğrenci kararındaki payı sınırlı; eğitim kalitesi, şehir, iş imkânı öne çıkıyor [A] (YÖK öğrenci anketi haberi ve tercih faktörleri çalışmaları) https://www.hurriyet.com.tr/egitim/yokten-kapsamli-arastirma-ogrencilerin-yuzde-72si-universitesinden-memnun-42707119
- **Hiçbir tercih robotu ranking göstermiyor** [W] univerlist ("URAP/QS/THE yer almamaktadır"), canlikoc, YÖK Atlas → boş alan.
**Dürüst cevap:** URAP'ı **sıralama tablosu olarak yayımlamak gürültüdür** — 198 satırlık bir liste, "en iyi üniversiteler" başlığı ya da programları URAP'a göre dizmek hem markanın "öznel sıralama yok" ilkesini deler hem de öğrencinin sormadığı soruya cevap verir. **Ama tek bir bağlamsal satır olarak gerçek bir acıyı dindirir:** "bu üniversite ciddi bir yer mi?" sorusu kıyas anında soruluyor ve bugün cevabı kulaktan dolma.
**Önerilen uygulama (kolaylık ölçütüne uyar, tek satır):**
- Yer: `/universite/[slug]` sayfasında başlığın altında tek satır; liste satırında **değil** (24 satırlık metin diyeti bozulmasın).
- Metin kalıbı: "URAP Türkiye 2025-2026: **N. / 198** — akademik yayın ve araştırma performansını ölçer; eğitim kalitesini veya iş bulma oranını ölçmez." + `https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025` bağlantısı (izin koşulu: aktif bağlantı/atıf, brief §4).
- Yapılmayacaklar: "en iyi üniversite" başlığı, URAP'a göre program sıralama, hedefe göre filtre, LLM prompt'una URAP sokmak (havuz kuralı ve metin diyeti bozulur).
- Veri işi: yıllık tek PDF ayrıştırma (`docs/ekip-raporlari/2026-09-21/06-uni-veri.md:62` planı hazır) — **M**, yılda bir tekrar.
---
## Ek: erişilemeyenler ve sınırlar
- **YouTube yorumları alınamadı** — video sayfası yorum içeriği döndürmüyor (https://www.youtube.com/watch?v=Yb7agCv-hs8, yalnızca başlık görüldü). "Ücretsiz tercih danışmanlığı + yapay zekâ" vaadi başlıkta doğrulandı [W]; yorum verisi **bulunamadı**.
- **Technopat "Tercih yaptım, pişmanım"** başlığı HTTP 403 verdi — erişilemedi.
- **DonanımHaber** iki başlık açıldı ama fetch yalnızca ilk mesajı getiriyor; biri 2009, biri 2016 tarihli — **güncel acı için kullanılmadı**.
- **Reddit'te (r/Turkey, r/YKS) tercih konulu güncel başlık bulunamadı** — arama yalnızca araç sitelerini döndürdü; bu kanalda **veri bulunamadı**.
- Ek yerleştirme rakamları (110.053) yalnızca haber özetinden [A]; ÖSYM birincil belgesinden **doğrulanmalı**.
- MEB'in Ağustos 2026 "para taleplerine itibar etmeyin" uyarısı **tercih danışmanlığıyla ilgili değil** (firma dolandırıcılığı) — kullanılmadı, yanlış atıf riski nedeniyle not düşüldü.
---
## Bilal'den istenen (3 madde)
1. **[BİLAL] Net/OBP arşivini vitrine çıkaralım mı?** "YÖK Atlas'ın 2026'da kaldırdığı 'son yerleşenin netleri' bizde 2023–2025 için duruyor" cümlesini pazarlamada kullanmak, önce verinin arşivden yayımlanmasının uygunluğu konusunda senin onayını ister (~10 dk karar, hukuki teyit ayrıca).
2. **[BİLAL] "Ücretsiz yolu da var" cümlesini siteye koyuyor muyuz?** Rakiplerin sustuğu yer burası; dürüstlük konumunu en çok güçlendiren, satışı en çok zorlayan tek cümle (~10 dk karar).
3. **[BİLAL] URAP kararı: tablo değil tek satır.** `/universite/[slug]` sayfasında tek bağlamsal satır + atıf bağlantısı; "en iyi üniversiteler" listesi yapılmaz (~5 dk onay).

View File

@@ -0,0 +1,273 @@
# 24'lük liste: nasıl oluşuyor, bize kaça mal oluyor, daha ne sunabiliriz
Gece vardiyası 2026-09-22 · Tur 1 · yapay zekâ mühendisi
Gerçek LLM çağrısı **yapılmadı** (para harcanmadı). Ölçüm yöntemi Bölüm A-2'de.
## 5 maddelik özet
1. **Yapay zekâ listeyi kurmuyor, listeyi dolduruyor.** 24 satırın hangi programlardan seçileceğini, kaç tanesinin hangi dilimde olacağını, satırların sırasını, risk ve trend cümlelerini **kod** belirliyor. Modelin tek işi hazır havuzdan seçmek ve satır başına bir kısa cümle gerekçe yazmak.
2. **Bir liste üretimi bize 1,7–2,1 kuruş.** (ölçüldü: 5 temsilî profil; fiyat OpenRouter'dan 22 Eyl 2026'da doğrulandı). Revizyon 2,4 kuruş, danışmana bir soru 0,6–1,6 kuruş.
3. **299 TL'lik paketin yapay zekâ maliyeti en kötü ihtimalle 0,91 TL** — cironun **binde 3'ü**. Yani kredi sistemi bizi bir maliyetten korumuyor; kredi tamamen bir fiyatlandırma aracı.
4. **Evet, gerçekten öyle.** Kodda doğruladım: paketi olmayan öğrenci 5 deneme kredisinin 3'ünü yakıyor ve 24 satırın 21'inin yorumu (gerekçe/risk/trend) kilitli geliyor. Ham veri (bölüm adı, üniversite, geçmiş taban sıralamaları) 24 satırın hepsinde açık. **Hükmüm: teaser doğru, ama teaser'ı deneme kredisiyle ücretlendirmek yanlış — maliyetimiz 2 kuruşken öğrencinin denemesini 3 kredilik bir duvara çarptırıyoruz.**
5. **Eval seti yok, çıktı denetimi yok.** Repoda tek bir test dosyası bile yok; "garanti/yerleşirsin" yasağı yalnızca prompt'ta yazıyor, üretilen metinde kontrol edilmiyor. Maliyeti sıfır olan iki açık.
---
# BÖLÜM A — Liste nasıl oluşuyor
## A-1. Zincir: sihirbazdan listeye
Öğrenci sihirbazda 4 şey söylüyor: **başarı sıralaması + puan türü**, **ilgi alanları**, **iller**, **devlet/vakıf**.
Sonra sırayla şunlar oluyor — **1., 2., 3. ve 6. adımlarda yapay zekâ yok**:
**1. Adaylar veritabanından çekiliyor** (`src/lib/db.ts:107` `dilimAra`)
Öğrencinin sıralamasına göre bütün programlar üçe bölünüyor:
| Dilim | Kural | Anlamı |
|---|---|---|
| Hayal | Taban sırası öğrencinin sırasından **daha iyi** | Geçen yıl buraya daha iyi dereceyle girilmiş |
| Dengeli | Taban sırası öğrencinin sırası ile **1,4 katı** arası | Tam bandında |
| Güvenli (kodda `garanti`) | Taban sırası **1,4 katından daha kötü** | Sıralamasının belirgin altında kapanmış |
Her dilimden en fazla 60 program çekiliyor, sınıra en yakından uzağa doğru sıralı. İl ve devlet/vakıf filtresi SQL'de, ilgi alanı filtresi sonra JavaScript'te uygulanıyor.
**2. Havuz 24'ü bulmuyorsa filtreler kademeli gevşiyor** (`src/lib/rapor-havuzu.ts:89` `havuzOlustur`)
1. Önce tam filtre denenir (iller + alan + tip).
2. 24 çıkmazsa **ilgi alanı** gevşer — aynı illerde, alan dışı programlarla doldurulur.
3. Hâlâ çıkmazsa **il** gevşer — il filtresi kalkar, ilgi alanına geri dönülür.
4. O da çıkmazsa ikisi birden gevşer.
Gevşetme olduysa prompt'a "bu gevşetildi, seçilene öncelik ver" notu ekleniyor ve ekranda dürüstçe belirtiliyor (`kapsam.uyarlandi`).
**3. Havuz 60 programa kırpılıyor** (dilim başına en fazla 20 — `PROMPT_LIMIT_DILIM`). Prompt'a giden şey bu: 60 program, her biri için son 4 yılın taban sıralaması + 2025 kontenjan/yerleşen.
**4. Liste iskeleti koddan geliyor** (`dilimHedefiHesapla`)
İdeal dağılım **5 hayal / 13 dengeli / 6 güvenli = 24**. Bir dilimde yeterli aday yoksa eksik, kapasitesi kalan dilimlere dağıtılır (öncelik: dengeli → güvenli → hayal). Örnek ölçümüm: 5.000. sıradaki tıp adayında havuz 48 programa düştü ve iskelet **7/8/9** oldu — hâlâ 24 satır.
**5. Burada, ve yalnızca burada, yapay zekâ devreye giriyor**
Modele giden talimat (`src/lib/ai/rapor.ts:64`): "Bu havuzdan tam 5 hayal, 13 dengeli, 6 güvenli program seç; her biri için **en fazla 15 kelimelik tek cümle** gerekçe yaz; artı 2 cümlelik genel değerlendirme ve 2-3 uyarı."
**6. Model cevap verince kod her şeyi yeniden ele alıyor** (`normalizeEt`, `rapor.ts:129`)
- Havuzda olmayan bir program kimliği geldiyse **atılır**.
- Aynı program iki kez geldiyse ikincisi **atılır**.
- Model bir programı yanlış dilime koyduysa **kod onu gerçek dilimine taşır**.
- Satırların 1'den 24'e sırası **koddan** atanır (dilim içinde iyi tabandan kötüye).
- Her satırın **risk notu** ve **trend özeti** gerçek sıra geçmişinden **kod tarafından** yazılır (`src/lib/risk.ts`, `src/lib/trend.ts`) — model bunlara hiç dokunmaz.
**7. Sayılar tutmazsa**: bir kez daha denenir (ikinci tam API çağrısı). O da tutmazsa **kurtarma** devreye girer: eksik dilimler havuzdan deterministik doldurulur, o satırların gerekçesi şablon cümledir. Yani **liste her koşulda kurulur**; ekrana hata gelmez.
**8. Paketi yoksa maskelenir** (`src/lib/rapor-maske.ts`) — ayrıntısı A-4'te.
### Özetle: yapay zekâ ne yapıyor, ne yapmıyor
| Yapıyor | Yapmıyor |
|---|---|
| Havuzdaki 60 program arasından 24'ünü seçiyor | Program uydurmuyor (uydursa bile kullanıcıya ulaşamıyor) |
| Satır başına 1 kısa cümle gerekçe yazıyor | Sıralama/taban puanı hesaplamıyor |
| 2 cümlelik genel değerlendirme + 2-3 uyarı yazıyor | Satırların sırasını belirlemiyor |
| | Risk ve trend cümlelerini yazmıyor |
| | 5/13/6 dağılımını belirlemiyor |
| | Hangi programın hangi dilimde olduğuna karar vermiyor |
---
## A-2. Gerçek API maliyeti (ölçüm, tahmin değil)
### Yöntem
Geçici bir ölçüm betiği yazdım (koştu, sonra sildim — repoda kalmadı). Betik gerçek `yokatlas.db` üzerinden `havuzOlustur`'u çağırıp **raporUret'in modele göndereceği metnin birebir aynısını** kurdu ve token saydı. **Hiçbir LLM çağrısı yapılmadı.**
**Doğrulanan fiyat** (OpenRouter public models API, 22 Eyl 2026, `curl https://openrouter.ai/api/v1/models`):
```
deepseek/deepseek-v4-flash
girdi (prompt) : $0,000000049 / token → $0,049 / 1 milyon token
çıktı (completion) : $0,000000098 / token → $0,098 / 1 milyon token
önbellekli girdi : $0,0000000098 / token (şu an kullanmıyoruz)
```
**Kur**: 1 USD = 48,82 TL (open.er-api.com, 22 Eyl 2026).
**Tek uyarı**: DeepSeek'in kendi tokenizer'ı npm'de yok; sayımı `o200k_base` ile yaptım. Türkçe metinde sapma tipik olarak ±%15'tir. Rakamlar 2 kuruş mertebesinde olduğu için bu sapma hiçbir sonucu değiştirmiyor.
### Ölçüm sonuçları — liste üretimi
| Profil | Havuz | İskelet | Girdi (token) | Çıktı (token) | Maliyet (USD) | Maliyet (TL) |
|---|---|---|---|---|---|---|
| Sayısal 45.000 · Mühendislik · İst+Ank · devlet | 60 | 5/13/6 | 6.734 | 946 | $0,000423 | **2,1 kuruş** |
| Eşit Ağırlık 120.000 · İktisat+Hukuk | 60 | 5/13/6 | 6.673 | 946 | $0,000420 | **2,1 kuruş** |
| Sözel 250.000 · Eğitim · İzmir | 60 | 5/13/6 | 6.591 | 946 | $0,000416 | **2,0 kuruş** |
| Sayısal 5.000 · Sağlık & Tıp | 48 | 7/8/9 | 5.109 | 946 | $0,000343 | **1,7 kuruş** |
| Sayısal 800.000 · 3 alan · Konya | 50 | 5/13/6 | 5.777 | 946 | $0,000376 | **1,8 kuruş** |
Girdinin neredeyse tamamı havuz JSON'u: 6.734 token'ın **6.048'i** (%90) 60 programın verisi. Sistem talimatı 523 token, sabit.
### Ölçüm sonuçları — diğer çağrılar
| Çağrı | Girdi | Çıktı | Maliyet |
|---|---|---|---|
| Liste üretimi (tipik) | 6.700 | 946 | **2,1 kuruş** |
| Liste üretimi, model şemaya uymayıp 2. deneme olursa | 13.400 | 1.892 | **4,1 kuruş** |
| Revizyon (önceki liste özeti de prompt'a girer, +1.251 token) | 7.937 | 946 | **2,4 kuruş** |
| Danışman: ilk soru, kısa cevap | 1.834 | ~300 | **0,6 kuruş** |
| Danışman: ilk soru, tavan cevap (1024 token) | 1.834 | 1.024 | **0,9 kuruş** |
| Danışman: dolu geçmişle (12 mesaj), tavan cevap | 4.474 | 1.024 | **1,6 kuruş** |
Danışman sohbetinin sistem prompt'u 1.793 token; bunun **1.195'i** 24'lük listenin özeti (her soruda yeniden gönderiliyor).
---
## A-3. Birim ekonomi
Paket **299 TL = 60 kredi**. Liste = 3 kredi, revizyon = 3 kredi, danışmana bir soru = 1 kredi.
Kredi başına en pahalı kullanım **sohbet** (1,6 kuruş/kredi); liste ise 2,1÷3 = **0,7 kuruş/kredi**.
Yani "en kötü senaryo" = kullanıcının krediyi mümkün olduğunca sohbete yatırması.
| Senaryo | Kredi dağılımı | Yapay zekâ maliyeti | Ciro | Marj |
|---|---|---|---|---|
| **En kötü hâl** (1 liste + 57 soru, hepsi tavan cevap) | 3 + 57 | **0,91 TL** | 299 TL | **%99,70** |
| Yoğun kullanım (1 liste + 2 revizyon + 51 soru) | 3+6+51 | 0,88 TL | 299 TL | %99,71 |
| Liste avcısı (20 liste, hiç soru yok) | 20 × 3 | 0,41 TL | 299 TL | %99,86 |
| Tipik kullanım (1 liste + 1 revizyon + 15 soru) | 3+3+15 | 0,21 TL | 299 TL | %99,93 |
| **Top-up 30 kredi** (hepsi soru) | 30 | 0,47 TL | 129 TL | %99,64 |
| **Deneme kullanıcısı** (1 liste + 2 soru, hiç ödeme yok) | 5 | **5,2 kuruş** | 0 TL | — |
**Okunuşu**: 299 TL'lik bir paketin yapay zekâ faturası **1 lirayı geçmiyor**. 1.000 kişi girip sadece deneme kredisini yakıp gitse toplam maliyet **52 TL**.
(Marjlar yalnızca LLM maliyetini içerir; iyzico komisyonu, KDV ve sunucu maliyeti bu tabloda yok — onlar benim alanım değil.)
---
## A-4. "Sadece 3'ünü mü gösteriyoruz?"
**Kodda gerçekten böyle. Doğruladım.**
`src/features/rapor/rapor-actions.ts:190` ve `:240`:
```ts
rapor: user.hasPaket ? sonuc : raporMaskele(sonuc),
```
`src/lib/rapor-maske.ts` ne yapıyor (`ACIK_SATIR = 3`):
| 24 satırda ne var | Paketsiz kullanıcı görüyor mu? |
|---|---|
| Bölüm adı, üniversite, il, devlet/vakıf | ✅ **24 satırın hepsi** |
| Geçmiş yılların taban sıralamaları (grafik verisi) | ✅ **24 satırın hepsi** |
| Kaç program bulundu / dağılım uyarlandı mı | ✅ Açık |
| Yapay zekânın yazdığı **gerekçe** | ❌ Yalnız ilk 3 satır |
| **Risk notu** ("sırana yakın", "belirgin altında") | ❌ Yalnız ilk 3 satır |
| **Trend özeti** ("45B'den 38B'ye indi") | ❌ Yalnız ilk 3 satır |
| Genel değerlendirme | ⚠️ İlk 2 cümlesi, sonra "…" |
| Uyarılar | ⚠️ 1 tanesi; kalanların yalnız sayısı |
Kilitli metinler istemciye **hiç inmiyor** (sunucuda maskeleniyor) — bu teknik olarak doğru yapılmış, kaynak koda bakarak da açılamaz.
Yani: **21 satırın yorumu kilitli (%87,5)**, ama o 21 satırın ham verisi açık. Öğrenci hangi bölümleri önerdiğimizi ve o bölümlerin geçmiş sıralamalarını görüyor; **neden** önerdiğimizi göremiyor.
### Kritik soru: paketsiz kullanıcı bunun için 3 kredi harcıyor mu?
**Evet.** `rapor-actions.ts:109-110`'daki yorum bunu açıkça söylüyor: *"Paket şartı yok: üretim kredi bazlı (yeni kullanıcının 5 deneme kredisi burada yanmaya başlar). Paketsize dönen rapor maskelenir."* Kredi düşümü (`:153`) maskelemeden önce ve ondan bağımsız.
Sonuç: girişte tanımlanan **5 deneme kredisinin 3'ü** (yani %60'ı) tek bir maskeli liste için yanıyor. Geriye 2 kredi kalıyor = danışmana 2 soru. İkinci bir liste denemesi mümkün değil.
### Hükmüm (tek cümle)
**İlk 3 satırı açık göstermek doğru bir teaser, ama 2 kuruşa mal olan bir üretimi öğrencinin deneme bakiyesinin %60'ıyla ücretlendirmek, korumadığımız bir maliyeti bahane ederek ürünü denemeyi zorlaştırmaktır — liste üretimi paketsiz kullanıcı için ücretsiz olmalı, deneme kredisi asıl değerin yaşandığı danışman sohbetine ayrılmalı.**
(Bu bir fiyatlandırma kararı → **[BİLAL]**. Kötüye kullanım riski kredi yerine kullanıcı başına günlük üretim sınırıyla kapatılır; `reports.userId` zaten tekil, `uretimKilidiAl` eşzamanlı üretimi zaten engelliyor. 10.000 deneme kullanıcısı × 1 ücretsiz liste = **207 TL** toplam maliyet.)
---
## A-5. Kalite ve risk — kısa
| Konu | Durum |
|---|---|
| **Havuz dışına çıkamama** | ✅ **Sağlam.** `normalizeEt` (`rapor.ts:129`) her kimliği havuz haritasında arıyor; bulunmayan atılıyor. Model ne uydurursa uydursun kullanıcıya ulaşamaz — mimari garanti, prompt'a güven değil. |
| **Model uydurursa ne olur** | Uydurma atılır → sayı tutmaz → 2. deneme (+2 kuruş) → hâlâ tutmazsa **kurtarma**: eksik satırlar havuzdan deterministik doldurulur, gerekçe şablon cümleye düşer. Kullanıcı hata görmez. |
| ⚠️ **Kurtarma ölçülmüyor** | Kurtarma yalnız `console.warn`'a yazılıyor. Kaç listede devreye girdiğini, yani kaç öğrenciye şablon gerekçe gittiğini **bilmiyoruz**. Bu tek satırlık bir analitik olayı ile ölçülebilir. |
| ⚠️ **Vaat dili çıktıda denetlenmiyor** | Prompt "garanti/kesin/yüzde yüz deme" diyor; **üretilen metinde hiçbir kontrol yok** (`src/lib/ai/` altında tek bir yasak-ifade filtresi yok — grep ile doğruladım). Prompt tek başına yeterli değildir. **Maliyeti sıfır**: üretimden sonra bir regex denetimi, ihlal varsa logla + satırı şablona düşür. |
| Kayıtlı tadımlık metinleri | ✅ Temiz. `app.db` `tadimlik_havuzu`: 522 satır, yasak ifade içeren **0** satır (SQL ile doğruladım). |
| **Zaman aşımı ve iade** | ✅ Sağlam. Tek çağrı 60 sn (`cagri.ts`), hata yolunda kredi iadesi var (`rapor-actions.ts:212`, `:339`; sohbet `soru/route.ts:313`), yarım kalan sohbet cevabı kaydediliyor ve kredi iade ediliyor. ⚠️ Tek delik, kodda da kabul edilmiş: platform fonksiyonu 120 sn'den önce öldürürse iade kodu hiç koşamaz. **Prod'daki server action süre sınırı doğrulanmalı.** |
| **Eval seti** | ❌ **Yok.** Repoda tek bir `.test.ts`/`.spec.ts` dosyası yok, test koşucusu (vitest/jest) `package.json`'da tanımlı değil. Prompt ya da model değiştiğinde "daha mı iyi oldu" sorusunun ölçülebilir cevabı bugün yok. |
---
# BÖLÜM B — Yapay zekâ API'siyle daha ne sunabiliriz
Ölçüt Bilal'in bu geceki tek ölçütü: **akışı kolaylaştırıyor mu, yoksa yeni ekran/karmaşa mı ekliyor?** Ucuz ve sadeleştiren önde, pahalı/gösterişli sonda.
### 1. Sihirbazı tek cümleyle doldurma — "Ne istediğini kendi cümlenle yaz"
**Acı**: Öğrenci 4 adımlı sihirbazı doldurmadan hiçbir şey göremiyor. En büyük terk noktası girişin kendisi.
**Ne olur**: Tek bir metin kutusu. *"450 bin sıradayım, İzmir'de kalmak istiyorum, bilgisayarla ilgili bir şey okumak istiyorum."* → model bunu ilgi alanı + il + tip seçimlerine çevirir, sihirbaz **ön-doldurulmuş** açılır, öğrenci isterse düzeltir. Sihirbaz kaybolmaz, sadece boş başlamaz.
**Ek API maliyeti**: girdi ~600 token (sistem + kategori listesi + cümle), çıktı ~80 → **0,2 kuruş/deneme**. 10.000 deneme = 20 TL.
**Kredi**: **0** — bu bir dönüşüm yatırımı, kullanıcıdan ücret alınacak yer değil. Kötüye kullanım oturum başına günlük sayaçla kapatılır.
**Büyüklük**: **S** (tek şema, tek çağrı; çıktı zaten var olan `sihirbazDogrula` ile doğrulanır — uydurma kategori geçemez).
**Akış**: ✅ **Sadeleştirir.** 4 karar → 1 cümle + onay.
### 2. Danışmanda hazır soru çipleri (LLM'e hiç gitmeden)
**Acı**: Liste geldikten sonra boş bir sohbet kutusu duruyor. Öğrenci ne soracağını bilmiyor; 1 kredi harcamaya da çekiniyor. Danışman büyük ihtimalle en az kullanılan özellik. *(Kullanım oranı `analitik` ajanından doğrulanmalı — bende Rybbit erişimi yok.)*
**Ne olur**: Listenin kendi verisinden üretilmiş 3 hazır soru: *"En riskli 3 tercihim hangisi?"*, *"3. ile 11. sırayı kıyasla"*, *"Vakıf tercihlerimin burs durumu ne?"*. Tıklayınca kutuya yazılır.
**Ek API maliyeti**: **0 kuruş.** Çipler şablondan + liste verisinden koddan üretilir; LLM'e hiç gitmez. (Dürüst olayım: bu bir LLM özelliği değil — ama LLM'i *kullandıran* özellik.)
**Kredi**: değişmez (soru sorulunca zaten 1 kredi).
**Büyüklük**: **S**.
**Akış**: ✅ **Sadeleştirir.** Boş kutu yerine üç tıklanabilir başlangıç.
### 3. Revizyonda hazır niyet çipleri
**Acı**: Revizyon 3 kredi ve öğrenci "ne değişsin" kutusuna ne yazacağını bilmiyor; kötü yazılmış bir istek 3 krediyi boşa yakıyor.
**Ne olur**: *"Vakıfları çıkar" · "Sadece İstanbul" · "Daha güvenli olsun" · "Daha çok hayal ekle"* çipleri, altında serbest metin. Çip metni doğrudan mevcut `revizyonNotu` alanına gider.
**Ek API maliyeti**: **0** — revizyon çağrısı zaten var, prompt'u değişmiyor.
**Kredi**: değişmez (3 kredi).
**Büyüklük**: **S**.
**Akış**: ✅ **Sadeleştirir.** Ve boşa yanan 3 kredileri azaltır.
### 4. Paket alındığında veliye giden tek paragraf
**Acı**: Parayı veli ödüyor ama listeyi öğrenci görüyor. Velinin elinde "bu 299 TL ne aldı" sorusunun cevabı yok. Bu bir güven ve iade sorunu.
**Ne olur**: Paket aktifleşince gönderilen e-postada, listenin altında **tek paragraf**: *"Çocuğunuzun listesi 24 tercihten oluşuyor; ilk 5'i iddialı, ortadaki 13'ü sıralamasının tam bandında, son 6'sı ise sıralamasının belirgin altında kapanan güvenli tercihler. Liste tamamen bu yılın resmî YÖK Atlas verisine dayanıyor."* Rakamlar şablondan, bağlayıcı cümle modelden.
**Ek API maliyeti**: girdi ~1.400, çıktı ~250 → **0,45 kuruş/paket**. 1.000 paket = 4,5 TL.
**Kredi**: **0** (paketin içinde, tek sefer).
**Büyüklük**: **M** (e-posta şablonuna bir bölüm + tetikleyici).
**Akış**: ✅ **Yeni ekran yok** — e-postada yaşıyor, siteye hiç dokunmuyor.
### 5. URAP sıralamasını havuza ekleyip gerekçede kullandırmak
**Acı**: Brief'teki niyet — *"tercih yaparken kolayca metrikleri görsün"*. Bugün model bir üniversitenin akademik gücünü hiç bilmiyor; gerekçeleri yalnız sıralama ve şehir üzerinden yazıyor.
**Ne olur**: Havuz JSON'una program başına tek alan (`urap: 42`). Model gerekçede kullanabilir: *"İzmir'de kalmak istiyorsun, bu üniversite URAP'ta ilk 50'de."* Ekranda satır başına küçük bir rozet + URAP'a atıf linki (izin koşulu).
**Ek API maliyeti**: 60 program × ~3 token = **+180 girdi token ≈ +0,001 kuruş**. Pratikte sıfır.
**Kredi**: değişmez.
**Büyüklük**: **M** — ve ağırlık veri tarafında (`veri-muhendisi`), yapay zekâ tarafı tek alan.
**Akış**: ✅ **Yük bindirmez** — satırda bir rozet, yeni ekran yok. Ama şart: rakam **koddan** basılır, modele yalnız bağlam olarak verilir (LLM'e sayı yazdırmayız).
### 6. ❌ Satır içi "Bu bölüm bana uygun mu?" butonu — **ÖNERMİYORUM**
**Ne olurdu**: Her satırda bir buton; tıklayınca model o program + adayın profili için 2 cümle yazar. Maliyet ucuz (0,27 kuruş/tık), teknik olarak basit.
**Neden eliyorum**:
1. **Danışman sohbetiyle birebir aynı işi yapıyor** — aynı soruyu sohbete yazınca zaten daha iyi cevap alıyor.
2. **24 satır = 24 buton.** Bilal'in "kullanıcıyı boğma" ölçütünün tam karşıtı: ekrana 24 yeni karar noktası koyuyor.
3. Her tık 1 kredi olursa öğrenci tıklamaya korkar; 0 kredi olursa danışmanın değerini yer.
Aynı gerekçeyle **"24 satırın her biri için bir paragraf açıklama"** fikrini de eliyorum: maliyeti düşük (~3,3 kuruş) ama kimse 24 paragraf okumaz, ve kodda zaten bilinçli bir "metin diyeti" kuralı var (`rapor.ts:83`).
### Özet tablo
| # | Öneri | Ek API maliyeti | Kredi | Boyut | Akışa etkisi |
|---|---|---|---|---|---|
| 1 | Tek cümleyle sihirbaz ön-doldurma | 0,2 kuruş | 0 | S | ✅ Sadeleştirir |
| 2 | Danışmanda hazır soru çipleri | 0 | değişmez | S | ✅ Sadeleştirir |
| 3 | Revizyonda hazır niyet çipleri | 0 | değişmez | S | ✅ Sadeleştirir |
| 4 | Veliye tek paragraf (e-posta) | 0,45 kuruş | 0 | M | ✅ Ekran eklemez |
| 5 | URAP alanı havuzda + gerekçede | ~0 | değişmez | M | ✅ Ekran eklemez |
| 6 | Satır içi "bana uygun mu?" butonu | 0,27 kuruş | 1 | M | ❌ **Elendi** |
---
## Bilal'den istenen (3 madde)
1. **[BİLAL] Liste üretimi paketsiz kullanıcıya ücretsiz olsun mu?** Bize 2 kuruş, öğrenciye deneme bakiyesinin %60'ı; kredi bizi bir maliyetten korumuyor. Kararın: evet/hayır. *(5 dakika)*
2. **[BİLAL] Sihirbazı "tek cümleyle doldur" kutusuyla açmak sana doğru geliyor mu?** Bu gecenin en ucuz (0,2 kuruş) ve akışı en çok kısaltan önerisi; onay verirsen CTO şartnameye çevirir. *(5 dakika)*
3. **[KARAR] İki sıfır maliyetli açığı kapatmama izin ver**: üretilen metinde vaat dili denetimi + kurtarmanın kaç kez devreye girdiğinin ölçümü. İkisi de küçük, ikisi de ölçülebilir; onaylarsan bir sonraki turda dal açarım. *(2 dakika)*

View File

@@ -0,0 +1,241 @@
# 05 · URAP Türkiye Sıralaması — keşif, eşleştirme ve en küçük işe yarar adım
**Rol:** veri-muhendisi · **Tarih:** 22 Eylül 2026 · **Kapsam:** BACKLOG #8 (üniversite sayfası zenginleştirme) ön koşulu + BACKLOG #9 teşhisi
## Özet (5 madde)
1. **Eşleştirme sorunu YOK.** URAP 2025-2026 genel sıralamasındaki **198 üniversitenin 198'i** (%100) bizim slug'ımızla eşleşti; dahası 198'inin **adı harfi harfine bizim DB'deki yazımla aynı**. Takma ad tablosu, normalleştirme kuralı, elle kontrol gerekmiyor. (OpenAlex'te 201/229 idi; URAP bundan çok daha temiz çünkü URAP da YÖK yazımını kullanıyor.)
2. **Veri, PDF ayrıştırmadan alınabiliyor.** Site bir Meteor SPA; tüm tablo tek bir Mongo dokümanının `data` dizisinde (198 satır × 8 gösterge puanı + toplam puan + şehir + web adresi) ve `rankings.byurlandgroup` yayınıyla geliyor. Geçen geceki rapordaki "basın PDF'i ayrıştırılmalı, ~4 saat" tahmini artık geçersiz.
3. **E-postadaki "güncelleme olursa sizde de direkt uygulanmış olur" beklentisi bu URL için gerçekleşmez.** URAP'ın adresleri yıla çivili (`/Rankings/2025-2026/GENEL-SIRALAMASI-2025`); son 7 yılın her biri ayrı grup + ayrı URL. Yeni yıl çıkınca **hem veriyi hem linki** biz güncelleyeceğiz. Yılda bir, ~30 dakika.
4. **En küçük işe yarar adım ~3 saat** (22 değil): üniversite sayfasına tek sayı — "URAP Türkiye sıralaması: 18 / 198" + tek cümlelik kaynak satırı. Yeni DB dosyası, yeni tablo, göç, ayrıştırıcı, cron **gerekmiyor**; `src/lib/uni-koordinatlar.ts` deseninde 198 satırlık sabit yeterli.
5. **BACKLOG #9'un kök nedeni bulundu ve URAP'la çapraz doğrulandı:** hata `unitur-onar.ts`'te ya da 2026 tazelemesinde değil, **ilk CSV ingest'inde** doğmuş; tazeleme onu sadakatle kopyalamış. Etki **100 satır** `unitur` + **26 satır** `il`. URAP'ın kendi devlet/vakıf ayrımıyla 198 üniversitenin **198'inde bizim etiketimiz doğru** — yani hata yalnız URAP listesi dışındaki KKTC/yurt dışı kurumlarda.
---
## 1. URAP verisinde ne var
**Kaynak:** `https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025` (22 Eyl 2026, tarayıcı paneliyle okundu; sayfa JS ile çiziliyor, `curl` boş HTML döndürür).
| Ne | Değer |
|---|---|
| Üniversite sayısı | **198** (devlet 125 + vakıf 73; URAP'ın kendi iki alt tablosu tam olarak 198'e tamamlanıyor) |
| Kolonlar | `rank`, `name`, `sehir`, `url` (üniversite web adresi), `lat`/`lng`, 8 puan kolonu + `total` |
| 8 puan kolonu | Makale, Atıf, Bilimsel Doküman, Doktora, Öğretim Üyesi/Öğrenci, Uluslararası İşbirliği, Yurtiçi İşbirliği, TÜBİTAK Proje |
| Toplam puan aralığı | 1.152,91 (Koç) → 70,82 (Antalya Belek) |
| Devlet/vakıf ayrımı | **Var** — ayrı sıralama tabloları: `DEVLET ÜNİVERSİTELERİ-2025` (125), `VAKIF ÜNİVERSİTELERİ-2025` (73) |
| Diğer kesitler | Tıp fakültesi olan/olmayan, 2000 öncesi/sonrası kurulan, 6.000'den az öğrencisi olan — yılda 8 tablo |
| Yıl arşivi | 2019-2020 → 2025-2026, **7 yıl**, her biri ayrı URL |
| Alan (bölüm) bazlı sıralama | **2025-2026 için YOK.** `/Rankings/2025-2026/fields` sayfası yalnız yukarıdaki 7 kesiti listeliyor; sitenin altbilgisindeki "ALANLARA GÖRE TÜRKİYE SIRALAMALARI" bağlantısı **2019-2020** yılına ait. Yani "bu bölümde bu üniversite kaçıncı" sorusuna URAP'la cevap veremeyiz. |
**Veri dönemi (URAP Yöntem sayfası, 22 Eyl 2026'da okundu):** 15 gösterge; makale sayımı **2024**, atıf/doküman/işbirliği **2020-2024**, doktora mezunu **2023-2024**, öğrenci ve öğretim üyesi **2024-2025**, TÜBİTAK projeleri **2019-2023**. Kaynaklar: InCites (Web of Science), YÖK, TÜBİTAK ARDEB. Sıralamanın adı "2025-2026" ama **ölçtüğü dönem 2020-2024** — dipnotta bunu gizlememek gerekir.
**Veri ucu (tazeleme betiği için).** Sayfa Meteor/DDP kullanıyor; REST yok. Tablonun tamamı `Rankings` koleksiyonundaki tek dokümanın `data` alanında:
```
Meteor.subscribe('rankings.byurlandgroup', 'GENEL-SIRALAMASI-2025', '2025-2026')
Rankings.findOne({url:'GENEL-SIRALAMASI-2025'}).data // 198 nesne
```
Toplam yük ~40 KB. Büyük dosya indirme yok; protokolün "büyük veri indirme" sınırına takılmıyor.
## 2. Eşleştirme testi — yöntem ve sonuç
**Yöntem.** URAP adı → `uniAdiNormalize` (sondaki parantezi at, `src/lib/harita.ts:32`) → `turkishSlugify` (`src/lib/slug.ts:6`) → bizim `programs.universite` üzerinden aynı kuralla üretilen slug kümesiyle karşılaştır. Yani **yeni bir normalleştirme kuralı yazılmadı**, sitenin hâlihazırda `/universite/[slug]` üretirken kullandığı kural uygulandı.
| Aşama | Yöntem | Eşleşen |
|---|---|---|
| 1 | Birebir slug | **198 / 198** |
| 2 | Gevşek anahtar (yedek) | gerek kalmadı |
| | **Toplam** | **198 / 198 (%100 URAP tarafı; 198/229 = %86,5 bizim tarafımız)** |
**Ek kontrol:** eşleşen 198 kaydın kaçında URAP yazımı bizim yazımımızdan farklı? **0.** `BEZM-İ ÂLEM VAKIF ÜNİVERSİTESİ`, `MANİSA CELÂL BAYAR ÜNİVERSİTESİ`, `İSTANBUL ÜNİVERSİTESİ-CERRAHPAŞA` gibi tuzaklı adlar dahil hepsi birebir aynı. Ad değişikliği sorunu da yok (URAP "AYDIN ADNAN MENDERES", "DEMİROĞLU BİLİM", "İSTANBUL ATLAS" gibi güncel adları kullanıyor — OpenAlex'in takıldığı 10 ad burada takılmıyor).
**Kural önerisi:** ek kural yok. Tek gereken, yıllık tazelemede eşleşmeyen satırın **sessizce düşmemesi**: betik/kontrol eşleşmeyen her URAP adını adıyla listelemeli, tahminle yakın slug'a bağlamamalı.
**Üretilen dosyalar (scratchpad, repoya konmadı):**
`/private/tmp/claude-501/-Users-bilalgursen-Desktop-kolaytercih/0a5eb19a-af4b-4ddc-83ed-e78660f30fd8/scratchpad/urap-2025.txt` (198 satır: sıra|ad|şehir|toplam puan) · `.../eslestir.mjs` (eşleştirme) · `.../fark.mjs` (yazım farkı) · `.../tur-capraz.mjs` (devlet/vakıf çapraz kontrolü) · `.../db-uni.txt` (DB'den çıkarılan 328 ham ad).
## 3. Kapsama boşluğu — bizde olup URAP'ta olmayan 31 üniversite
229 slug'ımızın 31'i URAP listesinde yok. Bu 31 kurumun toplam **1.660 program satırı** var: 21.493'ün **%7,7'si**.
| Neden | Kaç kurum | Örnek |
|---|---|---|
| KKTC ve yurt dışı kurumlar (URAP yalnız Türkiye'deki üniversiteleri sıralıyor) | 22 | Doğu Akdeniz (276 program), Yakın Doğu (205), Girne Amerikan (158), Uluslararası Balkan, Manas, Tiran New York |
| Yalnız meslek yüksekokulu olan vakıf kurumları | 4 | İstanbul Şişli MYO, Ataşehir Adıgüzel MYO, İzmir Konak MYO |
| Yeni / araştırma çıktısı henüz oluşmamış Türkiye üniversiteleri | 4 | Mudanya (78 program), Sivas Bilim ve Teknoloji, Türk-Japon BTÜ, Ankara Müzik ve Güzel Sanatlar |
| ÖSYM'de ayrı kurum gibi görünen özel kontenjan satırı | 1 | "İçişleri Bakanlığı ve Milli Savunma Bakanlığı adına… Sağlık Bilimleri Üniversitesinde eğitim alacaklar" |
**Öğrenci o sayfaya girince ne görmeli? Öneri: kutu her zaman görünsün, değeri ya sayı ya "Listede yok" olsun.**
- `—` **yazma.** "—" okuyucuya "puanı yok / kötü" gibi geliyor; oysa Doğu Akdeniz Üniversitesi kötü olduğu için değil, URAP Türkiye listesi KKTC'yi kapsamadığı için yok.
- Kutuyu **tümden gizlemek** de yanlış: 229 sayfanın 198'inde olan bir kutunun 31'inde hiç olmaması, öğrencinin "bende mi açılmadı" diye düşünmesine yol açar ve eksikliği görünmez kılar (protokol: eksik, eksik görünmeli).
- Önerilen metin, üç varyant — hangi nedene düştüğü zaten `unitur`'dan bilinir:
- KKTC/yurt dışı: **"URAP Türkiye sıralaması: listede yok — URAP yalnız Türkiye'deki üniversiteleri sıralıyor."**
- MYO / yeni üniversite: **"URAP Türkiye sıralaması: listede yok — 2025-2026 listesinde yer almıyor."**
- Sıralama/filtreleme: `/universiteler` hub'ında ilk sürümde URAP'a göre **sıralama ve rozet olmasın**. 31 kurumu listenin dibine iten bir sıralama, kapsama boşluğunu sessizce "kalitesizlik" gibi gösterir.
Nihai görünüm kararı tasarımcının; buradaki şart veri tarafının: değer yoksa sayı uydurulmaz, komşu yıldan/kurumdan kopyalanmaz, "0" ya da "199" yazılmaz.
## 4. Veri nerede dursun, nasıl tazelensin
### 4.1 Karar: veriyi kopyalayalım mı (a), yalnız link mi verelim (b)?
| | (a) Veriyi bizim tarafta tutmak + tarihli atıf | (b) Yalnız URAP'a link vermek |
|---|---|---|
| İzin | E-posta bunu **açıkça** veriyor: "…aktif bağlantı/atıf vermek kaydıyla **verilerimizi web uygulamanızda yayımlayabilirsiniz**" | Zaten herkesin hakkı; izin gerekmezdi |
| Öğrenciye faydası | Sayı sayfada görünür, 1 saniyede okunur; 24'lük listede/karşılaştırmada kullanılabilir | Öğrenci siteden çıkar, SPA'da 198 satırlık tabloda kendi üniversitesini arar — Bilal'in "kolayca görsün" hedefinin tersi |
| Güncellik riski | Bizde donmuş kalır → **dipnotta yıl yazmak zorunlu** | Her zaman güncel |
| İş | ~3 saat + yılda ~30 dk | ~15 dk |
| Bağımlılık | URAP sitesi çökse bile sayfa çalışır | URAP sitesi/URL'si değişirse ölü link |
**Öneri: (a).** İzin tam da bunun için istendi ve verildi; (b) hem izni ziyan eder hem "kolaylık" ölçütüne aykırıdır. (b)'yi (a)'nın içinde zaten uyguluyoruz: kutunun altındaki cümle URAP'ın kendi sayfasına aktif link verir.
**Ama e-postadaki beklenti düzeltilmeli.** "Bu şekilde verirseniz güncelleme olursa sizde de direkt uygulanmış olur" cümlesi, o URL'nin güncellendiği varsayımına dayanıyor. Sitenin yapısı bunu desteklemiyor: 7 yılın her biri ayrı grup ve ayrı adres (`GENEL-SIRALAMASI` 2021-2022, `-2022`, `-2023`, `-2024`, `-2025`). Yeni yıl **yeni bir adreste** yayımlanır; verdiğimiz link 2025-2026 tablosunda kalır. *(Bu, 7 yıllık URL desenine dayanan çıkarımdır — URAP'a tek cümleyle teyit ettirmek 5 dakikalık iş.)* Pratik sonucu: yılda bir kez veri + link birlikte güncellenir, bu zaten (a) yolunun takvimi.
### 4.2 Şema: yeni DB dosyası **gerekmiyor**
Geçen geceki `data/universiteler.db` + `uni_kimlik` + `uni_gosterge` tasarımı 8 kaynaklı, uzun biçimli bir gösterge deposu içindi. Tek kaynak ve tek sayı için fazla:
- Veri hacmi: 198 satır × 3 alan (~8 KB). SQLite'a koymanın hiçbir faydası yok — sorgu yok, birleştirme yok, filtre yok.
- `data/yokatlas.db`'ye **yazılamaz**: `ingest.ts` DB'yi baştan siliyor (`rmSync`, satır 26) ve dosya git'te izleniyor; her tazeleme binary diff üretir.
- Repoda **aynısının örneği var**: `src/lib/uni-koordinatlar.ts` (249 satır, slug→koordinat sabiti). Aynı desen.
**Önerilen ilk sürüm:**
```ts
// src/lib/urap-siralama.ts (tek seferlik üretilen sabit; elle düzenlenmez)
export const URAP_DONEM = "2025-2026";
export const URAP_TOPLAM = 198;
export const URAP_KAYNAK_URL =
"https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025";
/** URAP'ın sıralamayı yayımladığı tarih (dipnot bu tarihi gösterir). */
export const URAP_YAYIN = "2025-10"; // [doğrulanmalı — URAP basın bülteni tarihi]
export const URAP_SIRA: Record<string, { sira: number; puan: number }> = {
"koc-universitesi": { sira: 1, puan: 1152.91 },
"hacettepe-universitesi": { sira: 2, puan: 1096.48 },
// … 198 satır
};
```
Okuma tarafı: `getUniversiteBySlug` (`src/lib/katalog.ts:363`) dönüşüne `urap: URAP_SIRA[slug] ?? null` eklenir. `UniDetay` tipine bir alan. Başka hiçbir yere dokunulmaz.
**Geri alma:** dosyayı sil + tek alanı kaldır. Göç yok, `app.db`'ye dokunulmaz, `yokatlas.db` şeması değişmez. `app.db` göçü gerektiren hiçbir şey bu işte yok.
**Ne zaman DB'ye taşınmalı:** ikinci bir kaynak (YÖK İstatistik öğrenci sayısı, TÜBİTAK) eklendiğinde ya da "URAP'a göre sırala" gibi bir sorgu gerektiğinde. O gün geçen geceki `uni_gosterge` tasarımı doğru tasarımdır; bugün değil.
### 4.3 Tazeleme
**Sıklık: yılda bir, Ekim.** URAP Türkiye sıralamasını her Ekim yayımlıyor (7 yıllık grup deseni). Daha sık çekmenin anlamı yok — veri yıl içinde değişmiyor.
**İlk sürümde betik yazma.** Yılda bir koşacak bir DDP istemcisi (yeni bağımlılık: `simple-ddp` ya da elle SockJS) ~3 saat ve yeni bir bakım yükü. Aynı işi tarayıcı konsolunda tek satır yapıyor (yukarıdaki `Rankings.findOne(...).data`). Ekim'de 20 dakika:
1. `https://newtr.urapcenter.org/Rankings/<yeni-grup>/<yeni-url>` açılır (adres o yılın menüsünden alınır).
2. Konsolda tek satırla 198 (ya da yeni sayıda) satır dışa alınır.
3. `pnpm urap:uret <dosya>` — 30 satırlık dönüştürücü `src/lib/urap-siralama.ts`'i yeniden yazar ve **eşleşmeyenleri ekrana basar**.
4. `URAP_KAYNAK_URL`, `URAP_DONEM`, `URAP_TOPLAM` aynı commit'te güncellenir.
**Güncelleme sonrası doğrulama** (`scripts/veri-kalite.ts` içine, salt okunur):
| Kontrol | Beklenen |
|---|---|
| `URAP_SIRA` anahtarlarının tamamı `getAllUniversiteSlugs()` içinde mi | eşleşmeyen = 0; biri bile varsa **KALDI** (üniversite adı değişmiş demektir) |
| Sıra değerleri 1..`URAP_TOPLAM`, tekrarsız, boşluksuz | evet |
| Puanlar azalan sırada (sıra 1 en yüksek puan) | evet |
| `URAP_TOPLAM` = kayıt sayısı | evet |
| Bir önceki döneme göre listeden düşen üniversite | 0 olmalı; varsa **UYARI** + adlarıyla listelenir |
### 4.4 İş tahmini — "en küçük işe yarar adım"
| İş | Saat |
|---|---|
| `src/lib/urap-siralama.ts` (198 satır sabit; veri bu gece zaten çıkarıldı, scratchpad'de) | 0,5 |
| `katalog.ts` okuma katmanı + `UniDetay` tipi | 1 |
| `universite-icerik.tsx`'te tek kutu + atıf satırı (tasarımcı deseniyle) | 1 |
| `veri-kalite.ts`'e 5 kontrol + tsc/lint | 0,5 |
| **Toplam** | **~3 saat** |
Yıllık tazeleme: ~30 dk/yıl. Otomatik çekme betiği istenirse +3 saat — **ilk sürümde önerilmiyor.**
*(BACKLOG #8'in ~22 saatlik tahmini 8 alan ve 4 kaynak içindi; bu 3 saat onun yerine değil, en karlı ilk diliminin fiyatıdır.)*
## 5. Atıf şartı — sitede nasıl karşılanacak
İzin **şartlı**: "urapcenter.org adresine aktif bağlantı/atıf vermek kaydıyla". Veri tarafının koyduğu şart (görünüm tasarımcının):
**Kural: URAP'tan gelen bir sayının göründüğü HER yüzeyde, aynı ekranda, tek cümle + tıklanabilir bağlantı bulunur.**
Kanonik cümle:
> Kaynak: [URAP Türkiye Sıralaması 2025-2026](https://newtr.urapcenter.org/Rankings/2025-2026/GENEL-SIRALAMASI-2025), URAP Araştırma Laboratuvarı — 198 üniversite arasında.
Uygulama şartları:
1. Bağlantı **aktif** olacak: gerçek `<a href>`, yeni sekme + `rel="noopener"`. **`nofollow` konulmayacak** — "aktif bağlantı" şartının ruhu budur.
2. Bağlantı **o yılın URL'si** olacak (`URAP_KAYNAK_URL` sabitinden). Yıl güncellenirken link de güncellenir; ikisi aynı dosyada durduğu için ayrılamazlar.
3. Cümlede **dönem yazacak** ("2025-2026") ve toplam ("198 üniversite arasında") — "kaçıncı" sayısı payda olmadan yanıltıcıdır.
4. Geçtiği yerler bugün için: `/universite/[slug]` kutusu. İleride URAP sayısı bir rehber yazısında, karşılaştırma tablosunda, 24'lük listede, `/universiteler` hub'ında ya da OG görselinde görünürse **aynı cümle oraya da gider**; link konulamayan bir yüzeyde (ör. OG görseli) URAP sayısı **gösterilmez**.
5. `VeriKaynagi` bileşeni (`src/features/katalog/components/veri-kaynagi.tsx`) **kullanılmaz/kopyalanmaz**: o satır "YÖK Atlas 2026 · son güncelleme 21 Eylül 2026" yazar ve `KATALOG_VERI_TARIHI`'ne bağlıdır. URAP'ın dönemi başka, tarihi başka. Ayrı, ikinci bir kaynak satırı gerekir — yoksa öğrenciye URAP verisi YÖK Atlas tarihiyle sunulmuş olur.
6. `/gizlilik`-`/kosullar` benzeri bir hukuk metni değişikliği gerekmiyor; izin e-postası `docs/` altında saklanmalı (kanıt).
## 6. BACKLOG #9 — kök neden teşhisi (düzeltme UYGULANMADI)
### 6.1 Ne oluyor
| Üniversite | Bugünkü `unitur` | Olması gereken | Satır | Havuza girebilen (efektif sırası olan) |
|---|---|---|---|---|
| KIBRIS AMERİKAN ÜNİVERSİTESİ (+ `(KKTC-LEFKOŞA)` yazımı) | `DEVLET` | `KKTC` | 42 | 12 |
| ULUSLARARASI BALKAN ÜNİVERSİTESİ (parantezsiz yazım) | `DEVLET` | `YURTDISI KAMU` | 34 | 4 |
| ULUSLARARASI SARAYBOSNA ÜNİVERSİTESİ (parantezsiz yazım) | `DEVLET` | `YURTDISI KAMU` | 24 | 11 |
| **Toplam** | | | **100** | **27** |
Ayrıca **26 satırda** `ULUSLARARASI BALKAN ÜNİVERSİTESİ`nin ili `SARAYBOSNA - BOSNA - HERSEK` (üniversite Üsküp'te; aynı kurumun `(ÜSKÜP-MAKEDONYA)` yazımı bunu doğruluyor).
### 6.2 Kök neden
Hata **`unitur-onar.ts`'te değil**. O betik yalnız `unitur IS NULL` satırlara dokunuyor (dosya başlığı ve A/B/C aşamaları); bu satırlar NULL değil, dolu ve yanlış.
Hata **2026 tazelemesinde de doğmadı**. `scripts/refresh.ts:519` `uniturSec`, tahmin etmemek için DB'de o ad altında **tek** bir `unitur` varsa onu yeniden kullanıyor — yani var olan değeri sadakatle kopyalıyor.
Kanıt, yıl kapsamında: parantezsiz (yanlış `DEVLET`) satırların **2021-2024 verisi var**, parantezli (doğru `YURTDISI KAMU`) satırların yok.
```sql
sqlite3 -readonly data/yokatlas.db "
SELECT universite, unitur, COUNT(*) n,
SUM(sira2021 IS NOT NULL) y21, SUM(sira2025 IS NOT NULL) y25
FROM programs WHERE universite LIKE '%BALKAN%' GROUP BY 1,2;"
-- ULUSLARARASI BALKAN ÜNİVERSİTESİ | DEVLET | 34 | 2 | 4
-- ULUSLARARASI BALKAN ÜNİVERSİTESİ (ÜSKÜP-MAKEDONYA) | YURTDISI KAMU | 14 | 0 | 2
```
`refresh.ts` yalnız 2025/2026 kolonlarını yazar; 2021-2024 değerleri **yalnızca ilk CSV ingest'inden** gelebilir. Dolayısıyla `DEVLET` etiketi **`scripts/ingest.ts:159`'un CSV'den okuduğu `unitur` kolonundan** geliyor; kaynak CSV (`data/ham/`, `.gitignore`'da, repoda yok) bu üç kurumu `DEVLET` yazmış. *(CSV elde olmadığı için bu, yıl kapsamına dayanan çıkarımdır; doğrulaması Bilal'in elindeki ham CSV'de tek `grep`.)*
**Neden hiçbir kontrol yakalamadı:** `unitur-onar.ts`'in çelişki koruması `GROUP BY universite`, yani **tam ad** üzerinden çalışıyor. Aynı kurumun iki yazımı iki ayrı satır sayıldığı için `DEVLET` ile `YURTDISI KAMU` çelişkisi hiç görünmüyor. Baz ad (sondaki parantez atılmış hâl) üzerinden bakınca çelişki anında çıkıyor — bugün **4 kurum**: Uluslararası Balkan, Uluslararası Saraybosna (DEVLET↔YURTDISI KAMU) ve Manas, Hoca Ahmet Yesevi (YURTDISI KAMU↔YURTDISI VAKIF — bu ikisi kozmetik, kurum gerçekten ortak).
### 6.3 URAP'la çapraz doğrulama (bonus)
URAP'ın 125 devlet + 73 vakıf ayrımı bizim `unitur`'umuzla karşılaştırıldı: **198 üniversitenin 198'inde uyumlu, 0 çelişki.** Yani devlet/vakıf etiketimiz Türkiye üniversiteleri için sağlam; sorun yalnızca URAP'ın kapsamadığı KKTC/yurt dışı kurumlarda. Bu çapraz kontrol her yıl URAP tazelemesiyle birlikte bedavaya koşturulabilir.
### 6.4 Kullanıcıya yansıyan etki
| Yüzey | Ne yanlış görünüyor |
|---|---|
| `/universiteler` hub'ı (`src/features/katalog/components/universite-listesi.tsx:45`) | Üç KKTC/yurt dışı kurum **"Devlet üniversiteleri"** listesinde |
| `/universite/<slug>` | "Tür: Devlet" · Uluslararası Balkan için ülke/şehir Saraybosna (Bosna), üniversite Üsküp'te |
| Sihirbaz → "Devlet üniversitesi istiyorum" (`src/lib/db.ts:79`, `AND unitur = 'DEVLET'`) | Aday havuzuna **27 program** sızıyor; öğrenci "devlet" dediği hâlde KKTC/Bosna vakıf-benzeri kurum önerilebiliyor |
| Sihirbaz → "Vakıf" (`src/lib/db.ts:81`, `unitur <> 'DEVLET'`) | Aynı 27 program **eksik** kalıyor |
| Tadımlık satırı (`src/features/rapor/components/tadimlik-satiri.tsx:37`) | Aynı semantik, aynı sızıntı |
### 6.5 Düzeltmenin büyüklüğü
- **Veri:** 100 satır `unitur` + 26 satır `il` = **126 satır** `data/yokatlas.db` içinde. (Ayrıca `il` boş olan 19 satır isteğe bağlı doldurulabilir — kapsam dışı bırakılması önerilir.)
- **Kod:** `scripts/unitur-onar.ts`'e, NULL koşulu olmadan çalışan küçük bir `KURUM_DUZELT` haritası (~20 satır) + `scripts/veri-kalite.ts`'e "baz ad başına tek `unitur`" kontrolü (~8 satır). Toplam **~30 satır.**
- Düzeltme bu yolla kalıcıdır: `refresh.ts:519` bundan sonra DB'deki doğru değeri kopyalar.
- Düzeltme `data/yokatlas.db`'yi (git'te izlenen binary) değiştirir → betiğin koşulması ve commit'i **[BİLAL]**. Süre: betik ~1 sn, doğrulama `pnpm veri-kalite` ~10 sn.
## Bilal'den istenen
1. **Karar:** URAP'ın tek sayısını üniversite sayfasına koyalım mı — veriyi bizde tutup her yüzeyde aktif link + "2025-2026 · 198 üniversite arasında" cümlesiyle? (~3 saatlik iş; kararın kendisi ~2 dk)
2. **URAP'a tek cümle:** "Verdiğiniz adres 2025-2026 yılına ait görünüyor; yeni sıralama yayımlandığında linki ve veriyi biz güncelleyeceğiz, uygun mudur?" — beklentiyi baştan hizalar (~5 dk). Ayrıca izin e-postasını `docs/` altına koy (kanıt).
3. **Onay:** BACKLOG #9 düzeltmesi hazırlansın mı — 3 kurumda 126 satır (`unitur` + `il`), ~30 satır kod, sonra `data/yokatlas.db` commit'i? (~2 dk karar, uygulaması ayrı dalda ~1 saat)

View File

@@ -0,0 +1,149 @@
# 06 — CEO kararları (Tur 2, karar turu)
2026-09-22 gecesi · Ölçüt: *"Sitede kolay bir akış, gereksiz şeyler olmamalı, bilgi vereceğiz diye kullanıcıyı boğmamalıyız."*
Bu gece **4 iş** onaylandı. Geri kalan her şey reddedildi (§3). Kod değiştirmedim; yalnız bu dosyayı ve `KARARLAR.md`'yi yazdım.
---
## §1 Hüküm — gecenin ne olduğu (5 madde)
1. **Sezon dışındayız ve örneklem karar üretmiyor.** 5 haftada 801 temiz oturum; tüm zamanlarda **3** liste üretilmiş, **5** kişi kilidi görmüş, **0** ödeme tamamlanmış. Bu gece hiçbir deney, hiçbir yeniden tasarım onaylanmadı. Onaylanan dört işin dördü de "yanlış olanı düzelt" ya da "ölç" sınıfında; hiçbiri "deneyelim bakalım" değil.
2. **Gecenin en büyük bulgusu gerçek, ama dönüşüm rakamı korelasyon.** Net/OBP verisi rakipte yok, bizde var (2023–2025, 21 bin satır/yıl — 2026 **yok**). "Açanların sıra girme oranı 3 kat" cümlesi nedensellik değil: niyetli kullanıcı zaten hem açar hem sıra girer; analitik bunu kendi yazmış. **Ama nedensellikten bağımsız bir gerçek var:** o veri, adı ekranda hiç yazmayan bir ikonun arkasında (`program-netleri.tsx:101-102` — yalnız `ListChecks` ikonu + `sr-only` metin). Hükmüm: **veriyi bir tık öne çekme kararı doğru yönde, ama bu gece uygulanmaz** — çünkü pazarlama cümlesi iki doğrulanmamış iddiaya dayanıyor (YÖK Atlas'ın veriyi gerçekten kaldırdığı + arşivi yayımlamanın uygunluğu) ve katalog satırını yeniden tasarlamak n=801'de korelasyonla savunulamaz. Bu geceki payımız, nedensellik iddiası gerektirmeyen tek parça: **risk etiketinin satırda yazıyla görünmesi (P1)** — hem analitiğin 1 numaralı önerisinin bedava kısmı hem de açık bir `AGENTS.md` ihlalinin kapanması.
3. **Üç rapor iddiası koddan yanlış çıktı; ikisi bu gecenin iş listesini değiştirdi.** (a) `/bolum` sayfasında sıra formu **var** (`bolum-icerik.tsx:267`, üstelik "üstte olsun" diye yazılmış yorumla) → analitiğin 4. önceliği düştü. (b) `/paket`'te iade **görünüyor** (`paket-satinal.tsx:96`, CTA'nın hemen altında) → markanın güven bulgusunun yarısı kapanmış durumda. (c) `kosullar/page.tsx:15`'teki "MVP taslağıdır" bir **kod yorumu**, kullanıcı görmüyor. Tam tablo §2'de.
4. **URAP yapılır, çünkü izleyicisi var.** `/universite/*` bu sitenin en kalabalık yüzeyi (tek başına 405 mobil oturum). URAP oraya **kart eklemez, "Tür" kartıyla takas olur** — ızgara 4 kart kalır. Bu, "bilgi vereceğiz diye boğma" kuralını ihlal etmeyen tek metrik ekleme biçimi. Tasarımcı ile markanın ayrıştığı yer (kart mı, uyarı cümlesi mi) uzlaştırıldı: **sayı kartta, metodoloji uyarısı + aktif atıf tablonun altındaki ayrı kaynak satırında.**
5. **Bu gecenin en değerli reddi, yapay zekâ önerileridir.** Vaat dili regex denetimi, eval seti, "tek cümleyle sihirbaz doldurma", 24 satır için hazır çipler — hepsi ucuz, hepsi zekice, hiçbiri bugün bir kullanıcının derdine dokunmuyor. Sihirbaz zaten %80,6 tamamlanıyor; orada çözülecek bir problem yok. Bilal'in "olup olmadık şeyleri test etmek" uyarısının tam hedefi bunlardı ve reddedildiler.
---
## §2 İddiaların kod doğrulaması
| # | İddia (kaynak) | Hüküm | Kanıt |
|---|---|---|---|
| 1 | `netler` tablosunda 2023–2025 için ~21 bin kayıt/yıl var (marka §1) | **Doğru ama eksik** | `sqlite3 -readonly data/yokatlas.db`: 2023=21.341, 2024=20.813, 2025=20.821. **2026 yok** — pazarlamada yıl yazılmadan kullanılamaz |
| 2 | Net verisi "sadece katalogda bir modal düğmesi" (marka §1) | **Doğru ama eksik** | Buton 3 yüzeyde: `bolum-program-listesi.tsx:262`, `universite-program-tablosu.tsx:114`, **ve `/sonuc`** (`liste/components/program-tablosu.tsx:387`). Ama üçünde de görünür etiketi yok: `program-netleri.tsx:101-102` sadece `ListChecks` + `sr-only` + `title` |
| 3 | `netler_goruntulendi` akordeon açılınca atılıyor, ad doğru ölçüyor (analitik §1) | **Doğru** | `program-netleri.tsx:86-90` `acildi(acik)` → `if (!acik) return; olay(...)` |
| 4 | `/bolum/[slug]` detayında `CtaSiraForm` **hiç yok** (analitik öncelik #4) | **YANLIŞ** | `bolum-icerik.tsx:267` (`konum="ust"`, üstünde "listenin üstünde" diye yazılmış yorum) + `:297` (`konum="alt"`). Üniversite tarafı da aynı: `:290` ve `:352`, ikisi de tablonun **üstünde** — analitik "tablonun altında" demiş, o da yanlış |
| 5 | `sihirbaz_adim` 1. adımı hiç atmıyor (analitik §5-1) | **Doğru** | `sihirbaz-adimlar.tsx:205` `if (yeniAdim > adim) olay(...)` — modal 1. adımda açıldığı için 1 hiç düşmez |
| 6 | `/paket` linklerinin çoğunda `?kaynak=` yok (analitik §5-2) | **Doğru** (sayı ufak sapmalı) | 14 `href="/paket"` var; 10'u kaynaksız (`page.tsx:543,573`, `kosullar:55`, `tercih-degisti-modali:283,335`, `sohbet-client:351,538,546`, `odeme-kromu:45`, `odeme-sonuc-karti:141`), 4'ü kaynaklı. %56 değil %71 |
| 7 | Sihirbazı tamamlayanların %69'u öncelik seçmiyor (analitik §3) | **Doğru, ama n=29** | Analitik GA %51–83 veriyor ve "tam %69 savunulamaz" diyor; hükümde "çoğunluk" olarak kullandım |
| 8 | Öncelikler "listeyi daraltmaz" (tasarımcı K5) | **Doğru ama eksik** | `sihirbaz-adimlar.tsx:487-490` ekran metni: *"gerekçelere **ve program seçimine** yön verir; listeyi daraltmaz"*. Prompt'a giriyor (`sihirbaz-sabitler.ts:182-184`) → modelin 60'tan 24'ü seçmesini etkileyebilir. Etkisi ölçülmemiş |
| 9 | `/meraklisina` şeması 3. adımda öncelikleri anlatmıyor (tasarımcı K5) | **Doğru** | `huni-semasi.tsx`: `C("3. adım · Devlet / Vakıf…")` — öncelik geçmiyor. Kaldırma şemayı değiştirmez |
| 10 | Paketsiz kullanıcı 3 kredi yakıp 21/24 satırı kilitli görüyor (yapay zekâ §4) | **Doğru** | `credits.ts:11,14` (`DENEME_KREDISI=5`, `RAPOR_KREDI=3`), `rapor-maske.ts:12` (`ACIK_SATIR=3`), `rapor-actions.ts:109-110` yorumu ve kredi düşümü maskelemeden bağımsız |
| 11 | Kilitli 21 satır açılınca aynı satış kutusunu tekrarlıyor (tasarımcı K4) | **Doğru** | `rapor-listesi.tsx:306-323` — her kilitli satırda birebir aynı "Yapay Zeka karar desteği" kutusu |
| 12 | `/sonuc` tablosunda risk **yalnız renkli nokta**, metin etiketi yok (tasarımcı R1) | **Doğru — `AGENTS.md` ihlali** | `liste/components/program-tablosu.tsx:308-312`: `<span className={RISK_NOKTA[risk]} aria-hidden />`, `RISK_ETIKET` bu dosyada hiç kullanılmıyor |
| 13 | `/listem`'de risk etiketi mobilde gizli (tasarımcı R2) | **Doğru** | `rapor-listesi.tsx:267` `sr-only sm:not-sr-only` → 390px'te yalnız renk |
| 14 | `/paket` sayfasında iade politikası **hiç görünmüyor** (marka §1, §3) | **YANLIŞ** | `paket-satinal.tsx:96`: "Paketi al" butonunun hemen altında `/kosullar#iade` linki. Marka yalnız `app/paket/page.tsx`'e bakıp client bileşenini kaçırmış. İade metni de sağlam (`kosullar/page.tsx:61-83`) |
| 15 | `kosullar/page.tsx:15`'te "MVP taslağıdır" notu duruyor (marka §3) | **Doğru ama kullanıcı görmüyor** | Satır bir `// NOT:` JS yorumu, render edilmiyor. Gerçek eksik ayrı: satıcı kimliği (unvan/adres/vergi/MERSİS) — grep ile doğruladım, yok |
| 16 | URAP 198/198 slug'ımızla eşleşiyor, yeni normalleştirme gerekmiyor (veri §2) | **Doğru (ajan çalıştırarak doğruladı)** | `uniAdiNormalize`+`turkishSlugify` zinciri; scratchpad çıktıları raporda listeli. Tekrar koşmadım |
| 17 | 3 kurumda `unitur` yanlış → sihirbaz havuzuna 27 program sızıyor (veri §6) | **Doğru** | `db.ts:79-82`: devlet = `unitur = 'DEVLET'`, vakıf = `unitur IS NOT NULL AND unitur <> 'DEVLET'` → yanlış etiketli satırlar devlete sızıyor, vakıftan düşüyor |
| 18 | Üniversite sayfasında 4 kartlık metrik ızgarası var, "Tür" kartı takas edilebilir (tasarımcı §6-A) | **Doğru** | `universite-icerik.tsx:292` `grid-cols-[1fr_1fr_1.35fr] lg:grid-rows-2` + harita; "Tür" kartı `:311-322` |
| 19 | Liste üretimi bize 1,7–2,1 kuruş (yapay zekâ A-2) | **Doğrulanmadı — ajanın kendi ölçümü** | Betik silinmiş, fiyat OpenRouter'dan alınmış. Mertebe (kuruş) savunulabilir; rakamı yayına koymayız |
| 20 | Yayından beri her `program_eklendi` `yol:"dogrudan"` (analitik §2) | **Doğrulanamaz** | Rybbit yalnız analitikte açık. n=1 gerçek oturum; zaten karar için kullanılmadı |
| 21 | Dünkü "/sonuc parametre şişmesi" bulgusu iç trafik eseri (analitik §2) | **Doğru — kabul edildi** | Gerçek kullanıcıda medyan 1 sayfa görüntüleme. CTO listesinden düşürüldü, karar kaydına geçti |
**Raporların kaçırdığı, benim eklediğim:**
- **Sezon bandı metnini Bilal 18 saat önce bizzat seçti.** `84fc88e` / `bilal/sezon-bant-metni-B` commit mesajı A ve B alternatiflerini yan yana koyup B'yi seçiyor ve "375 px'te alt satıra taşar" bedelini açıkça kabul ediyor. Tasarımcı K1'de aynı bandın silinmesini öneriyor — yeni kanıt yok. **Reddedildi (§3).**
- **Net verisi 2026'yı kapsamıyor.** Site artık 2026 yerleştirme verisiyle çalışıyor ama `netler` 2025'te bitiyor. Herhangi bir net/OBP vitrin cümlesi bu boşluğu söylemek zorunda.
- **P4 ölçüm işi bir seri kırılması yaratır.** `sihirbaz_adim{1}` modal açılışında atılmaya başlayınca bu serinin paydası değişir; `program_eklendi` için 21 Eylül'de yaptığımız gibi kırılma tarihi karar kaydına yazıldı.
---
## §3 Bu gece yapılacaklar — 4 iş
Her iş tek amaçlı, ayrı dal, lokal commit. Push yok, merge yok.
### P1 — Riskin adı satırda yazsın · `gece/0922-risk-etiketi` · **[KARAR]** · ajan: `yazilimci` · **XS (~30 dk)**
**Ne:** `/sonuc` program tablosunda risk göstergesi yalnız renkli nokta ve `aria-hidden`; metin etiketi hiç yok. `/listem`'de etiket var ama `sm` altında `sr-only` — trafiğin ~%90'ı mobil, yani gören kullanıcı yalnız rengi görüyor.
**Neden:** `AGENTS.md` açık kural koyuyor: *"kırmızı/sarı/yeşil her zaman metin etiketiyle birlikte, renk tek başına anlam taşımaz."* İki yerde de ihlal (doğrulama tablosu #12, #13). Ayrıca bu, analitiğin 1 numaralı önerisinin ("karar veren bilgi tıklamasız görünsün") nedensellik iddiası gerektirmeyen, bedava kısmı: taban sıra satırda zaten var, eksik olan tek şey riskin adı.
**Kapsam:** `liste/components/program-tablosu.tsx:306-314` → `rapor-listesi.tsx:262-270` kalıbını kopyala (nokta + `RISK_ETIKET[risk]`, tek kaynak `src/lib/risk.ts`). `rapor-listesi.tsx:267` → `sr-only sm:not-sr-only` kalkar, etiket her zaman görünür. Yeni bileşen yok, yeni sabit yok, yeni olay yok.
**Kabul kriteri:** (1) `/sonuc` ve `/listem` satırlarında risk **yazıyla** görünür, kaynak `RISK_ETIKET`; (2) 390px'te etiket kesilmez, satır taşmaz; (3) `RISK_NOKTA` rengi korunur ama tek başına anlam taşımaz; (4) `tsc` + `lint` temiz.
### P2 — Sihirbaz havuzundaki sessiz sızıntıyı kapat · `gece/0922-unitur-kacagi` · **[KARAR]** (merge `[BİLAL]`) · ajan: `veri-muhendisi` · **S (~1 sa)**
**Ne:** 3 kurum (Kıbrıs Amerikan, Uluslararası Balkan, Uluslararası Saraybosna) `unitur='DEVLET'` etiketli; 100 satır. Uluslararası Balkan'ın ili 26 satırda "Saraybosna" (üniversite Üsküp'te). Sonuç: öğrenci "devlet üniversitesi istiyorum" dediğinde havuza **27 program** sızıyor, "vakıf" dediğinde aynı 27'si eksik kalıyor.
**Neden:** Sessiz doğruluk hatası — kullanıcı yanlış olduğunu fark edemez, biz de bugüne kadar fark etmedik. Kök neden teşhis edildi ve kalıcı çözümü var (`veri §6.2`: `unitur-onar.ts`'in çelişki koruması tam ad üzerinden çalıştığı için aynı kurumun iki yazımı çelişki saymıyor).
**Kapsam:** `scripts/unitur-onar.ts`'e NULL koşulsuz `KURUM_DUZELT` haritası (~20 satır) + `scripts/veri-kalite.ts`'e "baz ad başına tek `unitur`" kontrolü (~8 satır); betik koşturulur, 126 satır düzeltilir. **`data/yokatlas.db` binary'si ayrı bir commit olur** (kod ve veri karışmasın).
**Kabul kriteri:** (1) `pnpm veri-kalite` temiz ve yeni kontrol baz ad çelişkisini yakalıyor; (2) `db.ts` devlet filtresi bu 27 programı artık döndürmüyor, vakıf filtresi döndürüyor; (3) `/universiteler` hub'ında üç kurum "Devlet" listesinden çıkıyor; (4) 2021–2026 puan/sıra kolonlarında **hiçbir** değişiklik yok (fark raporu commit mesajında).
**Kapsam dışı:** `il` boş olan 19 satır; B4 (burs/dil ekli adlar); `kategoriBul` düzeltmesi.
### P3 — URAP tek sayı: "Tür" kartıyla takas · `gece/0922-urap` · **[KARAR]** (yayın `[BİLAL]`) · ajanlar: `veri-muhendisi` → `yazilimci` · **M (~3 sa)**
**Ne:** `/universite/[slug]` metrik ızgarasında "Tür" kartının yerine **URAP TÜRKİYE · 18 / 198 · 2025-2026** kartı. Kart sayısı 4'te kalır, ızgara şablonu değişmez, yeni bileşen icat edilmez.
**Neden:** Bilal'in bu geceki gündem maddesi ve izni elde (brief §4). En kalabalık yüzeyimiz burası. Tasarımcı ile marka bağımsız olarak "tablo değil, tek sayı" dedi; veri mühendisi 198/198 eşleşmeyi ve 3 saatlik yolu gösterdi.
**Çelişki çözümü (tek yerleşim kararı):**
- **Sayı kartta, uyarı kartta değil.** Kart üç satırı geçmez: başlık, `18 / 198`, `2025-2026`. Payda kartın içinde kalır — "18." tek başına yanıltır.
- **Markanın metodoloji uyarısı + atıf, tablonun altındaki ayrı ikinci kaynak satırında.** `VeriKaynagi` **kullanılmaz ve kopyalanmaz** (o satır YÖK Atlas tarihine bağlı; URAP'ın dönemi başka). Kanonik cümle: *"URAP Türkiye Sıralaması 2025-2026 (198 üniversite arasında) — akademik yayın ve araştırma performansını ölçer; eğitim kalitesini ya da iş bulma oranını ölçmez. Kaynak: [urapcenter.org …](…)"*
- **Boş durum (31 kurum):** tasarımcı "kart çizilmesin, Tür kalsın" diyor, veri mühendisi "eksik görünür kalsın" diyor — **ikisi de uygulanır:** ızgarada "Tür" kartı yerinde kalır (hiçbir sayfada "—" ya da delik yok) **ve** alttaki kaynak satırına tek cümle düşer: *"Bu üniversite URAP Türkiye sıralamasında yer almıyor — URAP yalnız Türkiye'deki üniversiteleri sıralıyor."* (KKTC/yurt dışı) ya da *"…2025-2026 listesinde yer almıyor."* (MYO/yeni).
- **Atıf pazarlık dışı:** gerçek `<a href>`, `rel="noopener"`, yeni sekme, **`nofollow` yok**, adres `URAP_KAYNAK_URL` sabitinden. URAP sayısının göründüğü her yüzeyde aynı ekranda bulunur; link konulamayan yüzeyde (OG görseli) sayı gösterilmez.
**Kapsam:** `src/lib/urap-siralama.ts` (198 satırlık sabit, `uni-koordinatlar.ts` deseni) + `katalog.ts:363` okuma katmanı + `UniDetay` tipine tek alan + `universite-icerik.tsx` kart takası ve kaynak satırı + `veri-kalite.ts`'e 5 kontrol. **Yeni DB dosyası yok, göç yok, cron yok, çekme betiği yok.**
**Kabul kriteri:** (1) URAP'ta olan sayfada 4 kart, "Tür" yerinde URAP; olmayan sayfada 4 kart, "Tür" duruyor — hiçbir sayfada "—"/boş kutu yok; (2) URAP sayısının göründüğü her sayfada aynı ekranda aktif atıf linki ve dönem var; (3) `veri-kalite` kontrolleri geçiyor, eşleşmeyen slug sessizce düşmüyor; (4) renk yok, rozet yok, `/universiteler` hub'ında URAP'a göre sıralama/filtre yok; (5) 24'lük listeye, `/sonuc` tablosuna ve LLM prompt'una URAP **girmez**; (6) `tsc` + `lint` + `build` temiz.
### P4 — İki ölçüm deliği · `gece/0922-olcum` · **[KARAR]** · ajan: `yazilimci` · **XS (~30 dk)**
**Ne:** (a) `sihirbaz_adim{adim:1}` modal açılışında atılsın (bugün yalnız ileri geçişte atıldığı için 1. adım hiç düşmüyor, payda `sira_girildi`den türetiliyor); (b) kaynaksız 10 `/paket` linkine `?kaynak=` eklensin.
**Neden:** İkisi de kullanıcıya görünmez, ikisi de tek satırlık, ikisi de her gelecek kararın önkoşulu — 2 Kasım'daki "+ tuttu mu" okuması dahil. Bunlar "ölçüm eklemek de bir iştir" diye ertelenecek kadar pahalı değil; ertelenirse bir sonraki karar turu yine kör başlar.
**Kapsam:** `sihirbaz-adimlar.tsx:205` çevresi (açılışta bir kez, geri dönüşlerde tekrar sayma) + 10 link (`page.tsx:543,573`, `kosullar/page.tsx:55`, `tercih-degisti-modali.tsx:283,335`, `sohbet-client.tsx:351,538,546`, `odeme-kromu.tsx:45`, `odeme-sonuc-karti.tsx:141`) — kaynak adları mevcut şemayla tutarlı (`kilit`, `kredi_bitti`, `nav` desenine uygun).
**Kabul kriteri:** (1) Sihirbaz açılışında `sihirbaz_adim{adim:1}` tam bir kez düşer, 1→2→1→2 gidip gelmede tekrar düşmez; (2) 14 `/paket` linkinin 14'ünde `?kaynak=` var ve değerler tekil; (3) hiçbir görsel değişiklik yok; (4) commit mesajında **seri kırılması notu**: bu tarihten önceki `sihirbaz_adim` paydası farklıdır.
---
## §4 Reddedilenler — tek cümlelik gerekçeyle
**Tasarım kesimleri**
- **K1 — sezon bandını sezon dışında hiç çizme: REDDEDİLDİ.** Bilal bu bandın metnini 18 saat önce iki alternatif arasından bizzat seçti (`84fc88e`, `bilal/sezon-bant-metni-B`) ve iki satıra taşma bedelini açıkça kabul etti; yeni kanıt yok, verilmiş karar yeniden açılmaz.
- **K2 — `/sonuc` boş harita kutusunu kaldır: REDDEDİLDİ (bu gece).** Kazanç ölçülmemiş bir piksel tahmini, bedel (ilk eklemedeki CLS + `+` ipucu) gerçek; üstelik yayından beri `/sonuc`'ta **0** gerçek oturum var, etkisi ölçülemez.
- **K3 — `/sonuc`'ta iki giriş panelinden birini kaldır: REDDEDİLDİ (bu gece).** Tasarımcının kendisi "hangisinin kalacağını rakam belirlemeli" diyor ve rakam yok; ayrıca kesim koşullu ("tadımlık havuzu boşsa B geri gelmeli"), yani tek amaçlı değil, durum makinesi.
- **K4 — kilitli satırların tek tek açılmasını kapat: REDDEDİLDİ (bu gece), backlog önerisi.** İki bağımsız raporla en iyi kanıtlanan kesim, ama bugünkü izleyicisi ~0 (tüm zamanlarda kilidi gören 5 gerçek oturum); sezon yaklaşınca ilk sıraya alınmalı.
- **K5 — sihirbazdan "Öncelikler"i çıkar: BU GECE UYGULANMAZ, `[BİLAL]`.** Ekran öğesi kaldırmak + yapay zekânın gördüğü girdiyi değiştirmek ürün kararıdır; tavsiyem "evet, kalksın" (§5).
- **S1–S8, R3–R11: REDDEDİLDİ (bu gece).** Hepsi tek tek küçük, toplamı Bilal'in inceleme kuyruğunu dörde katlar; kontrast sistematiği (R7, 48 kullanım) ve `+` butonundaki sınıf çakışması (R11) backlog'a en güçlü adaylar.
**Yapay zekâ önerileri**
- **Vaat dili regex denetimi + kurtarma ölçümü (`[KARAR]` istendi): REDDEDİLDİ.** Tüm zamanlarda üretilmiş **3** liste var; şikâyet edilmemiş bir çıktıya filtre yazmak, Bilal'in adıyla yasakladığı işin tam tanımı — `liste_olusturuldu` 50'yi geçince yeniden bak.
- **B-1 "tek cümleyle sihirbaz ön-doldurma": REDDEDİLDİ.** Sihirbazda kopma yok (adım 2→3 geçişi %96,9, tamamlama %80,6); %80 dönüşen bir adıma yapay zekâ girişi eklemek olmayan bir sorunu çözer. Bilal isterse bu reddi bozabilir.
- **B-2/B-3 hazır çipler: REDDEDİLDİ (bu gece).** Sıfır maliyetli ama ekranı olan kullanıcı sayısı bugün tek haneli; ekranın kalabalığını artırır, kimse görmez.
- **B-4 veliye e-posta paragrafı: REDDEDİLDİ (bu gece).** Tamamlanmış tek bir ödeme yok; tetikleyicisi hiç çalışmayacak bir şablon yazılmaz.
- **B-5 URAP'ı prompt'a/liste satırına sokmak: REDDEDİLDİ.** Ürünün metin diyetini ve "24 satıra sütun ekleme" yasağını deler; URAP bu sürümde yalnız üniversite sayfasında yaşar.
**Analitik önerileri**
- **Öncelik #4 (`/bolum`'e köprü ekle): REDDEDİLDİ — iddia yanlış.** Form zaten var ve zaten üstte (`bolum-icerik.tsx:267`).
- **Öncelik #2 (rehber ilk ekranına köprü): REDDEDİLDİ (bu gece).** Analitik kendi söylüyor: rehberde okuma mı terk mi ayırt edilemiyor; ölçüm olmadan yapılacak her müdahale kör atıştır. Kaydırma kilometre taşı olayı önce gelir, o da bu gecenin işi değil.
- **Öncelik #1'in tamamı (katalog satırının yeniden tasarımı): REDDEDİLDİ.** Korelasyonla satır tasarımı açılmaz; bedava olan parçası P1 olarak alındı.
**Marka önerileri**
- **"Ücretsiz yolu da var" cümlesi: REDDEDİLDİ (bu gece).** Konum olarak doğru, zamanlama olarak yanlış: sezon dışında izleyicisi yok ve tek bir tamamlanmış satış görmeden satışı zorlaştıran bir cümleyi siteye koymak sırasız. Sezon öncesi yeniden.
- **Satıcı kimliği / `/hakkinda`: YENİDEN AÇILMADI.** 21 Eylül'de Bilal erteledi; markanın forum bulgusu gerekçeyi güçlendiriyor ama kararı değiştirmiyor.
- **`/paket`'te iade görünmüyor: KONU KAPANDI** — iddia yanlış, link zaten CTA'nın altında.
- **`kosullar/page.tsx:15` yorumunu sil: REDDEDİLDİ.** Kullanıcıya görünmeyen bir kod yorumu için inceleme slotu harcanmaz.
---
## §5 Bilal'in karar vermesi gerekenler
| # | Soru (sade) | Seçenekler | Tavsiyem | Maliyet / geri dönüş |
|---|---|---|---|---|
| 1 | Sihirbazın son adımındaki **"Senin için önemli olan"** 7 etiketi (iş bulma kolaylığı, yüksek maaş…) kalksın mı? | (a) Kalksın, son adım tek soru olsun: Devlet mi, vakıf mı? (b) Kalsın | **(a) Kalksın.** Üç bağımsız kanıt: sihirbazı bitirenlerin çoğu hiç seçmiyor; ürünün kendi akış şeması bu adımı zaten anlatmıyor; listenin 24 satırını ve sırasını kod kuruyor, bu etiketler yalnız gerekçe cümlesinin tonuna dokunuyor | **Ucuz ve geri alınabilir.** Alan veride kalır, eski kayıtlar bozulmaz; fikir değişirse geri konur. ~1 saatlik iş |
| 2 | Paketi olmayan öğrenci listesini **ücretsiz** görsün mü? Bugün 5 deneme hakkının 3'ünü tek bir listeye yakıyor ve o listenin 21 satırı kilitli geliyor. | (a) Liste bedava olsun, 5 hak tamamen danışmana soru sormaya kalsın (b) Bugünkü gibi kalsın (c) Veri birikene kadar bekle | **(a).** Bu üretim bize kuruşlar mal oluyor, yani kredi bizi bir masraftan korumuyor — sadece denemeyi zorlaştırıyor. **Asıl para kapısı (kilitli satırlar) hiç değişmiyor**, tek kaybımız yok. (c) bekleme seçeneğini eleme sebebim: ekranda 3 liste var, Kasım'dan önce okunur hâle gelmeyecek; karar zaten ekonomiyle veriliyor, veriyle değil | **Tek sayı değişikliği, geri dönüşü dakikalar.** Kötüye kullanım kullanıcı başına günlük üretim sınırıyla kapanır (kilit mekanizması dün eklendi) |
| 3 | **URAP** paketi (üniversite sayfasında "Tür" kartının yerine "URAP Türkiye 18/198" + altta atıf cümlesi) hazır olunca canlıya çıksın mı? | (a) Çıksın (b) Bekle | **(a).** İzin elde, veri %100 eşleşiyor, ekrana yeni kutu eklenmiyor — takas. Atıf şartı pazarlık dışı uygulanıyor | Geri dönüş: dosyayı sil + tek alanı kaldır. Göç yok. Ayrıca **izin e-postasını `docs/` altına koy** (kanıt), ~2 dk |
| 4 | Sihirbazda "devlet üniversitesi" diyen öğrenciye **KKTC/Bosna'daki 3 kurumun 27 programı** öneriliyor. Düzeltme veritabanı dosyasını değiştirir — onaylıyor musun? | (a) Onayla, hazırlanan dal merge edilsin (b) Bekle | **(a).** Sessiz bir doğruluk hatası; kullanıcı yanlış olduğunu anlayamaz. Puan/sıra kolonlarına dokunulmuyor | Geri dönüş: dal merge edilmeden önce fark raporu commit mesajında; sonrası için `veri-2026-son` etiketi duruyor. ~10 dk inceleme |
| 5 | **"YÖK Atlas'ın kaldırdığı 'son yerleşenin netleri' bizde duruyor"** cümlesini siteye/pazarlamaya koyalım mı? | (a) Koyalım (b) Önce iki şeyi doğrula, sonra karar | **(b).** Kaynağımız iki şikâyet/köşe yazısı, resmî duyuru yok; ayrıca veri 2023–2025'i kapsıyor, 2026'yı **kapsamıyor** — "elimizde var" derken yılı söylemek zorundayız. Doğrulanmamış rakam/atıf yayına giremez | Doğrulama ucuz (YÖK Atlas'ta bir program sayfasının ekran görüntüsü, ~10 dk); yanlış çıkarsa marka zararı pahalı |
| 6 | **Rybbit paneli:** ekip trafiğini dışla + Web Vitals'ı aç | — | **İkisini de yap.** 21–22 Eylül'de panelde görünen trafiğin **%70'i bizdik**; filtresiz bakan biri "25 ödeme başlatıldı" görür, hepsi iç. Filtre açılmazsa 2 Kasım'daki okuma da çöp olur | ~12 dk toplam, tamamen geri alınabilir panel ayarı |
---
## §6 Diğer ajanlara açık sorular (Tur 3)
- **`analitik`:** (1) Öncelik #4'ü düşür — `/bolum` sayfasında form var ve üstte; `/bolum` mobilin 8 puan kötü olmasının sebebi köprü eksikliği değil, başka bir şey. Aynı iki sayfa tipinde **form altı davranış** (`cta_form_goruntulendi` → `sira_girildi`) ayrıştırılabilir mi? (2) `netler_goruntulendi` olan oturumlarda açılıştan **önceki** sayfa sayısı nedir? Niyetin önceden mi geldiğini (ters nedensellik) ayırmanın en ucuz yolu bu. (3) P4 sonrası `sihirbaz_adim{1}` serisinin kırılma tarihini raporlarında sabit dipnot yap.
- **`tasarimci`:** K5 onaylanırsa 3. adım tek soruya inince modal yüksekliği ve "Adım 3/3" göstergesi nasıl durur — tek ekran taslağı (kod değil). Ayrıca R7 (48 yerde `text-slate-400`) tek commit'lik sistematik bir işe sığar mı, yoksa parça parça mı?
- **`veri-muhendisi`:** P3'te `URAP_YAYIN` sabiti "[doğrulanmalı]" işaretli — kaynak bulunamazsa sabiti hiç koyma, dipnotta yalnız dönemi ("2025-2026") göster. P2'de düzeltme sonrası `programs_arsiv` tarafında aynı kurumların satırları var mı, varsa etiketleri tutarlı mı?
- **`yapay-zeka-muhendisi`:** Bilal §5-2'ye "evet" derse: liste üretimi paketsize ücretsiz olduğunda kötüye kullanım sınırı **hangi eşikte** olmalı (kullanıcı/gün) ve eşiğe çarpan kullanıcı ne görmeli? Tek paragraf, yeni ekran önerme.
- **`qa-muhendisi`:** P1–P4 dallarının her biri için, onaylanan kabul kriterlerini doğrulayan en kısa duman testi. Özellikle P2'de 27 programın havuz davranışı (devlet/vakıf filtresi) ve P3'te URAP'ı olmayan bir üniversite sayfasının ızgarasında delik açılmadığı.
- **`urun-yoneticisi`:** Reddettiğim ama backlog'a ait olanlar: K4 (kilitli satır tekrarı), K2, R7, R11, rehber kaydırma olayı, `kategoriBul` baz ad düzeltmesi (BACKLOG #10 ile aynı kök). BACKLOG'a ben dokunmadım.
---
## §7 Bilal'den istenen (3 madde)
1. **§5 tablosundaki 6 soruyu sırayla cevapla** — hepsi sade, hiçbiri teknik. **~15 dk.**
2. **Rybbit panelinde iki ayar:** ekip trafiğini dışla + Web Vitals'ı aç. Yapılmazsa bir sonraki ölçüm turu da kör. **~12 dk.**
3. **URAP izin e-postasını `docs/` altına kaydet** ve URAP'a tek cümle yaz: *"Verdiğiniz adres 2025-2026 yılına ait görünüyor; yeni sıralama yayımlandığında linki ve veriyi biz güncelleyeceğiz, uygun mudur?"* — beklentiyi baştan hizalar. **~7 dk.**

View File

@@ -0,0 +1,39 @@
# Tur 5 — hedefli güvenlik denetimi (`gece/0922-entegrasyon`)
Kapsam: `git diff 9bd448b..HEAD` içindeki `?kaynak=` allowlist genişletmesi, ödeme/kredi yüzeyine dokunan satırlar, URAP atıf şartının kod yolları. Salt okuma yapıldı; worktree'ye dokunulmadı.
## Özet (5 madde)
1. **Kritik bulgu yok.** Ödeme çekirdeği (`src/app/api/**`, `src/lib/credits.ts`, `src/lib/odeme.ts`, `src/lib/iyzico.ts`, `src/features/odeme/odeme-actions.ts`, `src/lib/auth.ts`, `src/lib/session.ts`) bu dalda **hiç değişmemiş** — `git diff --stat 9bd448b..HEAD` bu yollar için boş döner.
2. `KAYNAKLAR` allowlist'i **gerçekten kapalı**: `KAYNAKLAR.find((k) => k === ham) ?? "diger"` sabit literal dizisine tam eşitlik arar, bilinmeyen değer `"diger"`e düşer. 10 yeni değerin hepsi sabit snake_case; kişisel veri ya da enjeksiyon yükü taşımıyor.
3. `?kaynak=` **ödeme akışına taşınmıyor**: `/paket` sayfası yalnızca `hata` parametresini okur (`src/app/paket/page.tsx:20`), `odeme-actions.ts` içinde `kaynak` hiç geçmez, sipariş kaydına ve iyzico alanlarına girmez. Tek cümlelik cevap: taşınmıyor.
4. Bir **düşük** bulgu var: allowlist yalnızca *özel olayın* özelliğini korur; Rybbit'in otomatik pageview'i ham query string'i zaten olduğu gibi saklar, yani "serbest metin analitiğe sızmasın" yorumu eksik doğru (B-1).
5. URAP atıf şartı kodda korunuyor: sayının görüldüğü tek yüzey ile atıf linkinin tek yüzeyi **aynı `ilkSayfa` koşuluna** bağlı; linksiz sayı yolu bulunamadı (detay aşağıda).
## Bulgular
| Yer | Sorun | Somut senaryo | Önem | Düzeltme | Kesinlik |
|---|---|---|---|---|---|
| `src/features/odeme/components/paket-gorunum-olayi.tsx:13-15` (yorum) | Yorum "Serbest metin analitiğe sızmasın" diyor; allowlist bunu yalnız `paket_goruntulendi.kaynak` özelliği için sağlıyor. Rybbit script'i her pageview'de ham `querystring` alanını saklıyor. | Saldırgan `kolaytercih.com/paket?kaynak=<istediği metin>` linkini paylaşır; kurban tıklar; metin Rybbit panelinin `querystring` kırılımında görünür. Kod yürütme yok, yalnız panel kirliliği/yanıltma. Doğrulama: Rybbit `querystring` kırılımında `?kaynak=nav`, `?kaynak=kilit` satırları ham biçimde duruyor (site 1, tüm zaman). | düşük | Kod değişikliği gerekmez; yorumu "olay özelliği kapalıdır, ham query string ayrıca pageview'de saklanır" diye düzelt. | DOĞRULANDI |
| `src/lib/analitik.ts:10-12` (bu dalda değil — mevcut durum) | Dosyanın başındaki KURAL "öğrencinin ham başarı sıralaması analitiğe GÖNDERİLMEZ, her zaman `siraKovasi()` ile bantlanır" diyor. Özel olaylar için doğru, ama `/?sira=14000&tur=say` gibi URL'lerde ham sıra pageview'in `querystring` alanında saklanıyor. | Rybbit panelinde `querystring` kırılımı açılır; `?sira=14000&tur=say`, `?sira=55&tur=say`, `?sira=581000&tur=ea&sihirbaz=1` satırları ham sıralamayı gösterir. Oturum/kullanıcı satırıyla birleşince tekil öğrenciye bağlanabilir (Rybbit trait'lerinde ad/e-posta da var). **Bu dalın getirdiği bir şey değil**, aynı mekanizmanın önceden var olan sonucu. | orta | Kod tarafı: sıra formu URL'e `sira` yazıyorsa değeri bantlı tutmak ya da form gönderimini query'siz yapmak; alternatif: Rybbit tarafında query string toplamayı kapatmak. Karar `[BİLAL]`. | DOĞRULANDI |
## Kapsam sorularına kısa cevaplar
**1. Allowlist kapalı mı?** Evet — `paket-gorunum-olayi.tsx:43-46`. Dedup anahtarı da sanitize edilmiş `kaynak`tan türetiliyor (`olayBirKez(..., kaynak)`), ham değer sessionStorage anahtarına da girmiyor. Yeni 10 değerin hepsi (`fiyat_paket`, `fiyat_kredi`, `kosullar`, `tercih_degisti`, `tercih_degisti_yetersiz`, `danisman_rozet`, `danisman_kredi_bitti`, `danisman_kredi_az`, `odeme_geri`, `odeme_hata`) yüzey adı; kişisel veri yok.
**2. Ödeme/kredi yüzeyi.** `odeme-kromu.tsx:45`, `odeme-sonuc-karti.tsx:141`, `sohbet-client.tsx:351/538/546`, `tercih-degisti-modali.tsx:283/335`, `src/app/page.tsx:543/573`, `src/app/kosullar/page.tsx:55` — hepsi **yalnızca `href` string'i**. Kredi düşümü, sipariş durumu, yetki kontrolü, fiyat/ürün belirleme hiç değişmedi. `sihirbaz-adimlar.tsx`'teki tek yeni satır mount'ta `olayBirKez("sihirbaz_adim", { adim: 1 }, "adim1")`; sabit değer, kişisel veri yok. `program-tablosu.tsx` / `rapor-listesi.tsx` değişiklikleri erişilebilirlik (risk etiketini `sr-only`dan çıkarma) — güvenlik etkisi yok.
**3. URAP atıf şartı (kod yolları).** URAP'ı tüketen tek yer `src/features/katalog/components/universite-icerik.tsx`; başka hiçbir bileşen, metadata, JSON-LD ya da OG görseli sayıyı almıyor (`grep -rn "urap\|URAP" src/` → yalnız `lib/urap-siralama.ts`, `lib/katalog.ts` tipi, `universite-icerik.tsx`, `scripts/veri-kalite.ts`).
- Sayının çizildiği tek yer: kart, `universite-icerik.tsx:363-371` — `ilkSayfa` dalının (satır 308) içinde.
- Atıf linkinin çizildiği tek yer: `UrapKaynakSatiri`, `universite-icerik.tsx:129-156` — çağrısı `satır 441: {ilkSayfa ? <UrapKaynakSatiri uni={uni} /> : null}`.
- İkisi de aynı koşula bağlı olduğu için "sayı var, link yok" sayfası üretilemiyor; `/universite/[slug]/sayfa/[no]` (2+) ne sayıyı ne linki gösteriyor. `uniSayfaMetadata` ve `opengraph-image.tsx` URAP'a hiç dokunmuyor.
- **Kalan kırılganlık (bulgu değil, not):** `src/lib/katalog.ts:402` artık `urap`'ı `UniDetay` nesnesine iliştiriyor. Yarın biri `UniDetay`'i bir istemci bileşenine ya da yeni bir kart/JSON-LD'ye verirse sayı linksiz bir yüzeye çıkabilir. `scripts/veri-kalite.ts` içindeki URAP kontrolleri veri bütünlüğünü denetliyor ama "her gösterim yanında link var mı" sorusunu denetlemiyor. Bu tip kurallar yorumla korunuyor (`katalog.ts:229-231`), testle değil.
## Metin × kod uyumsuzlukları
- `paket-gorunum-olayi.tsx:13` yorumu ile gerçek saklama arasındaki fark (yukarıda B-1).
- `analitik.ts:10-12` KURAL'ı ile `querystring` alanında duran ham sıra arasındaki fark (yukarıda, mevcut durum).
## Bilal'den istenen
1. Ham `?sira=` değerinin Rybbit `querystring` alanında saklanması sürsün mü, yoksa kapatılsın mı — karar senin (5 dk).

View File

@@ -0,0 +1,166 @@
# 12 — Bağımsız kod denetimi (Tur 5)
**Dal:** `gece/0922-entegrasyon` @ `9e1506d` · **Taban:** `main` @ `9bd448b` · **Denetçi:** `cto` (kodu yazmadı)
**Kapsam:** `git diff 9bd448b..HEAD` — 20 dosya, +948/−38, `data/yokatlas.db` binary dahil. Salt okuma; hiçbir dosya değiştirilmedi, commit atılmadı, `git status` entegrasyon worktree'sinde **temiz**.
---
## HÜKÜM
**İncelemeye çıkabilir.** Kritik bulgu yok; veri bütünlüğü bağımsız olarak doğrulandı ve iddia edildiği gibi çıktı. Ancak dalı Bilal'in önüne koymadan önce **iki tek-satırlık düzeltme** yapılmasını öneriyorum (Y1 ve O2 aynı dosyayı ilgilendirmiyor, ikisi birlikte ~10 dk): biri P4'ün tek çıktısını okunabilir kılıyor, diğeri yanlış bir doğrulama rakamını kayda geçiriyor. Bunlar yapılmazsa da dal çalışır ve kullanıcıya zarar vermez — yalnız 2 Kasım'daki ölçüm okuması bozuk olur.
## Özet (5 madde)
1. **Veri commit'i temiz.** `data/yokatlas.db`'nin iki sürümünü ayrı kopyalara çıkarıp 45 kolonu tek tek kıyasladım: değişen **yalnız `unitur` (100 satır) ve `il` (26 satır)**. `id` kümesi aynı, `programs_arsiv`/`netler`/`veri_meta` sıfır fark, 2021–2026 puan/sıra/kontenjan/yerleşen kolonlarında **0 satır** değişti. P2'nin iddiası birebir doğru.
2. **Paketler birleşince doğru davranıyor.** P3'ün boş durum varyantı P2'nin yeni `unitur` değerleriyle üç kurumun üçünde de doğru cümleyi veriyor — kod okumasıyla değil, **dalın kendi ürettiği statik HTML'den** doğrulandı (Kıbrıs Amerikan, Balkan, Saraybosna → "URAP yalnız Türkiye'deki üniversiteleri sıralıyor"). Hub'da üçü de "KKTC ve Yurt Dışı" bölümüne geçmiş.
3. **P4'ün tek çıktısı ölçüm olarak kullanılamaz durumda.** `sihirbaz_adim{1}` oturum başına tekil (`olayBirKez`), `{2}`/`{3}` ise geçiş başına atılıyor. Paydayla pay farklı birimde olduğu için huni oranı %100'ü aşabilir. Kodun kendi yazılı kuralı (`analitik.ts:23`) bu tercihe karşı. Tek kelimelik düzeltme.
4. **P2'nin rapor/commit rakamlarından biri yanlış:** "`/universiteler` hub'ında Devlet listesi 170 → 166". Gerçek sayı üretilmiş HTML'de **129** (öncesi 132). Kriterin kendisi karşılanıyor, yalnız kanıt rakamı ham DB adlarını sayıyor ve yanındaki "iki yazım iki ayrı slug" gerekçesi de yanlış.
5. **P1'in mobil iddiası doğru, P3'ün atıf şartı sağlam.** `TableCell`/`TableHead` varsayılanı `whitespace-nowrap` + kap `overflow-x-auto` + program hücresi `truncate` → etiket kesilmez, satır taşmaz. URAP sayısı 198 sayfada, hepsinde aynı ekranda `rel="noopener"` link, `nofollow` yok; sayı derin sayfalarda hiç çizilmiyor, dolayısıyla "linksiz sayı" hiçbir yerde oluşmuyor.
---
## Bulgular (şiddet sırasına göre)
### KRİTİK — yok
### YÜKSEK
#### Y1 · Huninin paydası ile payı farklı birimde; oran %100'ü aşabilir
**Dosya:** `src/features/sihirbaz/components/sihirbaz-adimlar.tsx:154-156` (yeni) ile `:220` (mevcut)
```ts
// :154-156 — oturum başına EN FAZLA BİR KEZ
useEffect(() => { olayBirKez("sihirbaz_adim", { adim: 1 }, "adim1"); }, []);
// :220 — her ileri geçişte, sınırsız
if (yeniAdim > adim) olay("sihirbaz_adim", { adim: yeniAdim + 1 });
```
`olayBirKez` `sessionStorage` anahtarıyla tekilleştiriyor (`src/lib/analitik.ts:169-184`), `olay` tekilleştirmiyor.
**Somut senaryo (tek sekme, tek oturum):** Öğrenci ana sayfadaki hero formundan sıralamasını girer, sihirbazı 1→2→3 tamamlar → `adim:1` ×1, `adim:2` ×1, `adim:3` ×1. `/sonuc`'a düşer, "Tercihlerini güncelle" ile tercih kapısını açar → `SihirbazAdimlar` yeniden mount olur ama `sessionStorage`'da `kolaytercih.olay.sihirbaz_adim.adim1` zaten yazılı, **`adim:1` atılmaz**; öğrenci yine 1→2→3 gider → `adim:2` ×2, `adim:3` ×2. Panelde adım 1→2 geçiş oranı **%200** görünür. Aynı şey `/bolum` ve `/universite` sayfalarında iki ayrı `CtaSiraForm` (üst ve alt) bulunduğu için tek sayfada da olur.
**Neden bu bir tasarım tercihi değil:** `src/lib/analitik.ts:22-24` aynı sorunu daha önce yaşayıp yazıya dökmüş:
> `liste_uretim_basladi` … *Bilerek `olayBirKez` KULLANILMAZ: aynı oturumdaki ikinci deneme de sayılmalı, yoksa payda başarıdan (liste_olusturuldu) küçük kalır.*
P4 tam tersini yapmış ve bunu raporunda tartışmamış (`08-p4-olcum.md`, kabul kriteri 1 yalnız "iki kez düşmesin"e bakıyor — kriter karşılanıyor, ölçüm bozuluyor).
**Önerim (tek kelime, mevcut serileri bozmaz):** `olayBirKez` → `olay`. Mount zaten "sihirbaz bir kez açıldı"ya eşit; `1→2→1→2` gezinmesi unmount etmediği için CEO'nun "tekrar düşmesin" kriteri korunur, ikinci **açılış** ise `adim:2`/`{3}` ile aynı mantıkla yeniden sayılır. Alternatif (2 ve 3'ü de oturum-tekil yapmak) doğru ama `sihirbaz_adim{2,3}` serisinde **ikinci** bir kırılma yaratır — o yüzden önermiyorum.
### ORTA
#### O1 · P2'nin hub rakamı yanlış; yanındaki gerekçe de yanlış
**Dosya:** `1df86cf` commit gövdesi ("`/universiteler` hub'ında Devlet listesi 170 → 166 kurum") ve `docs/gece-vardiyasi/2026-09-22/09-p2-unitur.md:107,110`
Dalın kendi build'inin ürettiği HTML (`.next/server/app/universiteler.html`):
```
Devlet Üniversiteleri …>129 Vakıf Üniversiteleri …>78 (üçüncü bölüm: "KKTC ve Yurt Dışı")
```
Düzeltme öncesi DB üzerinde `getAllUniversiteler`in algoritmasını birebir koşturduğumda **132** çıkıyor. Yani gerçek değişim **132 → 129 (3 kurum)**; raporun yazdığı 170 → 166 ham `programs.universite` ad sayısıdır (eski DB'de `DEVLET` etiketli 170 farklı ad, yenide 166), hub satırı değil.
Rapordaki gerekçe de yanlış: *"Kıbrıs Amerikan'ın iki yazımı bugün iki ayrı slug"*. `uniAdiNormalize` (`src/lib/harita.ts:32-34`) sondaki parantezli eki atıyor, `uniSayfaSlug` (`src/lib/slug.ts:41-43`) da aynı kuralı uyguluyor → iki yazım **tek slug** (`kibris-amerikan-universitesi`, 42 program, tek sayfa). Buna bağlanan BACKLOG #10 atfı da bu satır için geçersiz.
**Etkisi:** Davranış doğru — üç kurumun üçü de "Devlet" listesinden çıkmış, "KKTC ve Yurt Dışı" bölümüne geçmiş (HTML'de konumları doğrulandı). Yalnız **kanıt rakamı** yanlış. Bu commit `[BİLAL]` onayına gidiyor ve onay mesajdaki fark raporuna dayanıyor; rakam düzeltilmeden gitmemeli.
#### O2 · P4 ikinci bir seri kırılması yaratıyor, commit'te yazmıyor
**Dosya:** `src/features/odeme/components/paket-gorunum-olayi.tsx:16-38` (allowlist 3 → 13) ile `:45-47`
```ts
const kaynak = KAYNAKLAR.find((k) => k === ham) ?? "diger";
olayBirKez("paket_goruntulendi", { kaynak }, kaynak); // tekilleştirme anahtarı = kaynak
```
Tekilleştirme anahtarı `kaynak` olduğu için allowlist genişleyince olayın **oturum başına atılabilme sayısı 4'ten 14'e** çıkıyor.
**Somut senaryo:** Bir oturumda kullanıcı ana sayfanın fiyat bölümünden `/paket`'e gidiyor, geri dönüyor, sonra danışman ekranındaki kredi rozetinden tekrar gidiyor. **Önce:** iki gidişte de `kaynak="diger"` → tek `paket_goruntulendi`. **Sonra:** `fiyat_paket` ve `danisman_rozet` → iki ayrı olay. Yani `paket_goruntulendi` toplamı trafikten bağımsız olarak yükselecek ve `diger` kovasının anlamı tamamen değişecek (eskiden "10 bilinen yüzey + gerçekten bilinmeyen", şimdi yalnız "gerçekten bilinmeyen"). Deploy tarihinden önceki/sonraki `paket_goruntulendi` karşılaştırılamaz.
Commit gövdesi (`26893ce`) seri kırılması notunu yalnız `sihirbaz_adim` için yazıyor. `program_eklendi` için 21 Eylül'de konan kuralın gereği: bu da yazılmalı.
#### O3 · P2 + P3 birleşince üç üniversite sayfasında bozuk Türkçe etiket
**Dosya:** `src/features/katalog/components/universite-icerik.tsx:381-385` → `trBaslikDuzeni` (`src/lib/slug.ts:56-62`)
`trBaslikDuzeni` `toLocaleLowerCase("tr-TR")` kullanıyor; tr-TR'de `I` → `ı`, dolayısıyla `"YURTDISI KAMU"` → **`"Yurtdısı Kamu"`**. (Orkestratör günlüğü bunu "Yurtdisi Kamu" diye kaydetmiş; üretilen HTML'deki gerçek çıktı "Yurtdısı Kamu" — Türkçede var olmayan bir kelime.)
**Hangi paket yaptı:** ikisi birden. P2 `unitur`'ü `DEVLET` → `YURTDISI KAMU`/`KKTC` yaptı; P3 "Tür" kartını **yalnız** URAP dışındaki 31 kurumda bıraktığı için bu değerler o sayfaların tek metrik kartı hâline geldi. Ayrı ayrı iki dal da sorunsuz görünüyordu.
**Kanıt (dalın ürettiği HTML):**
```
uluslararasi-balkan-universitesi.html : <dd …>Yurtdısı Kamu</dd> (dün: "Devlet")
uluslararasi-saraybosna-universitesi.html : <dd …>Yurtdısı Kamu</dd> (dün: "Devlet")
kibris-amerikan-universitesi.html : <dd …>Kktc</dd> (dün: "Devlet")
```
"Yurtdısı" içeren sayfa: 6 · ">Kktc<" içeren sayfa: 16 · "Tür" kartı olan toplam sayfa: 31.
**Not:** doğruluk arttı (KKTC kurumuna "Devlet" demekten iyidir), görünürlük kalitesi düştü. Düzeltme `unitur` → görünen etiket için 5 satırlık bir harita; `trBaslikDuzeni`'ye dokunmaya gerek yok. Bilerek yapılmadığı günlükte yazılı, itiraz etmiyorum — ama sabah incelemesinde gözle görülecek ilk şey bu.
#### O4 · 198 üniversite sayfasında "devlet mi, vakıf mı" bilgisi tamamen kayboldu
**Dosya:** `src/features/katalog/components/universite-icerik.tsx:363-397` (kart takası)
CEO kararı bunu açıkça "takas" diye tanımlamış (§3/P3), yani **şartname ihlali değil**. Ama karar kaydında "bilgi yerine başka bir yerde kalıyor" demiyor; kalmıyor:
```
.next/server/app/universite/bogazici-universitesi.html → "Devlet" kelimesi 0 kez
.next/server/app/universite/koc-universitesi.html → "Vakıf" kelimesi 0 kez
```
H1'de yok, giriş paragrafında yok (`:310-330`), `uniSayfaMetadata` açıklamasında yok (`:180-183`), breadcrumb'da yok, program tablosunda yok (`UniDetay.stats.devletMi` üretiliyor ama `katalog.ts:409`'dan sonra hiç okunmuyor). Sitenin en kalabalık yüzeyinde (`/universite/*`) bir öğrencinin ilk sorduğu ikili bilgi ekrandan çıktı.
**Ucuz telafi (ızgaraya dokunmadan):** giriş paragrafındaki cümleye tek sıfat — "… bir **devlet üniversitesi** olarak 2026 YKS yerleştirme sonuçlarına göre N programda öğrenci aldı." Kart sayısı 4'te kalır, yeni kutu açılmaz. Bu bir `[BİLAL]` kararı; ben yalnız kaybın gerçek olduğunu belgeliyorum.
### DÜŞÜK
- **D1 · `/listem` risk sütunu artık kendi içinde tutarsız.** Kilitli satır `rapor-listesi.tsx:259` hâlâ `sr-only sm:not-sr-only` "Pakette", kilitsiz satır `:267` görünür etiket. Paketsiz kullanıcıda 24 satırın 21'i kilitli, yani P1'in mobil kazancı o kullanıcı için 3 satır. Sütun genişliğini zaten "Az riskli" belirlediği için "Pakette"yi görünür yapmanın **ek genişlik maliyeti yok**. (P1 raporu ve orkestratör günlüğü bunu zaten not etmiş.)
- **D2 · AGENTS.md renk kuralının açık kaldığı üçüncü yüzey.** `src/features/liste/components/liste-cekmecesi.tsx:424-428` — risk yalnız renkli nokta + `aria-label`; görünür metin yok. Kapsam dışı bırakılması bilinçliydi; kural hâlâ ihlal.
- **D3 · URAP sabitinde denetimsiz tek alan: `URAP_KAYNAK_URL`.** `URAP_DONEM`/`URAP_TOPLAM`/`URAP_SIRA` birbirine `veri-kalite` kontrolleriyle bağlı (`scripts/veri-kalite.ts:191-266`), URL hiçbirine bağlı değil. Gelecek Ekim'de dönem `2026-2027` olup URL unutulursa sayfa "URAP Türkiye Sıralaması **2026-2027** … Kaynak: urapcenter.org" der ve **2025-2026 sayfasına** link verir — izin şartı biçimsel olarak ihlal edilir, `pnpm veri-kalite` sessiz kalır. Tek satır kapatır: `zorunlu("URAP: kaynak URL dönemi tutuyor", URAP_KAYNAK_URL.includes(URAP_DONEM), URAP_KAYNAK_URL)`. *(URL'nin kendisi doğru: URAP'ın izin e-postasındaki adres — `00-brief.md:8`; veri mühendisi 22 Eyl'de tarayıcı paneliyle okumuş — `05-urap.md:17`. Bu oturumda tarayıcı açmadım.)*
- **D4 · Yeni `veri-kalite` kontrolünün bilgi kolu hiçbir zaman uyarı üretmiyor.** `scripts/veri-kalite.ts:318` `bilgi(..., false, ...)` — sabit `false`. Bugün iki kurum bu kolda: Kırgızistan-Türkiye Manas ve Hoca Ahmet Yesevi, iki yazımı `YURTDISI KAMU` + `YURTDISI VAKIF`. Kullanıcıya yansımıyor (devlet/vakıf ayrımını bölmüyor, sayfa tek slug'da birleşiyor), ama P2'nin kapattığı hata sınıfı iki kurumda hâlâ açık ve sayaca girmiyor.
- **D5 · URAP dışı 9 Türkiye kurumunda gerekçesiz olumsuz cümle.** "Bu üniversite URAP Türkiye Sıralaması 2025-2026 listesinde yer almıyor." — dördü MYO, üçü yeni devlet üniversitesi (Sivas Bilim ve Teknoloji, Türk-Japon, Ankara Müzik ve Güzel Sanatlar), biri de üniversite bile değil (`icisleri-bakanligi-ve-milli-savunma-bakanligi-adina-…`). Sabitin kendi yorumu ("kötü demek değildir; MYO'lar ve yeni üniversiteler listeye girmiyor" — `src/lib/urap-siralama.ts:13-16`) kullanıcıya ulaşmıyor. CEO'nun yazdığı kanonik cümle birebir uygulandığı için **şartname ihlali değil**.
- **D6 · `data/yokatlas.db-shm` / `-wal` git'te izleniyor.** Veri commit'i ana dosyayı değiştirdi, yan dosyalar commit'e girmedi. Bugün zararsız (`-wal` 0 bayt) ama repoda tutulmaları ileride tutarsız çift üretebilir. P2 raporu da not etmiş; backlog.
- **D7 · Tür rozeti hâlâ ikili.** `program-tablosu.tsx:311` ve `rapor-listesi.tsx:225-233`: `unitur === "DEVLET" ? "Devlet" : "Vakıf"`. P2'den sonra düzeltilen 27 program artık **"Vakıf"** rozetiyle görünüyor. "Devlet"ten doğru, gerçekten doğru değil; aynı durumda ~1.350 KKTC/yurt dışı satırı zaten vardı. Backlog.
---
## Temiz çıkanlar (denetlendi, bulgu yok)
**Veri (P2) — bağımsız SQL doğrulaması.** `git show` ile iki sürüm ayrı kopyalara çıkarıldı, `sqlite3 "file:…?immutable=1"` ile ATTACH edilip 45 kolon tek tek kıyaslandı:
- `programs`: 21.493 → 21.493, `id` kümesi farkı 0/0. Değişen kolon **yalnız `unitur` (100) ve `il` (26)**; diğer 43 kolonda değişen satır 0.
- `programs_arsiv` 3.735 → 3.735 (unitur/il/universite farkı 0) · `netler` 62.975 → 62.975 (fark 0) · `veri_meta` 37 → 37 (fark 0).
- Değişimler: Kıbrıs Amerikan (iki yazım, 36+6) `DEVLET`→`KKTC`; Balkan (34) ve Saraybosna (24) `DEVLET`→`YURTDISI KAMU`; Balkan'ın 26 satırında il `SARAYBOSNA - BOSNA - HERSEK`→`ÜSKÜP-MAKEDONYA`. Başka kuruma dokunulmamış.
- Havuz etkisi bağımsız sayıldı: `unitur='DEVLET'` + efektif sırası dolu bu dört adda **27 → 0**.
- Düzeltme sonrası `programs`'ta `unitur IS NULL` satır yok ve aynı ham adın iki farklı `unitur`'ü yok.
**P2 + P3 birleşik davranışı (denetim sorusu #1).** `UrapKaynakSatiri` (`universite-icerik.tsx:129-133`) `unitur === "KKTC" || unitur?.startsWith("YURTDISI")` bakıyor. DB'deki 229 slug'ın tamamını `uniSayfaSlug` ile üretip URAP sabitiyle kesiştirdim: URAP dışı 31 slug'ın 22'si `KKTC`/`YURTDISI *` → yurt dışı cümlesi, 9'u Türkiye → liste cümlesi. Üç düzeltilen kurumun üçü de yurt dışı kolunda. Dalın ürettiği HTML de aynı sonucu veriyor. **Ek kod gerekmemiş, iddia doğru.**
**`olayBirKez` dayanıklılığı (denetim sorusu #3).** `src/lib/analitik.ts:169-184`: SSR'da `typeof window === "undefined"` ile çıkıyor; `window.sessionStorage`'a **erişimin kendisi** `try` bloğunun içinde, dolayısıyla storage kapalı/engelli ortamda `SecurityError` yutuluyor ve olay tekilleştirmesiz yine atılıyor — patlamıyor, sessizce düşmüyor. Gizli sekmede `sessionStorage` normal çalışır. Dev StrictMode'un çift effect'i ilk koşuda yazılan anahtarla yutulur (ve Rybbit script'i zaten yalnız prod build'de yükleniyor). Sihirbaz `dynamic(..., { ssr: false })` ile yükleniyor (`sihirbaz-adimlar-lazy.tsx:46-53`), sunucuda hiç koşmuyor.
**"Mount = 1. adım görüldü" varsayımı.** `SihirbazAdimlar`'ın beş mount noktasının beşi de koşullu: `sihirbaz-modal.tsx:47` (Radix `Dialog`, kapalıyken unmount), `hero-form.tsx:216` (`facetler && sira`), `cta-sira-form.tsx:328` (`facetler && sira != null`, form dalıyla ayrık ternary), `tercih-profili-kapisi.tsx:450` (`facetler` yalnız `facetYukle` sonrası doluyor). Sayfa yüklenirken kendiliğinden mount olan bir yüzey yok. Varsayım tutuyor; sorun yalnızca Y1'deki birim uyuşmazlığı.
**P1'in mobil taşma iddiası (denetim sorusu #2).** `src/components/ui/table.tsx:86` `TableCell` varsayılanı `whitespace-nowrap`, `:73` `TableHead` aynı, `:11` tablo kabı `overflow-x-auto`; program hücresi `program-tablosu.tsx:324` `max-w-0 w-full` + içeride `truncate`. Yani etiket sarmalanamaz/kesilemez, artan genişliği program adı sütunu yutar, en kötü durumda tablo yatay kayar — sayfa taşmaz. **İddia doğru.** "Az riskli" en uzun etiket (`src/lib/risk.ts:8-12`); kalan genişlik Bilal'in gözle bakacağı bir tasarım kararı, hata değil.
**P4 link envanteri.** `grep -rn '"/paket' src/` → gezinme amaçlı 14 `<Link>`'in 14'ünde `?kaynak=` var, 13 tekil değerin **13'ü de** `KAYNAKLAR` allowlist'inde (fazlası/eksiği yok). Kalan `/paket` geçişleri `redirect()` ve giriş `callback`'leri — kullanıcı tıklaması değil, CEO'nun listesinde de yoklar.
**P3 sızıntı denetimi.** `src/lib/urap-siralama.ts`'i içe aktaran yalnız `src/lib/katalog.ts:13`, `universite-icerik.tsx:33-37` ve `scripts/veri-kalite.ts:129`. LLM prompt'una (`src/lib/ai/rapor.ts`), `/sonuc` tablosuna, OG görsellerine, hub'a girmiyor. `universite-icerik.tsx` sunucu bileşeni (`"use client"` yok) → 14 KB'lık sabit tarayıcıya inmiyor, standalone/bellek etkisi yok.
**Atıf şartı.** Metrik ızgarası `ilkSayfa` koşulunun içinde (`:308` açılıyor, `:400` kapanıyor), kaynak satırı da `:441`'de aynı koşulla. Yani URAP sayısının göründüğü tek yüzeyde link her zaman aynı ekranda. Üretilen HTML: 198 sayfada `URAP Türkiye</dt>`, 31 sayfada `Tür</dt>`, toplam 229 — delik yok, "—" yok.
**`veri-kalite` #14'ün sezgisi veriyle tutuyor.** Türkiye ili sezgisi "tire yok + `KKTC_ILLERI`'nde değil". DB'deki tireli il değerleri yalnız 5 yurt dışı değer (`BAKÜ-AZERBAYCAN`, `BİŞKEK-KIRGIZİSTAN`, `SARAYBOSNA - BOSNA - HERSEK`, `TÜRKİSTAN-KAZAKİSTAN`, `ÜSKÜP-MAKEDONYA`); KKTC il değerlerinin **hepsi** sabitte (GİRNE, LEFKOŞA, GAZİMAĞUSA, LEFKE, GÜZELYURT, KIBRIS); ili NULL olan kurumlar `HAVING SUM(il IS NOT NULL) > 0` ile eleniyor. Yanlış pozitif/negatif üretecek bir boşluk bulamadım.
**AGENTS.md (denetim sorusu #6).** Yeni badge/eyebrow yok (`SectionEyebrow` dışı pill eklenmemiş), yeni modal/kapatma çarpısı yok, yeni CTA butonu yok — dokunulan CTA'ların `ArrowRight` deseni korunmuş. `/meraklisina` şeması **doğru olarak güncellenmedi**: sihirbaz adımlarının sayısı-sırası-içeriği, aday havuzu kuralları, 24'lük iskelet, gevşetme sırası ve havuz-dışı kuralı değişmedi; P2 havuzun *içeriğini* düzeltti, *mimarisini* değil. Risk renk dili P1 ile **güçlendi** (tek kalan ihlal D2).
---
## Backlog önerileri (kapsam dışı, kayda değer)
1. `unitur` → görünen etiket haritası (`Devlet / Vakıf / KKTC / Yurt dışı — kamu / Yurt dışı — vakıf`), tek kaynak; `trBaslikDuzeni` ham DB değerlerine uygulanmasın (O3, D7 aynı kökten).
2. `/sonuc` ve `/listem` satır rozetinde üçüncü değer (KKTC/yurt dışı) — bugün ~1.350 satır "Vakıf" diye etiketleniyor.
3. `veri-kalite`'ye `URAP_KAYNAK_URL ⊃ URAP_DONEM` kontrolü (D3) ve #13'ün bilgi kolunun gerçekten uyarı sayması (D4).
4. `data/yokatlas.db-shm` / `-wal` git izlemesinden çıksın (D6).
5. `listem-govde.tsx:288` ve `:369` iki ayrı kilit yüzeyi, ikisi de `kaynak=kilit` — P4'ün kendi raporunda not edilmiş, ayrılmalı.
---
## Bilal'den istenen (3 madde)
1. **Y1'i merge öncesi düzelttir** — `sihirbaz-adimlar.tsx:155`'te `olayBirKez` → `olay`; yoksa 2 Kasım'daki huni okuması payda/pay uyuşmazlığı yüzünden şişik çıkar. **~5 dk.**
2. **O1'i kayda geçir** — veri commit'inin gövdesindeki "170 → 166" gerçek hub sayısı değil; doğrusu **132 → 129**, düzeltme mesajı onayla birlikte girsin. **~3 dk.**
3. **O4'e karar ver** — üniversite sayfalarında "devlet mi vakıf mı" bilgisi tamamen kayboldu; giriş cümlesine tek sıfat ekleyelim mi, yoksa takas bu hâliyle mi kalsın? **~2 dk.**

View File

@@ -0,0 +1,75 @@
# 13 — Denetim düzeltmeleri (Tur 6)
**Ajan:** `yazilimci` · **Kaynak:** `12-kod-denetimi.md` Y1 / O2 / O3 · **Dallar:** `gece/0922-olcum`, `gece/0922-urap`, birleşim `gece/0922-entegrasyon`
Push yok, `main`'e commit yok, tarayıcı açılmadı.
---
## Özet (5 madde)
1. **Y1 kapandı.** `sihirbaz-adimlar.tsx`'te `olayBirKez("sihirbaz_adim", {adim:1}, "adim1")` → `olay("sihirbaz_adim", {adim:1})`. Payda artık payla aynı birimde: sihirbaz her açıldığında `adim:1` düşer, `:225`'teki ileri geçiş olayı zaten her geçişte düşüyordu. `olayBirKez` bu dosyada başka kullanılmadığı için import'tan da çıktı.
2. **CEO'nun P4/(1) kabul kriteri düzeltildi ve commit mesajına yazıldı.** Eski kriter ("oturumda tam bir kez") mevcut olay sözleşmesiyle çelişiyordu; yeni kriter "her sihirbaz **açılışında** bir kez". 1→2→1→2 gezinmesinde tekrar düşmeme şartı korunuyor (mount effect, `[]` bağımlılık; geri dönüşler unmount etmiyor).
3. **O2 (yalnız belge).** `paket-gorunum-olayi.tsx`'in allowlist yorumuna, tekilleştirme tavanının 4→14 çıktığını ve `diger` kovasının anlamının değiştiğini söyleyen bir seri-kırılması notu eklendi. Kod değişmedi.
4. **O3 kapandı.** `universite-icerik.tsx`'e karta özel `UNITUR_ETIKET` haritası kondu; `src/lib/slug.ts`'teki `trBaslikDuzeni`'ye **dokunulmadı**. Üretilen HTML'de "Kktc" ve "Yurtdısı" üniversite sayfalarından tamamen kalktı.
5. **Entegrasyon tazelendi, dördü de temiz:** çakışmasız iki merge, `next typegen` + `tsc --noEmit` + `lint` + `build` hatasız. `gece/0922-entegrasyon` başı `74f7aa1`, çalışma ağacı temiz.
---
## Commit'ler
| Dal | Hash | Mesaj |
|---|---|---|
| `gece/0922-olcum` | `58f4dc2` | `fix(olcum): huninin paydası ile payı aynı birimde olsun` |
| `gece/0922-urap` | `0e689e6` | `fix(katalog): "Tür" kartı ham DB değerini okunur Türkçeyle gösterir` |
| `gece/0922-entegrasyon` | `e1760d4` | `Merge branch 'gece/0922-olcum' into gece/0922-entegrasyon` |
| `gece/0922-entegrasyon` | `74f7aa1` | `Merge branch 'gece/0922-urap' into gece/0922-entegrasyon` |
**Dokunulan dosyalar (3, hepsi yol vererek eklendi — `git add -A` kullanılmadı):**
- `src/features/sihirbaz/components/sihirbaz-adimlar.tsx` (+9/−4)
- `src/features/odeme/components/paket-gorunum-olayi.tsx` (+6/−0, yalnız yorum)
- `src/features/katalog/components/universite-icerik.tsx` (+19/−5)
---
## Kabul kriterleri
| # | Kriter | Sonuç | Nasıl doğrulandı |
|---|---|---|---|
| 1 | `sihirbaz_adim{1}` dedup'sız atılıyor | ✔ | `grep`: `:160` `olay("sihirbaz_adim", { adim: 1 })`, `:225` `olay(..., { adim: yeniAdim + 1 })` — ikisi de dedup'suz. Dosyada `olayBirKez` kalmadı |
| 2 | Effect yalnız gerçek açılışta koşuyor, her render'da değil | ✔ (koddan çıkarım) | `useEffect(..., [])`; bileşen beş mount noktasının beşinde de koşullu (denetim raporu §"Mount = 1. adım görüldü" ile aynı okuma). Tarayıcıda koşturulmadı |
| 3 | O2 notu dosyada ve commit mesajında | ✔ | `paket-gorunum-olayi.tsx:16-21` yorumu + `58f4dc2` gövdesi |
| 4 | "Kktc" üniversite sayfalarından kalktı | ✔ | `grep -rl '>Kktc<' .next/server/app/universite/` → **0**; `dogu-akdeniz-universitesi.html` → `>Tür</dt><dd …>KKTC<` |
| 5 | "Yurtdısı" hiçbir üniversite sayfasında yok | ✔ | `grep -rl "Yurtdısı" .next/server/app/universite/` → **çıktı yok** |
| 6 | Yeni etiketler doğru dağılıyor | ✔ | 1. sayfalarda: `KKTC` 16 sayfa, `Yurt dışı (kamu)` 6 sayfa (Azerbaycan Devlet Pedagoji, Hoca Ahmet Yesevi, Kırgızistan-Türkiye Manas, Tiran New York, Uluslararası Balkan, Uluslararası Saraybosna). Toplam 22 = denetimin saydığı 22 yurt dışı/KKTC slug'ı |
| 7 | Izgarada delik açılmadı | ✔ | `>Tür</dt>` 31 sayfa + `>URAP Türkiye</dt>` 198 sayfa = 229; `Devlet`/`Vakıf` etiketleri bozulmadı (ör. `sivas-bilim-ve-teknoloji-universitesi.html` → `Devlet`) |
| 8 | `trBaslikDuzeni`'ye dokunulmadı | ✔ | `git diff` yalnız 3 dosya; `src/lib/slug.ts` listede yok |
| 9 | Entegrasyon: typegen + tsc + lint + build temiz | ✔ | Dördü de `0` çıkışla koştu; build 229 üniversite + 494 sayfalama rotası üretti |
| 10 | Merge çakışması yok | ✔ | İki merge de `ort` stratejisiyle otomatik |
---
## Şartnameden sapmalar
**Yok** — verilen üç dosyanın dışına çıkılmadı, `trBaslikDuzeni` korundu.
Not düşülecek iki nokta:
- **`YURTDISI VAKIF` etiketi hiçbir sayfada görünmüyor (0 sayfa).** Haritada var ama DB'deki 12 satır, iki yazımı `YURTDISI KAMU` + `YURTDISI VAKIF` olan iki kuruma (Hoca Ahmet Yesevi, Kırgızistan-Türkiye Manas) ait ve okuma katmanı bu slug'lar için `YURTDISI KAMU`'ya düşüyor. Bu tam olarak denetimin **D4** maddesi; harita bugün ölü kol, ileride D4 kapanınca çalışır.
- **Aynı bozuk etiketler `/bolum/*` program listesinde duruyor.** `bolum-program-listesi.tsx:227` de ham `unitur`'ü `trBaslikDuzeni`'den geçiriyor: üretilen HTML'de "Kktc", "Yurtdısı Kamu", "Vakıf Myo" (24 bölüm sayfası), "Yurtdısı Vakıf" (7 sayfa) rozetleri var. **Bu gerileme değil, `main`'de de vardı** — `main`'in DB'sinde zaten 1.145 `KKTC` + 99 `YURTDISI KAMU` satırı var (sqlite karşılaştırması yapıldı); P2 bu sayıları 1.187 + 157'ye çıkardığı için yüzey biraz genişledi. Şartname bu dosyayı vermediği için dokunmadım; denetimin backlog önerisi #1 ("tek kaynak `unitur` → etiket haritası") bunu kapsıyor.
---
## Merge sonrası doğrulanması gerekenler
1. **Canlıda `sihirbaz_adim` serisinin kırılma tarihi** — deploy gününden itibaren `adim:1` var ve **oturum başına birden çok kez** düşebiliyor; 2 Kasım okumasında huni oranı bu tarihten önceki veriyle karşılaştırılmamalı. (`analitik`'in sabit dipnotu güncellenmeli: kriter "her açılış".)
2. **`paket_goruntulendi` toplamı ve `diger` payı** — deploy sonrası ikisi de trafikten bağımsız olarak değişecek; panelde önce/sonra kıyası yapılmamalı.
3. **Gözle bakış:** `/universite/dogu-akdeniz-universitesi` ve `/universite/uluslararasi-balkan-universitesi` "Tür" kartı (`KKTC` / `Yurt dışı (kamu)`) — 390px'te kart üç satırı geçmiyor mu.
4. Denetimin kapsanmayan maddeleri hâlâ açık: **O1** (commit gövdesindeki 170→166 yerine 132→129), **O4** (üniversite sayfasında devlet/vakıf bilgisinin kaybı), D1–D7.
---
## Bilal'den istenen (3 madde)
1. **O1'i kayda geçir** — `1df86cf` veri commit'inin gövdesindeki "170 → 166" hub sayısı değil; doğrusu **132 → 129**. Merge onayı bu fark raporuna dayandığı için düzeltme onayla birlikte girmeli. **~3 dk.**
2. **O4'e karar ver** — üniversite sayfalarında "devlet mi vakıf mı" bilgisi tamamen kayboldu; giriş cümlesine tek sıfat mı eklensin, yoksa takas bu hâliyle mi kalsın? **~2 dk.**
3. **`/bolum` rozetlerini backlog'a al mı, şimdi mi** — aynı bozuk etiketler (`Kktc`, `Yurtdısı Kamu`, `Vakıf Myo`) bölüm listelerinde duruyor; bu gece kapsam dışıydı, tek kaynak haritaya taşımak ~20 dk. **~1 dk karar.**

View File

@@ -0,0 +1,71 @@
# 14 — Analitik: net detayı nedensellik mi, niyetin belirtisi mi?
2026-09-22 gece vardiyası · Tur 7 · CEO'nun `06-ceo-kararlari.md` §6 sorusu (2)
Kaynak: `mcp__rybbit__run_query`, `scoped_events`, site_id=1 · TT penceresi (18 Ağu 00:00 → 21 Eyl 12:24) · `country='TR'` · iç cihaz/hesap `NOT IN` filtresi (`01-analitik.md` §"Veri güvenilirliği" ile aynı CTE). Sorgu §1'i birebir yeniden üretti (685 açmayan / 22 sıra; 116 açan / 14 sıra) — yani karşılaştırma aynı tabanda.
## Hüküm tek cümlede
**CEO haklıydı; iş yeniden açılmamalı.** İki bağımsız ayırt edici de aynı yöne gidiyor: nedensellikle uyumlu tahmin %9,4 değil **%4,3** ve %3,2'lik tabandan ayrılmıyor.
---
## 1. Ölçüm A — olaydan ÖNCEKİ sayfa sayısı (CEO'nun istediği test)
`netler_goruntulendi` olan 116 temiz oturumda, ilk net açılışından önce kaç sayfa görüntülendiği:
| Olaydan önceki sayfa | Oturum | Sıra girdi | Oran |
|---|---|---|---|
| **0–1 (ilk sayfasında açtı)** | **70** | **1** | **%1,43** (GA %0,25–7,66) |
| 2 | 16 | 5 | — |
| 3 | 11 | 3 | — |
| 4 | 6 | 2 | — |
| 5+ | 13 | 3 | — |
| **2+ (derin gezinen)** | **46** | **13** | **%28,3** (GA %17,3–42,6) |
| *Karşılaştırma:* hiç açmayan | 685 | 22 | %3,21 (GA %2,13–4,81) |
Medyan = **1** sayfa; ortalama 2,23; p75 = 3.
**Bu tablo testi tersine çeviriyor.** CEO'nun kriteri "detayı açanlar yeni girmişse detay bir şeyi tetikliyor olabilir" idi. Açanların **%60'ı (70/116) gerçekten siteye yeni girmiş** — ve tam da o grup **%1,43** ile taban çizgisinin **altında** dönüşüyor (Fisher iki yönlü **p = 0,71**; taban çizgisinden ayırt edilemiyor). %3,2 → %9,4 farkının tamamı derin gezinen 46 oturumdan geliyor (%28,3; derin vs. ilk-sayfa farkı p = 1,8e-05).
Yani: detayı erken açmak hiçbir şey tetiklemiyor. "Açma" ile "sıra girme" yalnızca **oturumun derinliğinde** birlikte artıyor — ikisinin ortak nedeni gezinme/niyet.
## 2. Ölçüm B — sıra girişi detaydan ÖNCE mi SONRA mı? (daha doğrudan sinyal)
Hem `netler_goruntulendi` hem `sira_girildi` olan **14** oturumda ilk olay damgalarının sırası:
| Sıra girişi | Oturum | Net açılışından önceki ort. sayfa | İki olay arası ort. |
|---|---|---|---|
| **Detaydan ÖNCE geldi** | **9** | 4,67 | −99 sn |
| Detaydan SONRA geldi | 5 | 2,80 | +174 sn |
| Aynı saniye | 0 | — | — |
**14 dönüşümün 9'unda ok ters yönde:** kullanıcı sıralamasını zaten girmiş, sonra katalog satırının detayını açmış. Bu 9 oturumun sıralamayı girmesini detay açıklayamaz — detay henüz açılmamıştı.
**Nedensellikle uyumlu tek tahmin** (detayı açmış ve *ondan sonra* sıra girmiş): **5/116 = %4,31** (GA %1,85–9,69). Taban çizgisi %3,21 (GA %2,13–4,81). Aralıklar üst üste biniyor, Fisher **p = 0,58**. §1'deki "3 kat" farkı bu kesimde **kayboluyor**.
---
## 3. Dürüstlük notları
- n küçük: nedensellikle uyumlu pay yalnız **5 olay** üzerine kurulu. "%4,3, tabandan farksız" ifadesi savunulabilir; "detayın etkisi sıfırdır" savunulamaz — GA'nın üst sınırı %9,7, yani gerçek bir etki hâlâ bu aralığa sığabilir. Doğru cümle: **veri artık bir etki iddiasını desteklemiyor.**
- Rybbit 30 dk'lık oturumlama yapıyor: detayı açıp *ertesi gün* sıra giren kullanıcı "SONRA" kovasına düşmez. Bu, B ölçümünü nedensellik aleyhine hafif yanlı kılar. Ama A ölçümü bu yanlılıktan bağımsızdır ve aynı sonucu veriyor — iki testin aynı yöne gitmesi hükmü taşıyor.
- `netler_goruntulendi` adı doğru ölçüyor (`src/features/katalog/components/program-netleri.tsx:86-90`, yalnız açılışta, CEO §2-3'te doğrulanmış). Dolayısıyla bulgu ölçüm hatası değil, yorum hatasıydı — §1'deki tablo yanlış değil, **nedensellik okumaya elverişli değildi.**
- Verinin içinde bana yönelik talimat içeren içerik yok; kimlik/e-posta sorgulanmadı.
## 4. Tavsiye
**CEO'nun reddi doğruydu — katalog satırının yeniden tasarımı yeniden açılmamalı.** P1 (risk etiketinin satırda yazıyla görünmesi) nedensellik iddiasına dayanmadığı, `AGENTS.md` ihlalini kapattığı için ayakta kalır; ama "net/OBP'yi bir tık öne çekersek dönüşüm 3 katına çıkar" gerekçesi bu gece **düştü** ve bundan sonraki hiçbir raporda gerekçe olarak kullanılmamalı. §1 öncelik tablosunun 1. satırı ve "Tasarımcıya" §1 maddesi bu dipnotla işaretlenmeli.
## 5. Kesin cevap için gereken tek olay
**`netler_satiri_goruldu`** — kapalı net butonunun viewport'a ilk girişinde, oturum başına bir kez (`src/components/use-gorunum-olayi.ts` hook'u bunu zaten yapıyor; `program-netleri.tsx:95` tetikleyici butonuna ref bağlamak yeterli).
*Neden bu:* Bugün 685 "açmayan" oturum iki farklı insanı aynı kovaya koyuyor — **butonu gördü, açmadı** ile **hiçbir program satırına kadar inmedi**. Doğru karşılaştırma birincisiyle yapılır. Gören-açmayan grubun dönüşümü tabanla aynıysa detay gerçekten fark yaratmıyor; belirgin düşükse detayın kendisi bir şey katıyor demektir. Bu tek olay, gözlemsel veriyle sorulabilecek en iyi soruyu açar.
*Sınır:* Nedenselliği **kesin** kanıtlayan tek yöntem rastgeleli deneydir ve bugünkü hacimde (haftada ~8–9 + oturumu) o deney sezon öncesinde güç üretmez. Bu olay "kesin cevap" değil, **daha temiz bir gözlem** sağlar — talep edilen tek olay buysa bu.
---
## Bilal'den istenen
Yok — bu tur karar değil, düzeltme turu. (Önceki turdaki üç istek geçerliliğini koruyor.)

Binary file not shown.