content(rehber): gece vardiyasının 14 yeni yazısı + 2 düzeltme, ekip raporları ve kurallar

14 yeni rehber yazısı (hepsi editör denetiminden geçti, 46 yazıda 829 iç link
tarandı, 0 kırık hedef; 180+ DB rakamı yazıların kendi filtreleriyle yeniden
koşuldu):

  taban-siralamalari-alti-yilda-nasil-degisti · kac-net-ile-hangi-bolum ·
  siralama-bandlari-hangi-kapilar-acilir · ayni-bolum-farkli-universite-siralama-farki ·
  hangi-bolumlerin-kontenjani-azaldi · yeni-acilan-bolumler-nasil-degerlendirilir ·
  bilgisayar-mi-yazilim-muhendisligi-mi · kktc-universiteleri-okunur-mu ·
  yapay-zekaya-tercih-sordum-guvenilir-mi · ek-madde-1-puanim-yetiyor-mu ·
  universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma · yks-2027-takvimi ·
  rehber-ogretmenler-icin-veri-kaynaklari · bolumumu-sevmedim-hangi-kapilar-var

İki canlı yazı düzeltildi:
- veliler-icin-tercih-rehberi: veli diliyle kapanış; altındaki "sıralamanı gir"
  kutusu artık veliye ölü uç değil
- bos-kontenjanlar-ne-anlatiyor: "birkaç yüz kişilik fark" aslında ~9 bin
  (ÖSYM 265.356 ↔ bizim 256.532); payda açıklaması tersti — ek kontenjan
  paydaya girseydi oran düşerdi. guncelleme alanı eklendi (sitemap lastmod).

Kurallar (AGENTS.md):
- Yayın sonrası arama motoru bildirimi: URL denetimi yalnız canlıda 200 dönen
  adrese; kota sayacı; mülk/hesap notu; sitemap grep kuralı
- Yıkıcı git komutları yasak: reset/checkout --/restore/clean/stash
- Tarayıcı açma: tasarımcı ve UX gerekli gördüğünde açabilir (yetenek için
  .claude/agents/tasarimci.md'ye tarayıcı araçları eklendi)

docs/gece-vardiyasi/2026-09-22/ — 34 rapor: CEO kararları ve kapanış turu,
marka/ödeme analizi, sıfır ödeme teşhisi, SEO konu planı, veri kalitesi,
editör denetimi, CTO şartnamesi, yazılımcı ve güvenlik raporları, SABAH-OZETI.

docs/ekip/YAYIN-KUYRUGU.md — Search Console bildirim kuyruğu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-22 23:25:34 +03:00
parent 9bd448bd16
commit 2b350d0c5d
66 changed files with 12306 additions and 3 deletions

View File

@@ -0,0 +1,366 @@
# 01 — Yapay zekâ listesi hunisi: ziyaretten `liste_olusturuldu`'ya
Hazırlayan: Analitik ajanı · 22 Eyl 2026 gündüz vardiyası · Saat dilimi Europe/Istanbul
**Bu oturumda Rybbit MCP bağlı değil** (`.mcp.json` yalnız shadcn içeriyor, `.env` yok) — canlı sorgu çekilmedi, denenmedi. Bu rapor iki kaynağın üstüne kuruldu:
- **Dünkü ham Rybbit sonuçları** (yeniden sorgulanmadı, yalnız yeniden hesaplandı): `docs/ekip-raporlari/2026-09-21/03-donusum.md`, `docs/gece-vardiyasi/2026-09-21/01-analitik-bulgular.md`, `docs/gece-vardiyasi/2026-09-21/09-analitik-tur2.md`. Her rakamın yanında kaynağı **(dosya § bölüm)** biçiminde.
- **Koddan ölçüm denetimi** (bu vardiyada yapıldı): "koddan çıkarım (dosya:satır)" diye işaretlendi. Kod değiştirilmedi, yalnız okundu.
Ana pencere: **30g = 23 Ağu – 21 Eyl 2026**, iç trafik (13 cihaz + 9 hesap) ve bot dışlanmış, **621 gerçek ziyaret** (03-donusum §0).
---
## Yönetici özeti (5 madde)
1. **Sorun tek bir "sevk" sorunu değil, iki ayrı sorun.** 30g'de 621 gerçek ziyaretin 3'ü liste üretti (**%0,48**, %95 GA 0,2–1,4). Kayıp iki yerde toplanıyor: **593 kişi sıralamayı hiç girmiyor** (%95,5) ve **sihirbazı bitiren 22 kişinin 19'u listeye ulaşmıyor** (tamamlandı → liste **3/22 = %13,6**, GA 5–33). Hunininin üst yarısı trafik sorunu, alt yarısı ürün sorunu — ve alt yarı daha ucuz.
2. **Aritmetik, önce alt yarıyı düzeltmeyi söylüyor.** Bugünkü oranlarla: ziyaret→sıra iki katına çıkarsa (4,5→%9) aylık liste **3 → 6**; tamamlandı→liste %50'ye çıkarsa **3 → 11**. Yukarıya trafik pompalamak, aşağıdaki %86'lık deliğe daha fazla insan dökmek demek.
3. **Girişin maliyeti giriş kapısında bitmiyor — asıl kayıp girişten SONRA.** Girişli 14 oturumun 7'si `/listem`'i hiç görmedi (**7/14**, GA 27–73). Koddan kök neden: **navbar'da `/listem`'e giden hiçbir bağlantı yok** (`src/components/site-header.tsx:8-36` + `src/features/kullanici/components/user-nav.tsx:45-63` — girişli kullanıcı yalnız kredi pill'i, çıkış ve manuel liste çekmecesini görüyor) ve varsayılan giriş callback'i `"/"` (`src/features/kullanici/components/giris-karti.tsx:19-20`). Navbar'dan giriş yapan kullanıcı ana sayfaya düşüyor ve listeye dönecek kalıcı yol bulamıyor.
4. **"Butona basıp liste alamayan" kullanıcıyı bugünkü ölçümle GÖREMİYORUZ.** `liste_olusturuldu` yalnız başarı anında atılıyor (`src/features/rapor/components/liste-uretici.tsx:127`); denemenin kendisi hiç ölçülmüyor. Üç dal tamamen sessiz: profil bulunamadı (`:205-213`), oturum düşmüş → girişe sekme (`:145-146`), kullanıcı 20–60 sn'lik üretim sırasında sekmeyi kapattı (hiçbir olay yok). Üstelik `liste_uretim_hata` kodu **21 Eyl'de eklendi** (commit `cf19903`), yani 30 günlük pencerede hata ölçümü hiç yoktu. **Eklenecek tek olay: `liste_uretim_basladi`** (§2.4).
5. **Yapay zekâ listesine götüren 19 giriş noktası var; 11'i tamamen ölçüsüz.** En kritik körler: `/sonuc`'taki ana CTA "Yapay Zeka listemi kur" (`sihirbaz-cagri-karti.tsx:328-335` — tıklama olayı yok), o CTA'nın açtığı sihirbaz modalının açılış/kapanışı (katalog kapısında `kapi_acildi`/`kapi_kapatildi` var, `/sonuc` modalında **yok**), `/listem` boş durum CTA'sı (`listem-bos-cta.tsx:30`) ve çekmecedeki "Listemde aç" (`liste-cekmecesi.tsx:300-308`). Navbar'da ise hiç giriş noktası yok.
---
## Veri güvenilirliği — önce bunu oku
- **Canlı sorgu yok.** Rybbit MCP bağlı değil; bu raporda **tek bir yeni ölçüm yok**. Tüm sayılar dünkü raporlardan alındı, üzerine yalnız güven aralığı ve örneklem hesabı yapıldı (yerel Python; Wilson aralığı, n = z²p(1−p)/h², iki oran için n = (z_α+z_β)²·[p₁q₁+p₂q₂]/Δ²).
- **Örneklem küçük — huninin alt yarısında n = 3–28.** Aşağıdaki **her** oran "yön gösterir, kesin değil" kategorisindedir; **paydası 40'ın altındaki hiçbir yüzde karar için tek başına kullanılmamalı**. Ham kesirler ve GA'lar her satırda verildi.
- **Huni sıralı değil, kesişimli.** Rybbit'te oturum içi bayraklarla kurulmuş bir huni bu; `/sonuc` bazı oturumlarda `sihirbaz_tamamlandi`'dan önce görülüyor (katalog kapısı akışı) ve `girisli oturum` sayısı `sihirbaz_tamamlandi`'nın alt kümesi değil (önceden giriş yapmış kullanıcılar da var). Bu yüzden adımlar arası oranlar "şu adımı yapanların şu kadarı diğerini de yaptı" diye okunmalı, "şu kadarı ilerledi" diye değil.
- **Google OAuth dönüşü oturumu bölüyor** (01-analitik §2, madde "Ölçüm hatası"). Bu yüzden huni hem oturum hem cihaz bazında verildi; ikisi de aynı yönü gösteriyor.
- **21 Eyl 15:20'den sonra 7 yeni olay canlıya çıktı** (`kapi_acildi`, `kapi_kapatildi`, `sonuc_goruntulendi`, `cta_form_goruntulendi`, `paket_goruntulendi`, `giris_basarili`, `liste_uretim_hata`) (03-donusum §7). 30 günlük seri bunlardan **önce** — bu rapordaki huni eski ölçüm setiyle kurulmuştur ve yeni olaylarla karşılaştırılamaz.
- **21 Eyl 23:34 commit'leri (`ea3310a`, `992a01a`) canlıda mı bilinmiyor.** Katalogdaki kompakt sıra satırı (`universite-icerik.tsx:180`, `bolum-icerik.tsx:267`) ve üretim sonrası geçiş düzeltmesi bu commit'lerde; deploy Bilal'in kararı. **Doğrulanmalı.**
- **7 günlük rakamlar şüpheli** (03-donusum §1a notu): 7g'de sıra girme oranının %12,6'ya çıkması iç filtrenin yakalamadığı QA/tarayıcı-ajanı trafiğiyle açıklanabilir. 7g sütunu bu raporda yalnız referans için var.
- Bu raporda kişisel veri yok; iç hesaplar sayılmadı, kimlikler yazılmadı.
---
## 1. Huni — varış noktası `liste_olusturuldu`
### 1a. Oturum zinciri (30g, iç + bot hariç)
Kaynak: 03-donusum **§1a** (tüm ham sayılar). Oranlar ve GA'lar bu raporda hesaplandı.
| # | Adım | Kalan | Önceki adıma göre | %95 GA | Bu adımda kaybedilen | Ziyaretin %'si |
|---|---|---|---|---|---|---|
| 0 | Ziyaret (gerçek oturum) | **621** | — | — | — | %100 |
| 1 | `sira_girildi` | **28** | 28/621 = **%4,5** | 3–6 | **593** | %4,51 |
| 2 | `sihirbaz_adim` adım=2 | 25 | 25/28 = %89 | 73–96 | 3 | %4,03 |
| 3 | `sihirbaz_adim` adım=3 | 24 | 24/25 = %96 | 80–99 | 1 | %3,86 |
| 4 | `sihirbaz_tamamlandi` | **22** | 22/24 = %92 | 74–98 | 2 | %3,54 |
| 5 | `/sonuc` görüldü | 23 | *kesişim, alt küme değil* | — | — | %3,70 |
| 6 | Oturumda giriş yapılmış ("tanımlı") | **14** | 14/22 = **%64** | 43–80 | 8 | %2,25 |
| 7 | `/listem` görüldü | **7** | 7/14 = **%50** | 27–73 | **7** | %1,13 |
| 8 | **`liste_olusturuldu`** | **3** | 3/7 = %43 | 16–75 | 4 | **%0,48** |
| 9 | `kilit_goruntulendi` | 2 | 2/3 | — | 1 | %0,32 |
| 10 | `/paket` | 1 | 1/2 | — | 1 | %0,16 |
| 11 | `odeme_baslatildi` | **0** | — | — | 1 | %0 |
**Uçtan uca:** ziyaret → liste **3/621 = %0,48** (GA 0,2–1,4) · sıra → liste **3/28 = %10,7** (GA 4–27) · sihirbaz tamam → liste **3/22 = %13,6** (GA 5–33).
**En çok kaybeden adım, mutlak sayıyla:** adım 1 (ziyaret → sıra girişi), **593 kişi**.
**En çok kaybeden adım, orandan sonra kalan hacme göre:** adım 6–8 zinciri — sihirbazı bitiren 22 kişinin **19'u** (%86) listeye hiç ulaşmıyor.
### 1b. Cihaz zinciri (30g, 576 cihaz) — OAuth'un oturum bölmesini aşmak için
Kaynak: 03-donusum **§1b**.
| Adım | Cihaz | Önceki adıma göre | %95 GA |
|---|---|---|---|
| Cihaz | 576 | — | — |
| `sira_girildi` | 27 | %4,7 | 3–7 |
| `sihirbaz_tamamlandi` | 22 | 22/27 = %81 | 63–92 |
| `/sonuc` | 21 | 21/22 = %95 | 78–99 |
| Tanımlı (girişli) | **8** | 8/21 = **%38** | 21–59 |
| `/listem` | **4** | 4/8 = **%50** | 22–78 |
| **`liste_olusturuldu`** | **3** | 3/4 = %75 | 30–95 |
| `/paket` | 1 | — | — |
| `odeme_baslatildi` | 0 | — | — |
Cihaz bazında da aynı iki delik: **/sonuc → giriş %38** ve **giriş → /listem %50**. Cihaz görünümünde üretimin kendisi (4 → 3) sorunsuz duruyor — yani liste üretimi teknik olarak çalışıyor, insan oraya varmıyor.
### 1c. Mobil / masaüstü
Kaynak: 03-donusum **§1a** mobil ve masaüstü sütunları.
| Adım | Mobil | Masaüstü |
|---|---|---|
| Ziyaret | 492 | 129 |
| Tek sayfada çıkan | 362 (%74) | 78 (%60) |
| `sira_girildi` | 20 (%4,1) | 8 (%6,2) |
| `sihirbaz_tamamlandi` | 15 | 7 |
| `/sonuc` | 15 | 8 |
| `/giris` (botsuz) | ~10 | ~1 |
| Girişli oturum | 12 | 2 |
| `/listem` | 5 | 2 |
| **`liste_olusturuldu`** | **2** (492'nin %0,41'i) | **1** (129'un %0,78'i) |
n = 2 ve n = 1. **Mobil–masaüstü farkı bu huniden okunamaz**; tek söylenebilir şey trafiğin %79'unun mobil olduğu ve sıra girişinin mobilde %4,1'e karşı masaüstünde %6,2 olduğu (ikisi de GA'ları çakışıyor). Tek istatistiksel olarak ayrışan mobil sinyal, dünkü raporlarda ölçülmüş olan **+ tıklama oranı**: mobil %11,9 (GA 9,7–14,4) vs masaüstü %3,8 (GA 1,7–7,9) (09-analitik-tur2 §Soru 1e).
### 1d. Giriş sayfası tipine göre
Kaynak: 03-donusum **§2 / Sızıntı 1** tablosu.
| Giriş sayfası | Oturum | Tek sayfa | `sira_girildi` | Oran | %95 GA |
|---|---|---|---|---|---|
| Ana sayfa `/` | 67 | 42 (%63) | **11** | **%16,4** | 9–27 |
| `/rehber/*` | 73 | 63 (%86) | 5 | %6,8 | 3–15 |
| `/universite/*` (1. sayfa) | 296 | 205 (%69) | 9 | %3,0 | 1,6–5,6 |
| `/bolum/*` | 112 | 80 (%71) | 3 | %2,7 | 0,9–7,6 |
| `/universite/*/sayfa/N` | 56 | 40 (%71) | **0** | %0 | 0–6,4 |
| Diğer | 17 | 10 | 0 | — | — |
Giriş yapan 6 kişinin iniş sayfaları: ana sayfa 3, `/universite` 1, `/rehber` 1, `/bolum` 1 (03-donusum §5).
**`liste_olusturuldu`'nun giriş sayfası kırılımı dünkü raporlarda yok — ölçülemedi.** 3 listenin hangi iniş sayfasından geldiği bu verilerden çıkarılamıyor. Sıra girişi kaynağına göre kırılım var (03-donusum §3, olay sayısı): **kapı (katalogdaki +) 14 · ana sayfa hero 12 · düzenle 5 · katalog CTA formu 3**.
### 1e. 7 günlük (15–21 Eyl, 95 gerçek ziyaret) — yalnız referans
Ziyaret 95 → sıra 12 → tamam 9 → `/sonuc` 9 → `/giris` 6 → denendi 3 → girişli 9 → `/listem` 4 → **liste 2**. (03-donusum §1a.) Payda 4–12 arası; bu sütundan **hiçbir yön okunmamalı** (raporun kendi uyarısı: iç filtrenin yakalamadığı QA trafiği olabilir).
---
## 2. Koddan ölçüm deliği envanteri
### 2.1 `liste_olusturuldu` gerçekte nerede atılıyor
`src/features/rapor/components/liste-uretici.tsx:126-130` — **yalnızca** server action `listeOlustur()` `ok: true` döndüğünde:
```
if (sonuc.ok) {
olay("liste_olusturuldu", {
tur: profil.tur,
sira_kovasi: siraKovasi(profil.sira),
});
```
Bu bileşen `/listem?uret=1` ile gelindiğinde **mount'ta kendiliğinden** üretime başlıyor (`:162-176`); ayrı bir "üret" butonu yok. Yani `liste_olusturuldu` gerçekten "yapay zekâ listesi kuruldu" demek — adının söylediği şeyi ölçüyor. (Karşıt örnek: `program_eklendi` 21 Eyl öncesinde "+'ya basıldı" ölçüyordu — 09-analitik-tur2 §Soru 1.)
Olay 2 Ağu'dan beri kodda (commit `0b92f99`), yani 30 günlük pencerenin tamamını kapsıyor. **Rybbit'teki 3 kayıt gerçek.**
### 2.2 Ondan önceki adımlar ölçülüyor mu?
| Adım | Ölçülüyor mu | Kanıt (dosya:satır) |
|---|---|---|
| Sıralama girildi | ✅ `sira_girildi{kaynak, tur, sira_kovasi}` | `hero-form.tsx:82`, `cta-sira-form.tsx:149`, `tercih-profili-kapisi.tsx:197` |
| Sıra formu hatası | ✅ `sira_form_hata{kaynak}` | `hero-form.tsx:88`, `cta-sira-form.tsx:156`, `tercih-profili-kapisi.tsx:203` |
| Sihirbaz adım 1 | ❌ **ölçülmüyor** — `sihirbaz_adim` yalnız ileri geçişte ve adım 2'den itibaren atılıyor | `sihirbaz-adimlar.tsx:205` (`if (yeniAdim > adim)`) |
| Sihirbaz adım 2–3 | ✅ `sihirbaz_adim{adim}` | `sihirbaz-adimlar.tsx:205` |
| Sihirbaz tamamlandı | ✅ `sihirbaz_tamamlandi{...}` | `sihirbaz-adimlar.tsx:520` |
| `/sonuc` görüntülemesi | ✅ `sonuc_goruntulendi{girisli, sira_kovasi}` — **21 Eyl'den beri** | `sihirbaz-cagri-karti.tsx:89-99` |
| **`/sonuc` ana CTA tıklaması** | ❌ **ölçülmüyor** | `sihirbaz-cagri-karti.tsx:328-335` — `onClick={sihirbaziBaslat}`, hiç `olay()` yok |
| **`/sonuc` sihirbaz modalı açıldı/kapandı** | ❌ **ölçülmüyor** | `sihirbaz-modal.tsx` içinde hiç `olay()` yok (katalog kapısında karşılığı var: `use-tercih-profili.ts:174` + `tercih-profili-kapisi.tsx:79`) |
| Giriş denendi / başarılı / hata | ✅ `giris_denendi`, `giris_hata` (istemci) + `giris_basarili` (sunucu, 21 Eyl'den beri) | `giris-form.tsx:68,74,97,108`; `analitik-sunucu.ts:19` |
| **`/listem` görüntülemesi** | ⚠️ **yalnız pageview** — özel olay yok | `src/app/listem/page.tsx` — sayfada hiç `olay()` yok |
| **"Listemi oluştur" butonu tıklaması** | ❌ **ölçülmüyor** (bkz. §2.3 — aslında böyle bir buton yok) | — |
| **Üretim denemesi başladı** | ❌ **ölçülmüyor** — `liste_uretim_basladi` yok | `liste-uretici.tsx:79-93` |
| Kredi yetersiz | ✅ `kredi_bitti` (30g: **0 kayıt**) | `liste-uretici.tsx:143`, `tercih-degisti-modali.tsx:114` |
| Üretim hatası | ⚠️ `liste_uretim_hata{kod}` — kod **21 Eyl'de** eklendi (`cf19903`); 30g penceresinde yoktu | `liste-uretici.tsx:117, 148, 171, 179` |
| Kilit (ücretli içerik) görüldü | ✅ `kilit_goruntulendi` | `listem-govde.tsx:139,144` |
| Rapor yazdırıldı (değerin tüketimi) | ❌ **ölçülmüyor** | `rapor-yazdir.tsx` / `yazdir-butonu.tsx`'te `olay()` yok |
### 2.3 Butona basıp liste alamayan kullanıcıyı görebiliyor muyuz? **Hayır.**
Önce bir yanlış anlamayı düzeltmek gerekiyor: **"listemi oluştur" diye basılan bir buton yok.** Üretim, kullanıcı `/listem?uret=1`'e vardığı anda otomatik başlıyor (`liste-uretici.tsx:204-215`). "Buton" dediğimiz şey aslında bu URL'ye götüren 4 ayrı yol:
1. `/sonuc`'ta sihirbazı tamamlama → `ilerle()` → `router.push("/listem?uret=1")` (`sihirbaz-cagri-karti.tsx:180-189`)
2. `/sonuc`'ta hazır seçimlerle ana CTA'ya basma → aynı `ilerle()` (`:197-205`)
3. `/listem` boş durumundaki CTA → `<Link href="/listem?uret=1">` (`listem-bos-cta.tsx:30`)
4. Girişten dönüş → `callback=/listem?uret=1` (`sihirbaz-cagri-karti.tsx:185`)
Hiçbirinde tıklama olayı yok. Ve vardıktan sonra **dört sessiz dal** var:
| Dal | Kod | Kullanıcı ne görüyor | Olay |
|---|---|---|---|
| **Girişsiz geldi** | `listem-icerik.tsx:43` `verifySession(geriYol)` sunucuda `/giris`'e yönlendiriyor | Giriş sayfası | ❌ hiçbir şey — **`/listem` pageview'ı bile oluşmuyor** (sunucu yönlendirmesi HTML'den önce) |
| **Profil bulunamadı** | `liste-uretici.tsx:205-213` — `tercihProfiliOku() ?? sunucuProfil` null | "Henüz Yapay Zeka listen yok" boş durumu | ❌ hiçbir şey |
| **Oturum düşmüş (AUTH)** | `liste-uretici.tsx:145-146` — `router.push("/giris?callback=...")` | Giriş sayfası | ❌ hiçbir şey |
| **Üretim sırasında terk** | 20–60 sn süren `await listeOlustur(...)` (`:110-115`); 90 sn sonra "uzun sürdü" ekranı (`:195-201`) | İskelet + "Listen hazırlanıyor" | ❌ hiçbir şey — sekme kapanırsa ne başarı ne hata düşer |
**22 Eyl notu — beşinci dal, bu rapor yazılırken bulundu.** Çalışma ağacında (commit'lenmemiş, başka bir ajanın/Bilal'in işi) `liste-uretici.tsx`'e yeni bir `sunucu-yok` durumu ve `liste_uretim_hata { kod: "SUNUCUYA_ULASILAMIYOR" }` olayı eklenmiş (`:165-180`, `/api/saglik` yoklaması). Kod yorumuna göre neden: liste DB'ye yazıldıktan sonra konteyner ölürse ters vekilin düz metin "Bad Gateway" cevabı geliyor ve WebKit bunu sayfa yerine **dosya olarak indiriyor** (iPad + Chrome raporu) — yani kullanıcı kredisini harcıyor, listesi kuruluyor ve ekranda bir `.txt` buluyor. Bu, "butona bastı, liste alamadı" dalının canlıda gerçekten yaşandığının ilk somut kanıtı ve §2.4'teki `liste_uretim_basladi` ihtiyacını güçlendiriyor: bugün bu vakanın **kaç kez yaşandığı** bilinmiyor, çünkü payda yok. Bu dosyaya dokunulmadı; satır numaraları çalışma ağacındaki hâle göredir.
Yani bugün Rybbit'te `liste_olusturuldu` = 3 görüyoruz ama **bunun paydası yok**. 22 sihirbaz tamamlayandan 19'unun hangi duvara çarptığı — giriş mi, profil kaybı mı, yavaşlık mı, hata mı, yoksa hiç oraya gitmemek mi — ölçümle ayrılamaz.
### 2.4 Eklenecek **tek** olay
```
liste_uretim_basladi {
kaynak: "sihirbaz" | "hazir_cta" | "bos_durum" | "giris_donusu",
girisli: "evet" | "hayir",
yeniden_deneme: "evet" | "hayir"
}
```
**Çağrı yeri:** `src/features/rapor/components/liste-uretici.tsx`, `uret()` fonksiyonunun ilk satırı (`:101-103`, `setDurum({ ad: "uretiliyor" })`'un yanına) — `olay()`, `olayBirKez()` değil; "Tekrar dene" (`:261`) de sayılmalı, `yeniden_deneme: "evet"` ile.
Bu tek olay huninin alt yarısının **paydasını** yaratır: `liste_uretim_basladi` sayısından `liste_olusturuldu` + `liste_uretim_hata` + `kredi_bitti` çıkarıldığında geriye kalan = **terk edilen üretim** (sekme kapatıldı / çok uzun sürdü). Bugün bu fark hesaplanamıyor.
`liste-uretici.tsx:101`'deki `uret()` çağrılmadan dönen iki dala ayrıca olay gerekir; ama `OlayAdi` birliğini büyütmemek için aynı olayın özelliğine sıkıştırılabilir:
- `:212` profil-yok dalı → `liste_uretim_basladi { kaynak, sonuc: "profil_yok" }` (üretim başlamadı ama deneme sayılır)
- Girişsiz sunucu yönlendirmesi (`listem-icerik.tsx:43`) istemci tarafında hiç mount olmadığı için **ancak sunucu olayıyla** (`analitik-sunucu.ts`, `giris_basarili` deseni) görülebilir — ikinci öncelik.
**Ek olarak (ikinci tur, tek satırlık işler):**
- `sihirbaz_acildi {kaynak}` / `sihirbaz_kapatildi {adim}` → `sihirbaz-cagri-karti.tsx:197-205` ve `sihirbaz-modal.tsx` `onOpenChange`. Katalog kapısında karşılığı zaten var (`kapi_acildi`/`kapi_kapatildi`) — `/sonuc` modalı bu simetriyi kaçırıyor ve `/sonuc`'un asıl dönüşüm yüzeyi orası.
- `listem_goruntulendi {rapor_var, girisli}` → `/listem` sayfasında; pageview yerine olay, çünkü OAuth dönüşü ve `?uret=1` varyantları pageview'ı bölüyor.
---
## 3. Girişin maliyeti
### 3.1 `/sonuc` → giriş → `/listem` zinciri (30g)
| Geçiş | Kesir | Oran | %95 GA | Kaynak |
|---|---|---|---|---|
| `/sonuc` → `/giris` görüldü (botsuz) | 11/23 | %48 | 29–67 | 03-donusum §1a |
| `/giris` → `giris_denendi` | 6/11 | %55 | 28–79 | 03-donusum §1a, §6 |
| `giris_denendi` → başarılı | **6/6** | **%100** | 61–100 | 03-donusum §6 (hepsi Google; `giris_hata` 0) |
| `sihirbaz_tamamlandi` → girişli oturum | 14/22 | %64 | 43–80 | 03-donusum §1a |
| **Girişli oturum → `/listem`** | **7/14** | **%50** | **27–73** | 03-donusum §1a |
| `/listem` → `liste_olusturuldu` | 3/7 | %43 | 16–75 | 03-donusum §1a |
| Cihaz bazında: `/sonuc` → tanımlı | 8/21 | %38 | 21–59 | 03-donusum §1b |
| Cihaz bazında: tanımlı → `/listem` | 4/8 | %50 | 22–78 | 03-donusum §1b |
**Giriş mekanizması sorun değil: deneyen 6 kişinin 6'sı başardı.** Sorun (a) `/sonuc`'tan giriş sayfasına yalnız 11 kişinin gitmesi, (b) giden 11'in 5'inin butona bile basmaması, ve (c) **giriş yapanın yarısının listeye ulaşamaması**.
### 3.2 Giriş yapmış ama liste üretmemiş kullanıcı — davranış
Dünkü verilerden çıkarılabilenler (03-donusum §2/Sızıntı 3, §6):
- **Girişli ama `/listem`'i hiç görmeyen 7 oturum:** dünkü raporlarda bu 7 oturumun dizisi **yok** — sonraki davranışları **ölçülemedi**. Bu, Rybbit bağlanınca ilk sorulacak soru (§"Bilal'den istenen").
- **`/listem`'i görüp liste üretmeyen 4 oturum:** yine dizi yok. Ancak ürettiklerinin dizisi var (03-donusum §2/Sızıntı 3, S9):
- 28 Ağu mobil: rehber → sihirbaz → `/sonuc` → 7 program ekledi → `/listem` → **liste üretti** → kilit gördü → katalogda gezmeye devam (24 dk)
- 17 Eyl masaüstü: **liste üretti** → kilit ×2 → danışmana 1 soru → çıktı (93 sn)
- 21 Eyl mobil: sihirbaz → `/sonuc` → giriş CTA → Google → `/listem`
- **Girişten sonra `/sonuc`'ta bekleyenler:** girişli 6 `/sonuc` oturumunun `/sonuc`'tan çıkışa medyan süresi 696 sn (mobil) ve 308 sn (masaüstü) — anonim kullanıcıların 33 sn'siyle kıyaslanınca giriş yapan kullanıcı **siteyi kullanıyor**, sadece yapay zekâ listesine gitmiyor (03-donusum §2/Sızıntı 2 tablosu).
- **`kredi_bitti` 30g: 0.** Yani kimse "kredim yetmedi" duvarına çarpmadı; giriş yapan herkesin 5 deneme kredisi duruyordu. Liste üretmemenin nedeni kredi **değil**.
**Koddan en güçlü açıklama (koddan çıkarım):** girişten sonra listeye götüren yol kalıcı değil.
- Navbar'da `/listem` linki yok: `src/components/site-header.tsx:8-36` (logo + katalog araması + `UserNav`) ve `src/features/kullanici/components/user-nav.tsx:45-63` (kredi pill'i → `/paket?kaynak=nav`, çıkış, `ListemButonu`).
- `ListemButonu` "Kendi Listem" çekmecesidir, `/listem` değil — üstelik manuel liste boşken **hiç render edilmiyor** (`listem-butonu.tsx:24`: `if (liste.length === 0) return null;`). Kendi kod yorumu da bunu söylüyor: *"'Listem' adı Yapay Zeka raporunun yaşadığı /listem sayfasına aittir — isim çakışmasın"* (`:4-5`).
- Varsayılan giriş callback'i `"/"`: `giris-karti.tsx:19-20`. Navbar'daki "Giriş yap" butonundan (`user-nav.tsx:39`) giren kullanıcı ana sayfaya düşer.
- `/listem`'e giden tek kalıcı bağlantı manuel liste çekmecesinin dibindeki "Listemde aç" (`liste-cekmecesi.tsx:300-308`) — çekmece ise ancak manuel listede program varsa açılabiliyor.
Bu, "girişli 14 oturumun 7'si `/listem`'i hiç görmedi" bulgusunun en basit açıklaması: **kullanıcı listeye giden kapıyı bulamıyor.** n = 14 olduğu için bu bir hipotez, kanıt değil — ama düzeltmesi bir navbar linki kadar ucuz.
---
## 4. Sevk noktası envanteri (koddan çıkarım)
"Yapay zekâ listesi" hedefine götüren tüm giriş noktaları. **Kör nokta** = tıklandığı ölçülmüyor.
| # | Giriş noktası | Dosya:satır | Nerede görünür | Ölçüm |
|---|---|---|---|---|
| 1 | Ana sayfa hero sıra formu | `hero-form.tsx:82` | `/` ilk ekran | ✅ `sira_girildi{hero}` — ama **formun görüntülendiği ölçülmüyor** (hero'da `cta_form_goruntulendi` yok) |
| 2 | Ana sayfa kapanış CTA ("Ücretsiz dene" / "Üniversitelere göz at") | `hero-focus-button.tsx:20-29, 46-57` | `/` en alt | ❌ **kör** |
| 3 | Katalog/rehber sıra formu — alt kart | `cta-sira-form.tsx:112, 149` | `/universite/*`, `/bolum/*`, `/rehber/*`, `/rehber` (tablonun altında) | ✅ `cta_form_goruntulendi{konum}` + `sira_girildi{cta}` (21 Eyl'den beri) |
| 4 | Katalog kompakt sıra satırı — başlık altı | `universite-icerik.tsx:180`, `bolum-icerik.tsx:267` | katalog ilk ekran | ✅ aynı olaylar, `konum:"ust"` — **ama commit `992a01a` 21 Eyl 23:34; canlıda mı doğrulanmalı** |
| 5 | Katalog + butonu → tercih profili kapısı | `program-ekle-butonu.tsx:60`, `use-tercih-profili.ts:174` | katalog tabloları + `/sonuc` | ✅ `kapi_acildi{tetik}`, `kapi_kapatildi{adim}`, `sira_girildi{kapi}` |
| 6 | Katalog arama modalındaki funnel kartı | `arama-funnel-karti.tsx:82-99` | **her sayfa** (header araması) | ❌ **kör** — üstelik sitedeki tek "her sayfada var" sevk noktası |
| 7 | **`/sonuc` ana CTA "Yapay Zeka listemi kur"** | `sihirbaz-cagri-karti.tsx:328-335` | `/sonuc` tablo altı | ❌ **kör** — huninin en kritik butonu |
| 8 | `/sonuc` sihirbaz modalı (7'nin açtığı) | `sihirbaz-modal.tsx` | `/sonuc` | ❌ **kör** — açılış/kapanış olayı yok; adım 1'de terk eden hiç görünmez |
| 9 | `/sonuc` hazır panel (girişsiz, `?hazir=1`) | `sihirbaz-cagri-karti.tsx:272-306` | `/sonuc` tablo altı | ✅ `hazir_panel_goruntulendi` + `giris_cta_tiklandi{hazir_panel}` |
| 10 | `/sonuc` tadımlık satırı CTA | `tadimlik-satiri.tsx:100, 184` | `/sonuc` | ⚠️ `tadimlik_goruntulendi` 30g'de **0 kayıt**; hook 21 Eyl'de düzeltildi, **hâlâ doğrulanmadı** (03-donusum §7) |
| 11 | `/sonuc` "Listeni gör" (raporu olan kullanıcı) | `sihirbaz-cagri-karti.tsx:264-270` | `/sonuc` | ❌ **kör** |
| 12 | Manuel liste çekmecesi — "Listemde aç" → `/listem` | `liste-cekmecesi.tsx:300-308` | çekmece (manuel listede ≥1 program varsa) | ❌ **kör** |
| 13 | Manuel liste çekmecesi — "Giriş yap, kaydet" | `liste-cekmecesi.tsx:255-263` | çekmece | ✅ `giris_cta_tiklandi{liste_cekmecesi}` |
| 14 | Kaydet banner | `kaydet-banner.tsx:43, 86` | liste ≥3 programda | ✅ `kaydet_banner_goruntulendi` + `giris_cta_tiklandi` (21 Eyl'den beri) |
| 15 | `/listem` boş durum CTA "Yapay Zeka listeni kur" | `listem-bos-cta.tsx:30` | `/listem` (rapor yokken) | ❌ **kör** — üstelik profil yoksa CTA `/`'a gönderiyor, kullanıcı en baştan başlıyor |
| 16 | `/paket` içindeki `/listem?uret=1` linki | `paket-satinal.tsx:157` | `/paket` | ❌ **kör** |
| 17 | `/odeme/sonuc` "Listeni gör" | `odeme-sonuc-karti.tsx:64` | ödeme sonrası | ❌ **kör** |
| 18 | `/odeme/sonuc` "24'lük listeni oluştur" (rapor yokken) | `rapor-yok-cta.tsx:24` | ödeme sonrası | ❌ **kör** |
| 19 | `/meraklisina` demo kapanış CTA | `meraklisina-demo.tsx:244` | `/meraklisina` | ❌ **kör** |
| — | **Navbar** | `site-header.tsx:8-36`, `user-nav.tsx:25-64` | **her sayfa** | ⛔ **hiç giriş noktası yok** — ne "listeni kur" ne `/listem` linki |
**Sayı:** 19 giriş noktası, **11'i kör** (2, 6, 7, 8, 11, 12, 15, 16, 17, 18, 19). Kalıcı/her sayfada görünen sevk noktası sayısı: **1** (#6, arama modalı içindeki funnel kartı) — ve o da kör.
**Ölü kod notu:** `src/features/liste/components/secimlerim-paneli.tsx` kendi CTA'sını taşıyor ama hiçbir yerden import edilmiyor (`grep -rn "SecimlerimPaneli" src/` yalnız kendi export satırını buluyor). Envantere dahil edilmedi; ayrı bir temizlik işi olarak işaretlendi.
---
## 5. Kaç veriye ihtiyacımız var
Varsayımlar: sezon dışı hız = son 7 günün gerçeği, **~95 ziyaret/hafta** (03-donusum §1a). 30 günlük hızlar bu orana ölçeklendi. Wilson %95 GA; önce/sonra karşılaştırmalarında güç %80, tek yönlü α = 0,10 (yön okumak için) ve parantezde çift yönlü α = 0,05.
### 5.1 Haftalık payda (sezon dışı tahmin)
| Adım | 30g toplam | 30g/hafta | Sezon dışı tahmin (95 ziyaret/hafta) |
|---|---|---|---|
| Ziyaret | 621 | 145 | **95** |
| `sira_girildi` | 28 | 6,5 | **4,3** |
| `sihirbaz_tamamlandi` | 22 | 5,1 | **3,4** |
| Girişli oturum | 14 | 3,3 | **2,1** |
| `/listem` | 7 | 1,6 | **1,1** |
| `liste_olusturuldu` | 3 | 0,7 | **0,5** |
### 5.2 Bir iyileştirmenin işe yaradığını anlamak için gereken süre
| Ölçülecek şey | Gereken n | Payda/hafta | Hafta/kol | Toplam süre |
|---|---|---|---|---|
| Ziyaret → liste tek oranı ±0,5 puanla okumak (p≈%0,5) | 734 ziyaret | 95 | — | **~8 hafta** |
| Ziyaret → liste **3×'e** çıktı mı (%0,48 → %1,44) | 928/kol | 95 | 10 | **~20 hafta** (çift yönlü 34) |
| Ziyaret → sıra **2×** (%4,5 → %9) | 278/kol | 95 | 3 | **~6 hafta** (çift yönlü 10) |
| Tamamlandı → liste %14 → %40 | 24/kol | 3,4 | 7 | **~14 hafta** |
| Girişli oturum → `/listem` %50 → %80 | 21/kol | 2,1 | 10 | **~19 hafta** |
| `/listem` → liste %43 → %75 | 19/kol | 1,1 | 18 | **~36 hafta** |
| Tamamlandı → liste oranını ±10 puanla okumak | 46 | 3,4 | — | **~14 hafta** |
**Okuma:** sezon dışında **hiçbir oran** makul sürede okunamıyor. Tek makul aday "ziyaret → sıra girişi"nin ikiye katlanması (~6 hafta/önce-sonra toplamı). `liste_olusturuldu`'nun kendisini oran olarak izlemek **2027 tercih sezonuna kadar anlamsız** — bu, dünkü 09-analitik-tur2 §Soru 2'nin sonucuyla birebir aynı yöne çıkıyor.
### 5.3 O hâlde ne yapılmalı
1. **Oran değil, adet izleyin.** Haftada ~0,5 liste, ~2 girişli oturum, ~3,4 sihirbaz tamamlama var — bunların **hepsi tek tek okunabilir**. Rybbit bağlanınca haftada 30 dakikalık sabit bir ritüel: `liste_uretim_basladi` atan her oturumun zaman çizelgesini tek tek oku.
2. **A/B testi yapmayın.** Trafiği ikiye bölmek her kolu 47 ziyaret/haftaya düşürür; yukarıdaki sürelerin hepsi ikiye katlanır. Tek varyant yayınlayıp önce/sonra bakın, ve yalnız **≥3× fark beklenen** değişiklikleri deneyin (dünkü 09-analitik-tur2 §"Düşük trafikte A/B yerine ne yapılmalı" ile aynı tavsiye).
3. **Sağlık kontrolü ≠ oran.** Yeni `liste_uretim_basladi` canlıya çıktıktan sonraki ilk 2 hafta tek soru: olay düşüyor mu, ve `liste_uretim_basladi − (liste_olusturuldu + liste_uretim_hata + kredi_bitti)` farkı kaç? O fark "sessiz terk"in ilk ölçümüdür.
### 5.4 Kaldıraç — hangi adımı düzeltmek kaç liste getirir
Bugünkü ölçülmüş oranlarla basit aritmetik (n küçük, **yön gösterir**):
| Senaryo | 621 ziyaret → | Aylık liste |
|---|---|---|
| **Bugün** | 28 sıra → 22 tamam → 3 liste | **3** |
| Üst huni 2× (ziyaret→sıra %9), alt huni aynı | 56 → 44 → 6 | **6** |
| Alt huni düzelir (tamam→liste %50), üst aynı | 28 → 22 → 11 | **11** |
| İkisi birden | 56 → 44 → 22 | **22** |
Alt huni bugün ziyaretin **%86'sını çöpe atıyor** ve düzeltmeleri (navbar linki, üretim ölçümü, giriş dönüşü) kod olarak üst huniden çok daha ucuz. **Trafik işine yatırım yapmadan önce alt huni kapatılmalı.**
---
## 6. Öncelik tablosu
| # | Bulgu | Kanıt | Önerilen iş (backlog önerisi) | Beklenen etki | Kesinlik |
|---|---|---|---|---|---|
| 1 | Üretim denemesinin paydası hiç ölçülmüyor; butona basıp liste alamayan görünmez | `liste-uretici.tsx:101-151, 205-213` (koddan) | `liste_uretim_basladi {kaynak, girisli, yeniden_deneme}` — `uret()`'in ilk satırı (§2.4) | Huninin alt yarısını ilk kez ölçülebilir kılar; başka hiçbir iş bu olmadan doğrulanamaz | **Yüksek** (kod kesin) |
| 2 | Girişli 14 oturumun 7'si `/listem`'i hiç görmedi; navbar'da `/listem` linki yok, giriş callback'i `"/"` | 03-donusum §1a; `site-header.tsx:8-36`, `user-nav.tsx:45-63`, `giris-karti.tsx:19-20` (koddan) | Girişli kullanıcıya navbar'da kalıcı "Listem" girişi (rapor varsa "Listeni gör", yoksa "Listeni kur"); navbar girişinde callback `/listem` | Girişli → `/listem` %50'den yukarı; kayıtlı kullanıcı = geri dönüş kancası | Orta (n=14, yön kuvvetli; kök neden koddan kesin) |
| 3 | `/sonuc`'un ana CTA'sı ve sihirbaz modalı tamamen kör | `sihirbaz-cagri-karti.tsx:328-335`, `sihirbaz-modal.tsx` (koddan) | `sihirbaz_acildi{kaynak}` / `sihirbaz_kapatildi{adim}` — katalog kapısındaki desenin aynısı | `/sonuc`'taki terkin hangi adımda olduğunu ilk kez gösterir | **Yüksek** (kod kesin) |
| 4 | Sihirbazı bitiren 22 kişiden 19'u listeye ulaşmıyor; kredi sebep değil (`kredi_bitti`=0) | 03-donusum §1a, §2/Sızıntı 3 | Girişten dönüşte üretimin gerçekten başladığını QA ile uçtan uca doğrula (Google OAuth → `/listem?uret=1` → liste) | Tek satışa giden yolun çalıştığından emin olmak | Orta (n=22) |
| 5 | 11 sevk noktası kör; kalıcı (her sayfada) sevk noktası yok | §4 tablosu (koddan) | Kör noktalara tek ortak olay: `sevk_tiklandi {yuzey}`; ve ürün kararı — her sayfada kalıcı bir sevk yüzeyi olmalı mı | Sevk noktalarının hangisinin çalıştığı bilinmiyor; ölçmeden yüzey eklemek kör | Orta |
| 6 | `tadimlik_goruntulendi` 30g'de 0; hook düzeltmesi sonrası hâlâ doğrulanmadı | 03-donusum §7 | Rybbit bağlanınca ilk bakılacak: 21 Eyl sonrası kaç kayıt var | Ölçüm | Yüksek |
| 7 | `rapor_yazdirildi` yok — ücretli değerin tüketildiği hiç ölçülmüyor | `rapor-yazdir.tsx`, `yazdir-butonu.tsx` (koddan) | Yeni olay (düşük öncelik; önce hacim) | Ödeme sonrası değer sinyali | Yüksek (kod kesin), düşük öncelik |
| 8 | Katalogdaki kompakt sıra satırı ve üretim geçiş düzeltmesi canlıda mı bilinmiyor | commit `992a01a`, `ea3310a` (21 Eyl 23:34) | Deploy durumunu doğrula; deploy tarihini ölçüm serisine not düş | Seri kırılması yönetimi | Yüksek |
| 9 | Liste kurulduktan sonra sunucu ölünce kullanıcı ekrana `.txt` indiriyor (iPad/WebKit) — kredi yandı, liste teslim edilmedi | çalışma ağacındaki `liste-uretici.tsx:159-180` yorumu + yeni `SUNUCUYA_ULASILAMIYOR` kodu (koddan) | Düzeltme zaten yazılmış; **canlıda kaç kez yaşandığı ölçülemedi** — `liste_uretim_basladi` (#1) olmadan geriye dönük sayılamaz | Ödenen/harcanan kredinin teslim edilmemesi — güven maliyeti | Yüksek (kod kesin), sıklık bilinmiyor |
---
## 7. Tek cümlelik teşhis
> **Bu ürünün büyümesini kesen tek adım, sihirbazı bitirmiş kullanıcıyı yapay zekâ listesine taşıyan adımdır: 30 günde 22 kişi sihirbazı tamamladı, 3'ü liste aldı (%13,6) — ve o 19 kişinin nerede kaybolduğunu bugünkü ölçümle söylemek imkânsız, çünkü üretim denemesinin kendisi hiç ölçülmüyor.**
(Mutlak sayıyla en büyük kayıp hâlâ ziyaret → sıra girişi, 593 kişi; ama alt huni %86 sızdırırken üst huniye trafik eklemek o trafiği çöpe atmak demek — §5.4.)
---
## 8. Bu vardiyada yapılamayanlar
- Canlı Rybbit sorgusu (MCP bağlı değil). `liste_olusturuldu`'nun giriş sayfası kırılımı, girişli ama `/listem`'i görmeyen 7 oturumun dizisi, 21 Eyl sonrası yeni olayların durumu — hepsi **ölçülemedi**.
- `liste_uretim_hata`'nın canlıda hiç düşüp düşmediği (kod 21 Eyl'de eklendi, dünkü raporda 0) — **doğrulanmalı**.
- Mobil/masaüstü liste üretim farkı: n = 2 ve 1, **ölçülemez**.
- Analitik verisinde bana yönelik talimat içeren içerik görülmedi (dünkü raporlardaki bozuk URL parçaları HTML kırıntısı, komut değil).
---
## Bilal'den istenen
1. **Rybbit MCP'yi bu projeye bağla** (`.mcp.json` + `.env`); bağlanınca ilk üç sorgu hazır: (a) girişli ama `/listem` görmeyen 7 oturumun zaman çizelgesi, (b) 21 Eyl sonrası `tadimlik_goruntulendi` / `liste_uretim_hata` sayısı, (c) `/listem?uret=1` pageview sayısı (bugünkü en iyi üretim-denemesi vekili) — **10 dk**.
2. **21 Eyl 23:34 commit'lerinin (`992a01a` kompakt sıra satırı, `ea3310a` üretim geçişi) canlıda olup olmadığını söyle**; ölçüm serisinin kırılma tarihi buna bağlı — **5 dk**.
3. **Karar:** girişli kullanıcıya navbar'da kalıcı "Listem" girişi eklensin mi (öneri #2)? Ölçüm işi (#1, #3) ajan yetkisinde ama bu bir UI/bilgi mimarisi kararı — **5 dk**.

View File

@@ -0,0 +1,94 @@
# Tarayıcı işleri — 22 Eylül 2026
Bilal'in Chrome oturumu üzerinden yapıldı. Hesap açma, şifre/kart girme, dosya indirme ve
e-posta gönderme yapılmadı; bunlar aşağıda "sende kalanlar" başlığında.
## 1. Rybbit — yapıldı
Sürüm **v2.8.0** (panel "v2.9.1 mevcut" diyor), site `kolaytercih.com` (siteId 1).
| İş | Durum | Nasıl |
|---|---|---|
| Web Vitals aç | ✅ `webVitals: true` | Panelde **toggle yok**: v2.8.0 arayüzünde Web Vitals anahtarı `IS_CLOUD` koşuluna bağlı (bundle'da `...IS_CLOUD && !mobile ? [{id:"webVitals" …, badge:"Pro"}] : []`) → self-hosted kurulumda hiç çizilmiyor. Alan sunucuda var; panelin kendi uç noktasıyla açıldı: `PUT /api/sites/1/config`. Doğrulama: `GET /api/sites/1` → `webVitals: true`, ve betiğin okuduğu genel uç `GET /api/site/tracking-config/1` → `webVitals: true`. |
| İç trafik filtresi | ✅ kısmen | Site Settings → Exclusions → IP Exclusions: **94.54.157.194** (bu oturumun çıkış IP'si) eklendi ve kaydedildi (`excludedIPs: ["94.54.157.194"]`). |
**Değişmeyenler (elle kontrol edildi):** `blockBots: true`, `trackIp: true`, `saltUserIds: false`,
`public: false`, `firstPartyProxy: false`, `sessionReplay` kapalı, tüm `track*` bayrakları eskisi gibi.
**Uyarılar:**
- `data-web-vitals="true"` betik özniteliği bu işi **çözmezdi**: betik `y.webVitals ?? f.enableWebVitals`
diyor, sunucu `false` (null değil) döndüğü için öznitelik hiç devreye girmiyordu. Doğru yer sunucu alanıydı.
- Veri ancak canlı sayfa betiği yeni yapılandırmayı çektikten **sonra** birikir; geçmişe dönük LCP/INP/CLS yok.
- IP dışlaması yalnız **bundan sonrasını** etkiler; geçmiş kirli veri temizlenmez.
- Ev/ofis IP'si dinamikse değişir; ayrıca trafiğin %79'u mobil ve mobil testler **hücresel IP'den** geldiği
için IP filtresi kendi telefon testlerini yakalamaz. Kalıcı çözüm: test cihazlarında
`localStorage` tabanlı bir opt-out ya da ayrı bir `tag`/`user_id` ile filtre.
- Rybbit v2.8.0'da **Google Search Console entegrasyonu uçları var** (`/api/sites/1/gsc/connect`);
panelde görünmüyorsa sürüm yükseltmesiyle gelebilir — Search Console verisini Rybbit'e bağlamak
ayrı bir iş olarak değerlendirilebilir.
## 2. Google Search Console — okundu (değişiklik yapılmadı)
Mülk `bilalgursen777@gmail.com` hesabında **değil**; oturumdaki ikinci Google hesabında
(`authuser=1`). SEO planının istediği dört başlık:
1. **Mülk türü: Alan adı** (`sc-domain:kolaytercih.com`) → www ve http varyantları zaten kapsanıyor,
yeni mülk eklemeye gerek yok.
2. **Sitemap:** `https://kolaytercih.com/sitemap.xml` — gönderim 21 Eyl 2026, son okuma 21 Eyl 2026,
durum **Başarılı**, keşfedilen sayfa **897** (raporun beklentisi 903'tü; 6 fark incelenebilir).
3. **Dizine ekleme (son güncelleme 18.09.2026):** dizinde **947**, dizin dışı **93**, 4 neden —
*Tarandı, şu anda dizine eklenmiş değil* 62 · *Keşfedildi, şu anda dizine eklenmiş değil* 23 ·
*Kullanıcı tarafından seçilen standart sayfa olmadan kopya* 4 · *Yönlendirmeli sayfa* 4.
**"Bulunamadı (404)" ve "Yumuşak 404" satırı yok.** T1'in (soft 404) taban çizgisi budur:
bugün sıfır; arşive taşınan 25 slug Google'a henüz yumuşak 404 olarak yansımamış.
4. **Üretken yapay zekâ raporu:** 28 gün → **3,8 B gösterim**; 3 ay (20 Haz–19 Eyl) → **5,63 B gösterim**,
427 sayfa. 28 günün ilk sayfaları: `rehber/siralama-sartlari-2026` 250 ·
`universite/mimar-sinan-guzel-sanatlar-universitesi` 219. 3 ayın ilk üçü:
`rehber/kac-siralama-ile-hangi-bolume-girebilirim` 328 · `rehber/siralama-sartlari-2026` 309 ·
`universite/mimar-sinan-guzel-sanatlar-universitesi` 231.
Web araması: 3 ayda 825 tıklama, 75,3 B gösterim, TO %1,1, ortalama konum 15,2.
Not: `universite/*/sayfa/N` sayfaları AI gösterimi de alıyor (Selçuk/sayfa/5 153, KTÜ/sayfa/2 96,
Uşak/sayfa/3 62) — T4'ün (sayfalama URL'lerini sitemap'e alma) gerekçesini güçlendiriyor.
## 3. Yandex Webmaster — ✅ doğrulandı
- Yandex hesabına giriş Bilal tarafından yapıldı (ajan hesap açamaz/şifre giremez).
- `https://kolaytercih.com` Webmaster'a eklendi.
- Cloudflare'da (`kolaytercih.com` zone) TXT kaydı eklendi: ad `@`, içerik
`yandex-verification: bbd3b26245d9d086`, TTL Auto. Kayıt sayısı 10 → 11.
Yayılım doğrulandı: `dig +short TXT kolaytercih.com` hem 1.1.1.1 hem 8.8.8.8'de kaydı döndürüyor
(mevcut iki `google-site-verification` kaydı bozulmadı).
- Webmaster → "Verify" → **Owner** rolü verildi (yöntem: DNS record, kod `bbd3b26245d9d086`).
- Site haritası gönderildi: `https://kolaytercih.com/sitemap.xml`, 22.09.2026, durum
**işleme kuyruğunda** (Yandex'te işlenmesi 1–2 hafta sürebilir).
- Meta etiketi alternatifi hâlâ geçerli ve T3 ile birlikte sigorta olarak eklenebilir:
`<meta name="yandex-verification" content="bbd3b26245d9d086" />`.
- Yapılmadı: "Yandex Turbo" vb. teklifler (gelmedi; gelirse reddedilecek).
## 4. YÖK İstatistik Excel'leri — indirildi
İzninle indirildi ve repoya kondu (`data/kaynak/`):
| Dosya | Kaynak | Boyut | İçerik |
|---|---|---|---|
| `yok-istatistik-ogrenci-sayilari-2025-2026.xls` | istatistik.yok.gov.tr → Öğrenci İstatistikleri → Öğrenci Sayıları → *Üniversite Bazında Öğrenci Sayıları*, öğretim yılı 2025-2026 | 251 KB | 717 satır × 20 sütun. Başlıklar: Üniversite Adı · Tür · İl · Öğrenim Türü · Okuyan Önlisans/Lisans/Yükseklisans/Doktora · Genel Toplam (her biri 3 alt sütun) |
| `yok-istatistik-ogretim-elemani-sayilari-2025-2026.xls` | aynı site → Öğretim Elemanı İstatistikleri → Öğretim Elemanı Sayıları → *Üniversite Bazında Öğretim Elemanı Sayıları*, 2025-2026 | 94 KB | 224 satır × 22 sütun (206 üniversite). Başlıklar: Üniversite Adı · Üniversite Türü · İl Adı · Profesör · Doçent · Doktor Öğretim Üyesi · Öğretim Görevlisi · Araştırma Görevlisi · Genel Toplam (her biri 3 alt sütun) |
Biçim: JasperReports üretimi gerçek BIFF8 `.xls` (pandas `read_excel` ile açılıyor; `xlrd` gerekiyor).
Başlık iki satıra yayıldığı ve her ölçü 3 birleştirilmiş alt sütuna bölündüğü için ayrıştırıcı
**satır 0–2'yi atlayıp** sütunları elle eşlemeli. Bu, `06-uni-veri.md` §4'teki 1. ve 2. alanların
(öğrenci sayısı, öğretim elemanı sayısı ve öğrenci/öğretim üyesi oranı) ön koşuluydu — kalktı.
## 5. URAP izin e-postası — taslak hazır, gönderilmedi
Adres **info@urapcenter.org** (urapcenter.org iletişim sayfası). Taslak:
`docs/ekip-raporlari/2026-09-22/urap-izin-eposta-taslagi.md`. Ajan senin adına e-posta göndermez;
metni olduğu gibi kopyalayıp gönderebilirsin.
## 6. Sende kalanlar
- **Yandex:** 1–2 hafta sonra sitemap işlendi mi ve "Site tanılama"da uyarı var mı bak.
- **URAP:** taslağı gönder.
- **Rybbit:** kendi telefonun/test cihazların için IP dışında bir dışlama yöntemi kararı
(mobil hücresel IP'ler filtreye takılmıyor).

View File

@@ -0,0 +1,214 @@
# 02 — Sevk yolları: ziyaretçiyi yapay zekâ listesine götüren yol haritası ve eleştirisi
Hazırlayan: Tasarımcı · 22 Eyl 2026 gündüz · Yöntem: **koddan denetim** (tarayıcı açılmadı, ekran ölçülmedi).
Sayısal kaynak: `docs/ekip-raporlari/2026-09-21/03-donusum.md` (Rybbit, 30g, iç trafik hariç).
Piksel/ekran tahminleri "koddan çıkarım" olarak işaretlendi; doğrulaması Bilal'de.
## Sade özet (5 satır)
1. **"Yapay zekâ" kelimesi, ziyaretçinin ilk gördüğü ekranların hiçbirinde geçmiyor.** Organik trafiğin indiği katalog sayfalarında funnel'ın tamamı (`cta-sira-form.tsx` kompakt satır → çekmece → sihirbaz) ürünü "Programları gör" / "Ücretsiz tablonu gör" diye satıyor; 24'lük yapay zekâ listesinden ilk kez `/sonuc`'un ~3. ekranında söz ediliyor. Ziyaretçi kapılardan geçerken ardında ne olduğunu **bilmiyor**.
2. **En büyük sıra kaynağı hiçbir yere gitmiyor.** `sira_girildi{kaynak:kapi}` 30 günde 14 olayla en büyük kaynak (03-donusum §3); bu yol (`+` toast'ı → profil kapısı) sihirbazın 3 adımını da doldurtuyor, sonra `profilTamamlandi` `null` döndürüyor (`use-tercih-profili.ts:346`) ve kullanıcı "Tercihlerin kaydedildi." toast'ıyla kataloğda kalıyor. **Liste için gereken her şey toplandı, liste teklif edilmedi.**
3. **Ürünün tek gerçek değer önizlemesi ölü bölgede.** `TadimlikSatiri` (gerçek LLM gerekçesi + risk + trend) yalnızca `/sonuc`'ta, 60 satırlık tablonun altında render ediliyor (`sonuc/page.tsx:117`); `tadimlik_goruntulendi` 30 günde **0**. Ana sayfada, katalogda, rehberde listenin çıktısı hiç gösterilmiyor — 3 kutu metin ve bir karşılaştırma tablosu var.
4. **`/sonuc` ödül sayfası olarak kurulmamış.** Sihirbazı bitiren kullanıcının gördüğü ilk şey, hiç kullanmadığı manuel listenin **boş gri placeholder'ı** (`manuel-harita.tsx:71-79`); yapay zekâ paneli ~3–4 ekran aşağıda (koddan çıkarım). Ölçüm bunu doğruluyor: panel 17 anonimin 6'sına göründü, 0 tık.
5. **Kapı sayısı fazla değil, kapıların sırası ve sessizliği sorun.** Girişsiz kullanıcı için listeye giden en kısa yol 4 kapı / 7 ekran / ~9 tık; kapılardan ikisi (sihirbaz, giriş) meşru, ama ikisi de **ne kazandıracağı söylenmeden** açılıyor.
---
## 1. Yol envanteri — listeye ulaşan her yol
Ortak kısaltma: **S** = sihirbaz (3 adım: alan → il → devlet/vakıf, `sihirbaz-adimlar.tsx:276, 296, 434`).
Kapılar: **K1** sıra girme · **K2** sihirbaz · **K3** Google girişi · **K4** kredi (üretim 3 kredi, yeni hesapta 5 deneme kredisi).
### Yol A — Ana sayfa (30g: 67 oturum → 11 sıra, %16,4; en iyi dönüşen yol)
| # | Ekran | Ne yapılıyor | Dosya |
|---|---|---|---|
| 1 | `/` hero | puan türü çipi + sıralama + "Yapay Zeka listemi kur" | `app/page.tsx:244` → `hero-form.tsx:188-196` |
| 2–4 | Dialog (S) | 3 adım, son buton girişsizde **"Ücretsiz tablonu gör"** | `hero-form.tsx:209-228`, etiket `:222` |
| 5 | `/sonuc?hazir=1` | harita placeholder → tablo → tadımlık → hazır panel | `hero-form.tsx:104`, `sonuc/page.tsx:102-126` |
| 6 | `/giris?callback=/listem?uret=1` | Google | `sihirbaz-cagri-karti.tsx:245` |
| 7 | `/listem?uret=1` | üretim (~20 sn tipik, 60 sn sunucu sınırı) | `liste-uretici.tsx:42-45` |
**7 ekran · ~9 tık · 4 kapı.** Girişli kullanıcıda 5. ekran boşa gider: `/sonuc` tam tabloyu render eder, sonra `router.replace("/listem?uret=1")` ile sekilir (`sihirbaz-cagri-karti.tsx:209-219`).
### Yol B — `/universite/[slug]` ve `/bolum/[slug]` üst kompakt satır (30g: 464 oturum → 12 sıra, %2,6)
1. Kompakt satır: başlık + özet paragrafının altında, tablo/istatistik ızgarasının üstünde (`universite-icerik.tsx:180, 290, 352`; `bolum-icerik.tsx:267`). CTA: **"Programları gör"** (`cta-sira-form.tsx:254`).
2. Gönderince çekmece **doğrudan sihirbaz adımıyla** açılır (`cta-sira-form.tsx:145-148`); kompakt varyantta çekmecenin tanıtım/kanıt ekranı (`SectionEyebrow "Saniyede gör"` + "24 tercihlik plan / Risk analizi / YÖK Atlas verisi" üçlüsü) **hiç render edilmez** — koşul `!kompakt && adim === "sira"` (`:296`).
3. S 3 adım → "Ücretsiz tablonu gör" (`:334`) → `/sonuc?hazir=1` (`:172`) → Yol A'nın 5–7. adımları.
**8 ekran · ~9 tık · 4 kapı.** Bu yolda ziyaretçi "yapay zekâ", "24 tercih", "risk analizi" ifadelerinin **hiçbirini** görmez (grep: `src/features/katalog/components/*.tsx` + kompakt dal → 0 eşleşme).
### Yol C — Katalog alt kartı (tablonun ve sayfalamanın altı)
`universite-icerik.tsx:381`, `bolum-icerik.tsx:297`. Kart varyantı: başlık + `KATALOG_CTA_ACIKLAMA` (`sayfalama.tsx:40`) + "Sıralamanı gir, programları gör" → çekmecenin **sıra adımı** açılır (kanıt üçlüsü burada görünür) → S → `/sonuc`. **9 ekran**, üstteki satırdan 1 tık fazla. 30g'de 20 satır/dilim × 3 dilim tablonun altında; mobilde ~1.500 px aşağıda (koddan çıkarım).
### Yol D — `+` (tabloya program ekleme) kapısı — **30g'deki en büyük sıra kaynağı: 14 olay**
1. Tablodaki `+` (`program-ekle-butonu.tsx:105`, `size-11` — dokunma hedefi doğru).
2. Profilsiz eklemede toast: "Seçtiklerine eklendi · Sıralamanı girersen bu programın risk seviyesini de gösteririz." + aksiyon "Sıralamamı gir" (`:69-83`).
3. Aksiyon `profilToplamaAc(null, true, "arti_toast")` → kapı **sıra adımıyla** açılır → S 3 adım.
4. **`hedef = null` → `profilTamamlandi` `null` döndürür → yönlendirme yok** (`use-tercih-profili.ts:327-346`). Kullanıcı "Tercihlerin kaydedildi." toast'ıyla (`tercih-profili-kapisi.tsx:238`) kataloğa geri düşer.
**Sonuç: 4 ekran, 2 kapı geçildi, liste teklif edilmedi.** Aynı ölü uç manuel liste çekmecesindeki "Sıralamamı gir" butonunda da var (`liste-cekmecesi.tsx:296-298`, aynı çağrı).
### Yol E — Navbar "Sıralama gir" (mobilde kalıcı, sticky 2. satır)
`katalog-arama.tsx:366` (mobil) / `:302` (lg+) → `sonucaGitIste({dogrudanSira:true})` → kapı (tanıtım adımı atlanır, doğru) → S → `hedef="sonuc"` → `sonucHref()` **parametresiz**. `/sonuc`'ta `hazir=1` olmadığı için hazır panel yerine genel panel ("24 tercihi tek tek elemek yerine, yapay zekâ kursun", `sihirbaz-cagri-karti.tsx:312-336`) çıkar — o da sayfanın en altında. **6 ekran · 3 kapı.**
### Yol F — Arama modalındaki funnel kartı
`arama-funnel-karti.tsx:132-139` → "Yapay Zeka listemi kur" → `profilToplamaAc("sihirbaz")` → kapı → S → `/sonuc?hazir=1` (girişsiz) / `?sihirbaz=1` (girişli). **Niyeti doğru taşıyan tek kısayol** — ama arama modalının arkasında, mobilde `size-9` ikon butonla açılıyor (`katalog-arama.tsx:379-386`).
### Yol G — Rehber (30g: 73 oturum → 5 sıra; %86 tek sayfa)
`rehber-makale.tsx:115` — CTA kartı **makalenin tamamının altında** (`mt-12`), `rehber/page.tsx:45` liste sayfasının altında. Yazı içinde funnel girişi yok.
### Yol H — `/listem` doğrudan (boş durum)
`/listem` giriş duvarlı (`listem-icerik.tsx:43` `verifySession`). Girişli + raporsuz kullanıcı: `Sparkles` + "Henüz Yapay Zeka listen yok" + profil yoksa CTA **ana sayfaya** atar (`listem-bos-cta.tsx:30`, `href="/"`) → kullanıcı Yol A'nın 1. adımına döner. Profil varsa doğrudan `?uret=1` — bu dal doğru.
### Yol I — `/universite/*/sayfa/N` (30g: 56 oturum → **0** sıra)
Üst satır burada da var (`universite-icerik.tsx:352`), ama sayfa metni "tablonun N. sayfası" bağlam cümlesi; listeye dair hiçbir vaat yok.
---
## 2. Her kapının hesabı
| Kapı | Şu anda gerekli mi? | Ardında ne olduğu ekranda söyleniyor mu? | Karar |
|---|---|---|---|
| **K1 · Sıra girme** | Evet — tablo da, havuz da sıralamayla hesaplanıyor (`liste-queries.ts`). Doğru kapı, doğru yerde. | Kısmen. Kompakt satır "Sıralaman {X} tabanlarının neresinde? Ücretsiz, üyelik gerekmez." diyor (`cta-sira-form.tsx:354-362`) — **tabloyu** vaat ediyor, listeyi değil. | Kalsın, **vaadi büyüt**. |
| **K2 · Sihirbaz (3 adım)** | Evet — havuzu kuran girdi (bkz. `/meraklisina` şeması, `huni-semasi.tsx:16-19`). Adım başına kayıp 1–3 kişi; sihirbazın kendisi sağlıklı. | **Hayır.** Girişsizde son buton "Ücretsiz tablonu gör" (`cta-sira-form.tsx:334`, `hero-form.tsx:222`). Kullanıcı 3 adım doldurup "tablo" vaat ediliyor; yapay zekâ listesinden söz eden tek yer girişlilere gösterilen "(3 kredi)" etiketi. | Kalsın, **etiket vaadi söylesin**. |
| **K3 · Google girişi** | Evet (liste kullanıcıya bağlı, kredi sayacı hesapta). 6/6 deneme başarılı — mekanizma sorunu yok. | Evet, iyi: `/giris` funnel dalında "Seçimlerin hazır — giriş yap, 5 deneme kredinle listen hemen üretilsin" (`giris-karti.tsx:52-58`). Kapının **kendisi** iyi; sorun oraya davet eden panelin görünmemesi. | Kalsın. |
| **K4 · Kredi (3/5)** | Evet ve zararsız: yeni hesapta 5 kredi var, ilk liste ücretsiz. | Kısmen — "5 deneme kredin hazır" yalnızca `/sonuc` panelinde ve `/giris`'te. Katalog yolunda hiç geçmiyor. | Kalsın. |
| **K0 · Profil kapısının tanıtım adımı** | **Hayır.** `+` dışındaki tüm girişler `dogrudanSira` ile bu adımı zaten atlıyor. Kalan dalda ekran şu: "Tercihine ışık tutabilmemiz için önce ne istediğini öğrenelim" + 4 satır paragraf + Vazgeç / Tercihlerimi belirle (`tercih-profili-kapisi.tsx:297-338`). Hiçbir girdi toplamıyor. | — | **Kaldırılabilir** (bkz. Öneri 1 notu). |
**Özet:** Gereksiz kapı yok; **gerekçesiz kapı** var. Kullanıcı K1 ve K2'yi "tablo görmek için" geçiyor, K3'e geldiğinde ilk kez yapay zekâ listesini duyuyor — ve o an sayfanın 3. ekranında.
---
## 3. Katalog köprüsü — 992a01a sonrası hâl yeterli mi?
**Yetersiz, üç sebeple.**
1. **Konum.** Satır, h1'in değil, 8–9 satırlık SEO özet paragrafının altında (`universite-icerik.tsx:287-290`). 375 px'te üst uç ≈ 570 px, gönder butonu ≈ 840 px (koddan çıkarım: sticky başlık ~96 px + breadcrumb ~36 + logo/h1 bloğu ~144 + paragraf 8×28 ≈ 224 + `mt-6`). Yani **buton ikinci ekranda**. `/bolum` tarafında paragraf kısa (2 satır), satır ilk ekranda (`bolum-icerik.tsx:265-268`) — iki sayfa aynı davranmıyor.
2. **"Kompakt" yalnızca `lg`'de kompakt.** `flex-col gap-3 lg:flex-row` (`cta-sira-form.tsx:195`) ve input/buton `flex-col sm:flex-row` (`:227`). 375 px'te: 5 puan türü çipi 2 satıra sarar (~66 px) + input 48 + buton 48 + başlık 2–3 satır → **~270 px**, yani mobilde tek satır değil, bir blok. Mobilin %74'ü tek sayfada çıkıyor; bu blok tek ekrana sığmıyor.
3. **Vaat eksik.** Kompakt dal kanıt üçlüsünü ve "Saniyede gör" eyebrow'unu render etmiyor (`:296` koşulu). Ziyaretçiye "tabloda nerede olduğunu göster" deniyor; ürünün kendisi (24'lük liste) anlatılmıyor. `docs/tasarim/cta-cekmece-tasarimi.md` §1'deki "kart vaat eder → çekmece tahsil eder" algısı kompakt varyantta **vaat kısmı düşerek** uygulanmış.
---
## 4. `/sonuc` ve `/listem` — sihirbazı bitiren ne görüyor?
**`/sonuc` sırası (`sonuc/page.tsx:102-126`):** ManuelHarita → SonucProgramTablosu → TadimlikBolumu → SonucSihirbazi → dipnot.
- **İlk ekran boş bir kutu.** Manuel liste boşken (yeni gelen herkeste boş) `aspect-[1050/447]` gri alan + "Tablodan + ile ekledikçe üniversiteler haritada belirir." (`manuel-harita.tsx:71-79`). 375 px'te ~143 px. Ödül sayfasının en üstünde, kullanıcının hiç kullanmadığı bir özelliğin boş durumu duruyor.
- **Tablo uzun.** Dilim başına 20 satır (`liste-queries.ts:43`), satır ~64 px → ~1.280 px (koddan çıkarım).
- **Tadımlık ~1.500 px'te**, yapay zekâ paneli **~2.200 px'te** (≈ 3,5 ekran). Ölçümle tutarlı: panel 17 anonimin 6'sına göründü, `tadimlik_goruntulendi` = 0.
- **"Kaç saniyede geliyor" hiçbir yerde yazmıyor.** Süre bilgisi yalnızca üretim başladıktan sonra, `/listem`'de görünüyor: "Bu işlem yarım dakika kadar sürebilir, sayfayı kapatma." (`liste-uretici.tsx:271`). Karar anında (panel, sihirbaz son butonu) süre vaadi yok.
- **Panel metni uzun.** 3 cümlelik tek paragraf + parantez içi kredi açıklaması (`sihirbaz-cagri-karti.tsx:286-291`); 375 px'te ~8 satır.
**`/listem` boş ekranı bir ilk kullanıcıya:** giriş duvarının arkasında olduğu için ilk kullanıcı buraya ancak giriş yaptıktan sonra düşer. Gördüğü: `Sparkles` + "Henüz Yapay Zeka listen yok" + tek paragraf + tek buton. Profil yoksa buton **ana sayfaya** atıyor (`listem-bos-cta.tsx:30`) — kullanıcı sıfır noktasına döner. Ekranda ne alacağını gösteren hiçbir görsel yok (örnek satır, iskelet, ekran görüntüsü).
---
## 5. Değer önizlemesi — üretmeden önce ne gösteriliyor?
| Yüzey | Önizleme var mı? |
|---|---|
| Ana sayfa | **Yok.** Bölümler: Sorun / Nasıl çalışır (3 metin kartı) / Karşılaştırma tablosu / Fiyat / SSS / final CTA (`app/page.tsx:267-660`). Listenin çıktısından tek bir satır bile gösterilmiyor. |
| Katalog (`/bolum`, `/universite`) | **Yok.** |
| Rehber | **Yok.** |
| `/meraklisina` | Kurallar + mermaid şeması + kendi sıralamasına göre güncellenen sayılar (`meraklisina-demo.tsx:105-130`) — süreç anlatımı, çıktı değil. |
| `/sonuc` | **Var ama görülmüyor:** `TadimlikSatiri` gerçek rapor formatında tek satır (gerekçe + risk rozeti + trend, `tadimlik-satiri.tsx:113-191`). `tadimlik_goruntulendi` 30g = **0**. |
**Önemli teknik imkân:** `tadimlikSec(sira, tur, kategoriSlug?, tip?)` (`lib/tadimlik-havuzu.ts:107`) kovaya göre çalışıyor ve her kovanın `temsiliSira` değeri sabit (`:24-32`). Yani **ziyaretçinin sıralamasını bilmeden de** ("örnek bir aday için" etiketiyle) gerçek bir tadımlık satırı render edilebilir; havuz canlıda dolu (522 satır). Yeni içerik üretimi, yeni LLM çağrısı, yeni bileşen gerekmiyor — mevcut `TadimlikSatiri` başka yüzeylere taşınabilir.
---
## 6. Tasarım önerileri (6)
> Ortak kural: hiçbir öneri yeni rozet/pill/çarpı/buton varyantı icat etmez. Rozet gerekirse `SectionEyebrow` (`pixel-decor.tsx`), CTA'da metin önce + sonda `<ArrowRight className="size-4" aria-hidden />`, çekmece/modal kapatma çarpısı `dialog.tsx` kanonik seti. `/meraklisina` şeması (`huni-semasi.tsx:16-30`) sihirbaz adım sayısını/sırasını ve havuz kurallarını belgeler; aşağıdaki önerilerin **hiçbiri** adım sayısını, sırasını, havuz kurallarını veya 24'lük dağılımı değiştirmiyor → şema senkronu gerekmiyor (Öneri 1'de yalnızca sihirbaz **sonrası** yönlendirme değişiyor, şemada o yok).
### Ö1 — Kapı azaltma: sihirbazı bitiren herkes listeye çıksın (ölü uçları kapat)
**(a) Ne değişiyor:** `+` toast'ındaki "Sıralamamı gir" (`program-ekle-butonu.tsx:82`) ve liste çekmecesindeki eşi (`liste-cekmecesi.tsx:298`) `profilToplamaAc(null, …)` yerine `profilToplamaAc("sihirbaz", …)` çağırsın; navbar girişi (`katalog-arama.tsx:115`, `sonucaGitIste` → `hedef:"sonuc"`) de `"sihirbaz"` hedefine geçsin. Ayrıca `profilTamamlandi`'nin `hedef == null` dalı (`use-tercih-profili.ts:346`) `sonucHref({ hazir: "1" })` döndürsün — sihirbazı bitirmiş hiç kimse "kaydedildi" toast'ıyla yerinde bırakılmasın. `tercih-profili-kapisi.tsx:238`'deki başarı toast'ı bu dalda gereksizleşir (akış devam ediyor, bitmiyor).
**(b) Neden:** 30g'de en büyük sıra kaynağı `kapi` (14 olay) ve `duzenle` (5) bu ölü uçta bitiyor; ikisi birlikte tüm sıra girişlerinin ~%55'i. Kullanıcı K1 ve K2'yi geçmiş, tek eksik ona listeyi teklif etmek. Bu, **liste yolunu 3 ekran kısaltır** (kataloğa dönüp tekrar funnel'a girmek yerine doğrudan ödül ekranı).
**(c) Büyüklük:** S (davranış; `src/` içinde 4–5 satır).
**(d) Kural uyumu:** görsel değişiklik yok; şema etkilenmez. Ölçüm: `sira_girildi{kaynak:kapi}` → `sonuc_goruntulendi` zinciri ilk kez kurulur.
*Not (ayrı, opsiyonel):* profil kapısının tanıtım adımı (`tercih-profili-kapisi.tsx:297-338`) hiçbir girdi toplamıyor ve `dogrudanSira` ile zaten çoğu yolda atlanıyor. `ilkAdim`'ı her zaman `"sira"` yapmak bir ekran daha siler. **S.**
### Ö2 — Mobil tek ekran: katalog üst satırı başlığın altına, gerçekten tek satıra
**(a) Ne değişiyor:** `/universite/[slug]`'da `ustSiraSatiri` SEO özet paragrafının **üstüne**, `h1`'in hemen altına alınsın (`universite-icerik.tsx:287-290` → `:285` öncesi; `/bolum` zaten böyle). Kompakt varyantın mobil düzeni: (i) puan türü çipleri varsayılan "Sayısal" seçili tek satırda yatay kaydırmalı şeride (`flex-nowrap overflow-x-auto` + `-mx-4 px-4`) alınsın ya da başlangıçta gizlenip "Puan türü: Sayısal · değiştir" satırıyla açılsın; (ii) input + buton mobilde de yan yana (`flex-row`, buton `shrink-0`, yalnız ikon değil kısa metin: "Gör"→**hayır**, metin "Programları gör" kalsın, gerekirse buton alt satırda tam genişlik kalsın ama çipler tek satıra insin). Hedef: bloğun toplam yüksekliği ~270 px'ten ~150 px'e insin ve üst uç ~380 px'e çıksın → **375×667'de input + buton ilk ekranda**.
**(b) Neden:** Katalog 464 oturum → 12 sıra (%2,6); mobil bounce %74. 992a01a satırı yukarı taşıdı ama `/universite`'de paragrafın altında ve mobilde tek satır değil (bkz. §3).
**(c) Büyüklük:** M.
**(d) Kural uyumu:** mevcut çip class seti (hero formuyla birebir) korunur; CTA deseni değişmez; yeni pill yok. Yatay kaydırmalı şeride geçilirse kaydırma göstergesi metinle desteklenmeli, çipler `role="radio"` kalmalı.
### Ö3 — Değer önizlemesi kapıdan önce: tadımlık satırını kataloğa ve ana sayfaya taşı
**(a) Ne değişiyor:** Mevcut `TadimlikSatiri` bileşeni (yeni bileşen değil) iki yeni yerde render edilsin:
· **Katalog:** üst sıra satırının hemen altında, `SectionEyebrow`'u "Yapay zekâdan örnek satır" olarak, üstünde tek cümle: "Sıralamanı girince listendeki 24 satır böyle görünür." Sıra bilinmiyorsa `kovaBul().temsiliSira` ile "örnek bir aday için" etiketli hâli (`tadimlik-havuzu.ts:24-32, 107`); bölüm sayfasında bölümün kategorisi `kategoriSlug` olarak verilebilir.
· **Ana sayfa:** "Nasıl çalışır?" bölümünün 3 kartının altına, `steps` metinlerinin karşılığı olarak tek gerçek satır (`app/page.tsx:340-358` sonrası).
Çekmecenin sıra adımındaki kanıt üçlüsü kompakt dalda da gösterilsin (`cta-sira-form.tsx:296` koşulunun kompakt dalı).
**(b) Neden:** Ürünün çıktısı hiçbir yerde üretilmeden önce gösterilmiyor (§5); tek örnek `/sonuc`'un dibinde ve 30 günde 0 kez görüldü. "Bu kapının ardında ne var?" sorusunun cevabı budur.
**(c) Büyüklük:** M (yerleştirme + sırasız/kova varyantı; içerik hattı hazır).
**(d) Kural uyumu:** `SectionEyebrow` kanonik rozet; risk rozeti zaten metin etiketli (`RISK_ETIKET`, `lib/risk.ts:9`) — renk tek başına anlam taşımıyor. Tadımlık CTA'sı mevcut ok desenini kullanıyor (`tadimlik-satiri.tsx:186-188`).
### Ö4 — `/sonuc`'u ödül sayfası yap: sıralamayı tersine çevir
**(a) Ne değişiyor:** `sonuc/page.tsx:102-126` sırası şu olsun: **(1)** kısa ödül başlığı + yapay zekâ paneli (hazır panel / genel panel) → **(2)** tadımlık (girişsizde) → **(3)** program tablosu → **(4)** manuel harita, ve harita **boşken hiç render edilmesin** (`manuel-harita.tsx:69-80` boş dalı `null` dönsün; CLS riski yok çünkü tablonun üstünde değil altında). Panel metni 3 cümleden 1 cümleye insin: başlık "Seçimlerin hazır — listen bir adım uzakta", gövde "Google ile 5 saniyede giriş yap; 5 deneme kredinle 24 tercihlik listen ~30 saniyede kurulur." (süre ilk kez karar anında söylenir, kaynak `liste-uretici.tsx:42-44`).
**(b) Neden:** Anonim kullanıcı `/sonuc`'ta medyan 33 sn kalıyor ve panele inmiyor; panel 6/17 gösterim, 0 tık. Ödül sayfasının ilk ekranı şu an kullanılmamış bir özelliğin boş durumu.
**(c) Büyüklük:** M.
**(d) Kural uyumu:** panel bileşeni ve CTA deseni aynen kalır; yalnız sıra ve metin değişir. "Ücretsiz tablo her zaman açık" güvencesi panelde tek cümleyle korunmalı (vaatsizlik).
### Ö5 — `/sonuc` mobil sabit alt çubuk (anonim + seçimleri hazır)
**(a) Ne değişiyor:** Yeni bileşen değil: `sihirbaz-cagri-karti.tsx`'in `girisBekliyor` dalına, yalnız `max-sm`'de görünen sticky bir satır. İçerik: "Listeni kaybetme — Google ile kaydet" + `<ArrowRight className="size-4" aria-hidden />`, hedef `girisUrl`, olay `giris_cta_tiklandi{kaynak:"sonuc_cubuk"}`. Teknik gereklilikler: `position: sticky; bottom: 0` (fixed değil — klavye açılınca zıplamasın), yükseklik ≥ 56 px, `pb-[max(0.75rem,env(safe-area-inset-bottom))]`, sayfa altına eşdeğer `scroll-padding`/boşluk ki dipnot çubuğun altında kalmasın, `prefers-reduced-motion`'da giriş animasyonu yok.
**(b) Neden:** Panel mobilde 3,5 ekran aşağıda; anonim mobil oturumların medyan kalış süresi 33 sn. Çubuk görünürlüğü %100'e çıkarır.
**(c) Büyüklük:** S–M.
**(d) Kural uyumu:** CTA deseni (metin önce, sonda ok) birebir; yeni renk/pill yok; layout'taki `pb-28` (`app/layout.tsx:95`) ile çakışma kontrol edilmeli.
### Ö6 — Dil birliği: kapının ardındaki ödülü her etikette söyle
**(a) Ne değişiyor:** Üç etiket:
· Sihirbaz son butonu, girişsiz: "Ücretsiz tablonu gör" → **"Listeme geç — ücretsiz tablon + yapay zekâ listen"** ya da kısa hâli **"Devam et — listeni gör"** (`cta-sira-form.tsx:334`, `hero-form.tsx:222`, `sihirbaz-cagri-karti.tsx:348`).
· Kompakt satır başlığı: "Sıralaman {X} tabanlarının neresinde?" + **"Ücretsiz, üyelik gerekmez"** cümlesine ikinci cümle: "Sıralamanı girince yapay zekâ 24 tercihlik listeni de kurabilir." (`cta-sira-form.tsx:354-362`).
· `/listem` boş durumda profil yokken CTA ana sayfaya atmasın; aynı sayfada profil kapısını açsın (`profilToplamaAc("sihirbaz")`) — `listem-bos-cta.tsx:30`.
**(b) Neden:** Kullanıcı "tablo" vaadiyle 3 kapı geçiyor, ürünü `/sonuc`'un dibinde öğreniyor (§2). Boş `/listem` CTA'sı kullanıcıyı huninin başına geri atıyor.
**(c) Büyüklük:** S.
**(d) Kural uyumu:** yalnız metin + bir `href`; CTA ok deseni korunur. Yeni metinler vaat içermez ("kurabilir", "gör" — "yerleşirsin" değil).
---
## 7. Yan bulgular — tek kaynak / erişilebilirlik ihlalleri (öneri dışı, ucuz)
| Dosya:satır | Kural / sorun | Kullanıcıya etkisi | Düzeltme | Büyüklük |
|---|---|---|---|---|
| `sihirbaz-cagri-karti.tsx:269` | AGENTS.md CTA deseni: `<Link href="/listem">Listeni gör</Link>` — sondaki `ArrowRight` **yok** | Raporu olan kullanıcının gördüğü tek CTA sitedeki diğerlerinden farklı duruyor | `Listeni gör<ArrowRight className="size-4" aria-hidden />` | S |
| `sira-gerekli.tsx:61-62` | CTA deseni: `Trophy` ikonu **metnin başında** ("başta ikon yok") | Aynı eylem iki farklı biçimde | İkonu kaldır, sonda `ArrowRight` | S |
| `liste-uretici.tsx:220-221` | CTA deseni: `RefreshCcw` metnin başında ("Tekrar dene") | Hata ekranındaki tek buton desen dışı | İkon sona ya da kaldırılsın | S |
| `liste-cekmecesi.tsx:297, 307` | `<ArrowRight data-icon="inline-end" />` — `aria-hidden` yok, kanonik `className="size-4" aria-hidden` değil (`listem-govde.tsx:290,371` aynı yazım ama `aria-hidden`'lı) | Aynı ok üç farklı yazımda | Tek yazıma indir | S |
| `tercih-profili-kapisi.tsx:393-398` | Aynı eleman iki stilde: puan türü burada `Select`, hero/CTA formunda `role="radiogroup"` çipler (`hero-form.tsx:143-164`, `cta-sira-form.tsx:199-220`) | Kullanıcı aynı soruyu iki farklı arayüzle cevaplıyor | Çip radiogroup'a birle (tek kaynak) | M |
| `katalog-arama.tsx:343, 366, 379` | Mobilde funnel'ın kalıcı girişi `h-9` / `size-9` = **36 px** dokunma hedefi (< 44 px) | Trafiğin %90'ı mobil; ana funnel girişi ve arama küçük | `h-11`/`size-11`'e çıkar (ya da dokunma alanını `::before` ile büyüt) | S |
| `arama-funnel-karti.tsx:28, 42` | Vaat/korku dili: "Doğru strateji, doğru yerleşme.", "Boş kalan tercih, kaçan fırsattır." — ürünün "yerleşme garantisi vermiyoruz" duruşuyla (`app/page.tsx:393`) çelişiyor | Güven mesajını zayıflatıyor | İki satırı çıkar ya da yeniden yaz | S |
| `arama-funnel-karti.tsx:105, 125` | Palet dışı yüzey: `bg-[#0b1f3a]` + `text-cyan-300`; sitenin funnel yüzeyi `bg-primary` + `PixelField` (`sihirbaz-cagri-karti.tsx:275`, `liste-cekmecesi.tsx:269`) | Aynı işlevli panel iki ayrı marka dilinde | **[BİLAL]** — renk paleti kararı | S |
| `arama-funnel-karti.tsx:63` vs `cta-sira-form.tsx:49` | Aynı kanıt üçlüsü iki farklı etiketle ("24 tercih" / "24 tercihlik plan") ve iki renkte | Küçük ama ölçülebilir tutarsızlık | Tek sabit hâline getir | S |
---
## 8. Bilal'in gözle kontrol etmesi gereken ekranlar (375 px, mobil)
1. `/universite/<uzun-adli-bir-üniversite>` — kompakt sıra satırının üst ucu ilk ekranda mı, gönder butonu görünüyor mu; çipler kaç satıra sarıyor.
2. `/bolum/hemsirelik` — aynı satır (burada paragraf kısa; iki sayfa arasındaki fark ne kadar büyük).
3. `/sonuc` (sıralama girmiş, girişsiz) — ilk ekranda boş gri harita kutusu görünüyor mu; yapay zekâ paneline kaç kaydırma gerekiyor; tadımlık görünüyor mu.
4. Katalog tablosunda `+` → toast → "Sıralamamı gir" → sihirbazı sonuna kadar doldur — **ekran nerede kalıyor** (Ö1'in kanıtı).
5. Navbar'daki "Sıralama gir" pill'i — parmakla ilk denemede isabet ediyor mu (36 px).
6. `/listem` (girişli, listesiz) — boş ekran ve CTA'nın gittiği yer.
## 9. Bilal'den istenen (en fazla 3)
1. Yukarıdaki 6 ekranı telefonda sırayla aç, 3 ve 4 numaralıların ekran görüntüsünü ekibe bırak — **10 dk**.
2. Ö1'i (sihirbazı bitiren herkes `/sonuc`'a çıksın) onayla ya da reddet; en büyük sıra kaynağını huniye bağlayan tek değişiklik bu — **2 dk**.
3. Arama funnel kartının koyu lacivert/cyan yüzeyi kalsın mı, `bg-primary` funnel diline mi dönsün — marka kararı — **2 dk**.

View File

@@ -0,0 +1,299 @@
# 03 — Vaat envanteri ve ilk-5-saniye teşhisi
> Rol: Marka/pazarlama stratejisti · 22 Eylül 2026 (gündüz, Bilal başında) · Okuyucu: CEO (karar), CTO/ürün yöneticisi (iş tanımı)
> Yöntem: yalnızca okuma — `src/`, `content/`, `docs/`, `data/app.db` (salt sorgu) + 3 web araması/2 sayfa açıldı. Kod ve içerik **değiştirilmedi**.
> İşaretler: **[K]** koddan doğrulandı · **[W]** web sayfası açılıp okundu · **[A]** yalnızca arama özeti · **[V]** varsayım · **doğrulanmalı**
---
## Özet (5 madde)
1. **Ziyaretçi ürünün ana çıktısını ilk 5 saniyede öğrenmiyor — çünkü fold'da tek kelimeyle anlatılmıyor.** Ana sayfanın H1'i bir *sorun* cümlesi ("Dört yıllık geleceğini 48 saatlik panikle seçme", `src/features/pazarlama/components/hero-baslik.tsx:24-28`) ve **altında alt başlık yok**: `src/app/page.tsx:239` → `240` arası doğrudan sıralama formuna giriyor. Çıktının ne olduğu (24 program, hayal/dengeli/güvenli, gerekçe, taban trendi) ilk kez **fold'un çok altında**, "Üç adımda listen hazır" bölümünde geçiyor (`src/app/page.tsx:105-117`). Vaadi tam ifade eden tek yüzey OG görseli (`src/app/opengraph-image.tsx:4-5,71,85`) — yani sayfayı *açmayan* kişi vaadi, açan kişi görmüyor. [K]
2. **Trafiğin geldiği yerde (katalog + rehber) vaat hiç geçmiyor.** 464 kişinin indiği bölüm/üniversite sayfalarındaki tek dönüşüm bileşeni `CtaSiraForm`; görünen metinleri "Sıralaman … tabanlarının neresinde?" + "Sıralamanı gir, programları gör" + "Ücretsiz, üyelik gerekmez" (`src/features/sihirbaz/components/cta-sira-form.tsx:356-362, 411-437`, `src/features/katalog/components/sayfalama.tsx:40-41`, `bolum-icerik.tsx:179`, `universite-icerik.tsx:174`). **"24"** ve **"yapay zekâ"** kelimeleri bu kartların görünen yüzünde hiç geçmiyor; "24 tercihlik plan" rozeti yalnızca çekmece açıldıktan sonra görünüyor (`cta-sira-form.tsx:48-51` → yalnız `:312-325`). 27 rehber yazısının hiçbirinde ürünün 24'lük listesi tanıtılmıyor (`content/rehber/` grep). [K]
3. **Sitenin en üstünde, her sayfada, ürünün bugün işe yaramadığını söyleyen bir bant var.** `src/components/site-top-banner.tsx:7-8,64` bugün (22 Eyl 2026) "2026 YKS tercih dönemi · 29 Temmuz – 10 Ağustos 2026 · **Tercih dönemi sona erdi**" basıyor; ek yerleştirme tercihleri de 21 Eyl 23.59'da kapandı (`content/rehber/ek-yerlestirme-2026.md:12`). Buna rağmen kapanış CTA'sı hâlâ "**Tercih dönemi bitmeden yerini al**" diyor (`hero-focus-button.tsx:44-46, 63-66`). Ziyaretçiye önce "geç kaldın", sonra "acele et" deniyor. Veri tarafı ise 2027 kohortuna hazır (`src/lib/veri-yillari.ts:11,21` → `SON_YIL=2026`, `TERCIH_YILI=2027`). **Bu tek çelişki, 621 → 3 hunisinin en ucuz ve en büyük açıklaması.** [K]
4. **"Yapay Zeka listesi" ifadesi bugünkü hâliyle bir çıktı değil, bir teknoloji adı.** Kullanıcıya görünen 11 CTA'da "Yapay Zeka listemi kur" yazıyor (`hero-form.tsx:194`, `sihirbaz-cagri-karti.tsx:333`, `arama-funnel-karti.tsx:137`, `listem-bos-cta.tsx:31`, `tercih-profili-kapisi.tsx:463` vb.) ama butonun yanında *listede ne olduğu* yazmıyor. Üstelik yazım tek kaynaktan gelmiyor: kodda 59 "Yapay Zeka", 24 "yapay zekâ", 2 "Yapay Zekâ", 1 "yapay zeka" — **tek bir sözlük/sabit yok**, terim değişikliği ~30 dosyada elle arama-değiştirme demek. [K]
5. **Güven cümlelerimiz var ama satış anında görünmüyor.** En güçlü farklılaştırıcımız — "yapay zekâ yalnızca sıralamanla açılan gerçek programlardan seçer, havuz dışına çıkamaz" — yalnızca SSS'de (`src/app/page.tsx:127`) ve `/meraklisina`'da (`huni-semasi.tsx:47,52`, `meraklisina-icerik.tsx:119-127`) yaşıyor; `/sonuc`'taki giriş panelinde, `/giris` kartında, `/paket`'te **hiç geçmiyor**. `/meraklisina`'ya site içinden yalnızca 2 giriş var (ana sayfa rozeti `page.tsx:321`, footer `site-footer.tsx:77`). Buna karşılık footer ürünü **"YKS Tercih Robotu 2026"** diye adlandırıyor (`site-footer.tsx:49`) — `docs/urun/vizyon.md:22`'nin açıkça reddettiği kategori. [K]
---
## 1. Vaat envanteri — birebir alıntılar, dosya:satır
### 1.1 İlk ekran (ana sayfa fold, mobil) — sırayla ne görülüyor
| # | Yüzey | Birebir metin | Çıktıyı anlatıyor mu? | Kaynak |
|---|---|---|---|---|
| 1 | Üst bant | "2026 YKS tercih dönemi · 29 Temmuz – 10 Ağustos 2026" + "**Tercih dönemi sona erdi**" | Hayır — tersini söylüyor | `src/components/site-top-banner.tsx:7-8,64` [K] |
| 2 | Navbar | Logo · katalog arama · "Giriş yap" | Hayır — üründen hiç söz etmiyor | `src/components/site-header.tsx:13-34`, `user-nav.tsx:35-40` [K] |
| 3 | H1 | "Dört yıllık geleceğini **48 saatlik panikle** seçme" | Hayır — sorun cümlesi | `hero-baslik.tsx:24-28` [K] |
| 4 | *(alt başlık)* | **YOK** | — | `src/app/page.tsx:239→240` [K] |
| 5 | Puan türü çipleri | "Sayısal / Eşit Ağırlık / Sözel / Dil / TYT" | Hayır | `hero-form.tsx:31-37,148-163` [K] |
| 6 | Input | "YKS başarı sıralaman (ör. 85.000)" | Hayır — karşılıksız istek | `hero-form.tsx:177` [K] |
| 7 | Buton | "**Yapay Zeka listemi kur**" | Kısmen — "liste" ne, belirsiz | `hero-form.tsx:194` [K] |
| 8 | Güven rozeti | "Veri: YÖK Atlas · son güncelleme 21 Eylül 2026" | Hayır (ama iyi bir sinyal) | `src/app/page.tsx:247-256`, `src/lib/seo.tsx:24` [K] |
**Cevap: Hayır.** İlk 5 saniyede ziyaretçi yalnızca "bir sıralama isteniyor" ve "bir şey kurulacak" bilgisini alıyor. "24 program", "hayal/dengeli/güvenli", "her satırda gerekçe", "2026 taban sıralaması" kelimelerinin hiçbiri fold'da yok.
### 1.2 Vaadin geçtiği tüm yerler (kullanıcıya görünen metinler)
| Yüzey | Birebir alıntı | Dosya:satır | Huni aşaması |
|---|---|---|---|
| Metadata/title | "KolayTercih — Yapay Zekâ Destekli YKS Tercih Danışmanı" | `src/app/layout.tsx:50,61` | SERP |
| Meta description | "YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmandan çok daha düşük fiyata, yapay zekâ destekli tercih danışmanlığı." | `layout.tsx:53-54,62-63` | SERP |
| OG görseli | "YKS tercihin, gerçek YÖK Atlas verisiyle" / "Sıralamanı gir · Dengeli 24 tercihlik listeni al" | `src/app/opengraph-image.tsx:4-5,71,85` | Paylaşım |
| Ana sayfa adım 3 | "Hayal, dengeli ve güvenli dilimlerine dağıtılmış, **her satırı gerekçeli** tercih listeni indir; aklına takılanı listen üzerinden yapay zekâya sor." | `src/app/page.tsx:112-115` | Fold altı |
| Ana sayfa SSS | "Yapay zekâ **yalnızca sıralamanla açılan gerçek programlardan seçer; bu havuzun dışına çıkamaz.**" | `src/app/page.tsx:127` | Fold altı (akordeon **kapalı**) |
| Ana sayfa dürüstlük notu | "**Yerleşme garantisi vermiyoruz — çünkü kimse veremez.**" | `src/app/page.tsx:383-392` | Fold altı |
| Ana sayfa paket listesi | "Sıralamana özel, gerekçeli 24 tercihlik dengeli liste" / "60 yapay zekâ danışman sorusu" | `src/app/page.tsx:190-203` | Fiyat bölümü |
| Kapanış CTA | "Sıralamanı gir, yapay zekâ danışmanın veriyle konuşsun. **Tercih dönemi bitmeden yerini al.**" | `hero-focus-button.tsx:63-66` | Sayfa sonu |
| Katalog CTA (üst, kompakt) | "Sıralaman \<Bölüm\> tabanlarının neresinde?" + "Ücretsiz, üyelik gerekmez." | `bolum-icerik.tsx:179,267`, `cta-sira-form.tsx:356-362` | **Ana giriş noktası — vaat yok** |
| Katalog CTA (alt) | "Bu tablodaki tabanlar geçmiş yerleştirmelerin sonucu; bu yıl değişebilir. Sıralamanı gir, tabanı sıralamana yakın programları risk seviyesine göre ayrılmış hâlde listeleyelim. Ücretsiz, üyelik gerekmez." | `sayfalama.tsx:40-41` | **Vaat yok** |
| Katalog/rehber CTA butonu | "Sıralamanı gir, programları gör" / "Programları gör" | `cta-sira-form.tsx:254,427` | **Vaat yok** |
| Sihirbaz son buton (girişsiz) | "**Ücretsiz tablonu gör**" | `hero-form.tsx:222`, `cta-sira-form.tsx:334` | Vaadin düştüğü an |
| Sihirbaz son buton (girişli) | "Yapay Zeka listemi kur (3 kredi)" | `hero-form.tsx:222`, `sihirbaz-cagri-karti.tsx:348` | — |
| `/sonuc` başlık | **H1 YOK** (harita + ham tablo ile açılıyor) | `src/app/sonuc/page.tsx:96-117`; `program-tablosu.tsx:176` yalnız `aria-label` | Vaat kopuyor |
| `/sonuc` tadımlık | "Yapay zekâ listendeki her satırı böyle anlatır" / "Bu, 24 satırlık Yapay Zeka listenden yalnızca bir örnek." / "24 satırın tamamı için giriş yap — 5 deneme kredin hazır" | `tadimlik-satiri.tsx:116-123,173,186` | **En iyi vaat yüzeyi — ama tablonun altında** |
| `/sonuc` sihirbaz kartı | "24 tercihi tek tek elemek yerine, yapay zekâ kursun" / "…yapay zekâ hayal, dengeli ve güvenli dilimlerine dağıtılmış 24 tercihi — her satırı yerleşme riski ve gerekçesiyle — senin yerine dizer." | `sihirbaz-cagri-karti.tsx:319-327` | Sayfa sonu |
| `/sonuc` hazır panel | "Seçimlerin hazır — Yapay Zeka listen bir adım uzakta" / "5 deneme kredinle Yapay Zeka listeni kur — giriş yap" / "Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede" | `sihirbaz-cagri-karti.tsx:284-309` | Giriş kapısı |
| `/giris` başlık | "Giriş yap**, çünkü listen seni bekliyor / …kaçırmak istemezsin**" (6 varyant, döngüsel yazıcı) | `giris-baslik.tsx:6-13` | Kapı |
| `/giris` alt metin | "Seçimlerin hazır — giriş yap, **5 deneme kredinle** listen hemen üretilsin." | `giris-karti.tsx:52-58` | Kapı |
| `/listem` boş durum | "Henüz Yapay Zeka listen yok" / "…24 tercihlik risk analizli listeni kur; sonra burada görüntüleyip Yapay Zeka danışmanla üzerinde konuşabilirsin." | `listem-icerik.tsx:59`, `listem-bos-cta.tsx:19-31` | Ürün içi |
| `/paket` | "Tek seferlik Tercih Dönemi Paketi: yapay zekâ destekli kişisel 24 tercihlik liste, risk analizi, liste revizyonları ve soru hakkı." / H1: "İnsan danışmanın işini, çok daha düşük fiyata" | `src/app/paket/page.tsx:12-13,44-51` | Satış |
| `/meraklisina` | "Sihir yok, kara kutu yok…" / "4. Sihirbaz süzer, yapay zekâ kurar" / "ona boş bir sayfa değil, bu havuz verilir" / "5. Dürüst olalım: bu bir tahmin aracıdır" | `src/app/meraklisina/page.tsx:25-33`, `meraklisina-icerik.tsx:105-127,138+` | **Güvenin tamamı burada, trafik yok** |
| Arama modalı kartı | 30 döngüsel cümle; ör. "Üç adımda sana özel 24 tercih." ama ayrıca "**Doğru strateji, doğru yerleşme.**", "Uzman işi bir liste" | `arama-funnel-karti.tsx:19-50,137` | Her sayfa |
| E-posta | "Listen seni bekliyor" / "Yapay zekânın senin sıralamana göre kurduğu tercih listesi hesabında" | `src/lib/eposta.ts:175-209` | Geri kazanım |
| Footer | "**YKS Tercih Robotu 2026**" (ürün linki) · "KolayTercih bir karar destek aracıdır, yerleşme garantisi vermez." | `site-footer.tsx:49,130,133` | Her sayfa |
### 1.3 Teşhis — "ziyaretçi bu listenin var olduğunu öğreniyor mu?"
**Hayır, üç kırılma noktasında öğrenemiyor:**
- **Giriş anında (katalog/rehber, 464/621 ziyaret):** Vaat sıfır. CTA yalnızca "programları gör" diyor — bu, ücretsiz rakiplerin (YÖK Atlas, Kariyer.net, Canlıkoç) zaten verdiği şey. Ziyaretçi burada KolayTercih'in bir *liste kurduğunu* öğrenmiyor.
- **Sihirbaz sonunda:** Ziyaretçi "Yapay Zeka listemi kur" diyen butona basıp 3 adım tamamlıyor; son butonda metin **"Ücretsiz tablonu gör"**e düşüyor (`hero-form.tsx:222`). Vaat, yerine getirilmeden önce sessizce küçülüyor.
- **`/sonuc`'ta:** Sayfanın H1'i yok; ziyaretçi ham tabloya düşüyor. Vaadi tekrar duyduğu yer, tablonun *altındaki* tadımlık (`tadimlik-satiri.tsx:116`). Analitik raporu bunu ölçmüş: 17 anonim oturumun yalnız 6'sı paneli gördü, **0 tık** (`docs/ekip-raporlari/2026-09-21/03-donusum.md` §Özet-3).
- Ek risk: tadımlık, havuzda satır yoksa **hiç çizilmiyor** (`tadimlik-bolumu.tsx:19-21`). Havuz bugün 522 satır (`data/app.db` sorgusu, `tadimlik_havuzu` — 6 kova × 5 tür × kategori × tip) [K]; kapsam dışı kombinasyonda ziyaretçi vaadi hiç görmüyor. **Kapsam ölçülmeli.**
---
## 2. Vaadin netliği — "yapay zekâ listesi" öğrenciye ne diyor?
**Bugünkü hâli soyut.** CTA'daki "Yapay Zeka listemi kur" üç soruyu cevapsız bırakıyor: *kaç satır? neye göre? veri nereden?* Çıktının somut hâli kodda var ve doğrulanabilir — ama CTA'nın yanında değil:
| Somut unsur | Kod kanıtı | CTA'nın yanında görünüyor mu? |
|---|---|---|
| 24 satır | `huni-semasi.tsx:26+`, `page.tsx:113` | Hayır |
| Hayal / Dengeli / **Güvenli** dilimleri (tek etiket kaynağı) | `src/lib/risk.ts:21-25` | Hayır |
| Her satırda gerekçe + risk notu + trend özeti | `src/lib/tadimlik-havuzu.ts:44-51`, `rapor-listesi.tsx:294-316` | Hayır |
| En güncel taban sıralaması (2026; o yıl veri yoksa 2025) | `src/lib/veri-yillari.ts:11,13,38` | Hayır |
| 6 yıllık taban serisi (2021–2026) | `veri-yillari.ts:9-11,29` | Hayır |
| Havuz kısıtı: uydurma program yok | `huni-semasi.tsx:47`, `page.tsx:127` | Hayır |
### Somutlaştıracak 3 alternatif söz (vaatsiz, doğrulanabilir — kullanıma hazır)
**A — Hero alt başlığı (yeni `<p>`; hedef: `src/app/page.tsx:239` ile `240` arası, `HeroBaslik` ile `#hero-form` arasına):**
> "Başarı sıralamanı gir; sana açık olan gerçek programlardan 24 satırlık bir tercih listesi kuralım — her satırda hayal/dengeli/güvenli etiketi, en güncel YÖK Atlas taban sıralaması ve o satırın neden orada olduğunun gerekçesi."
**B — Katalog/rehber CTA açıklaması (hedef: `src/features/katalog/components/sayfalama.tsx:40-41`, `KATALOG_CTA_ACIKLAMA`):**
> "Bu tablodaki tabanlar geçmiş yerleştirmelerin sonucu; bu yıl değişebilir. Sıralamanı gir: hangi programların sana açık olduğunu ücretsiz gör, istersen aynı verinin üzerine kurulan 24 satırlık gerekçeli tercih listeni de kur. Ücretsiz, üyelik gerekmez."
**C — CTA butonu metni (hedef: `hero-form.tsx:194`, `sihirbaz-cagri-karti.tsx:333`, `arama-funnel-karti.tsx:137`, `listem-bos-cta.tsx:31`, `tercih-profili-kapisi.tsx:463` — 11 yer):**
> "24 tercihlik listemi kur"
> `[BİLAL]` — "Yapay Zeka" ibaresinin CTA'dan çıkarılması bir **terim kararı**. Bugün 11 görünür CTA + 84 kod içi geçiş var ve **tek bir sözlük sabiti yok**; değişiklik ~30 dosyada elle yapılır. Alternatif (daha ucuz, geri dönüşü kolay): buton kalsın, yanına B'deki cümle konsun. Geri dönüş maliyeti: metin-only, 1 commit revert.
**Ek kural önerisi [KARAR]:** "yapay zekâ" yazımı tek kaynaktan gelsin (ör. `src/lib/marka.ts` içinde `YZ_ETIKET = "yapay zekâ"`). Bugünkü 4 farklı yazım hem markayı dağıtıyor hem gelecekteki terim kararını pahalılaştırıyor.
---
## 3. Güven engeli — öğrenci/veli neden "yapay zekâ listesi"ne mesafeli?
### 3.1 Dışarıda ne konuşuluyor
- Prof. Dr. Gamze Sart (İÜ-Cerrahpaşa, Rehberlik ve Psikolojik Danışmanlık ABD Başkanı), 9 Ağu 2026: "yapay zekânın **yanlış veya güncel olmayan bilgiler sunabilmesi** ve adayın kişisel özelliklerini yeterince değerlendirmeden önerilerde bulunabilmesi… tercih sürecinde risk oluşturabiliyor." [W] — https://www.milliyet.com.tr/egitim/yapay-zeka-sizi-yaniltmasin-7637863
- Koçluk blogları tercih robotlarını "sonuç değil başlangıç noktası" diye konumluyor; ana eleştiri "arka planda oldukça **sınırlı bir veri seti** ve genel geçer kalıplar var", "bir algoritma senin hikâyeni bilmiyor". [W] — https://www.hocamkocluk.com/blog/tercih-robotlarina-ne-kadar-guvenilmeli
- Rakip tarafında iki zıt uç var (dünkü rapordan, tekrar edilmedi): TercihSepeti ve tercih-robotu.com **"yerleşme olasılığı/ihtimali"** vaat ediyor; Unikazan ise "robot seni tanımaz, karar verici yapma" diyor (`docs/ekip-raporlari/2026-09-21/04-rakip-analizi.md` §1.2). [W, dünkü rapordan]
**Okuma:** Piyasadaki mesafe iki gerekçeye dayanıyor — **(a) uydurma/eski veri**, **(b) seni tanımıyor**. İkisinin de kodda hazır cevabı var, hiçbiri satış anında söylenmiyor.
### 3.2 Sitenin söylediği / söylemediği
| Güven iddiası | Söyleniyor mu? | Nerede | Satış anında görünüyor mu? |
|---|---|---|---|
| Veri kaynağı resmî YÖK Atlas | Evet | `page.tsx:121,361`, hero rozeti `page.tsx:247-256`, `veri-kaynagi.tsx:29` | **Evet** (tek iyi örnek) |
| Veri tazeliği (21 Eyl 2026) | Evet | `src/lib/seo.tsx:24`, hero rozeti | Evet |
| Havuz kısıtı — "uydurma program yok" | Evet ama gömülü | `page.tsx:127` (kapalı akordeon), `huni-semasi.tsx:47,52`, `meraklisina-icerik.tsx:119-127` | **Hayır** |
| Yerleşme garantisi yok | Evet, iyi | `page.tsx:132,383-392`, `sonuc/page.tsx:128-132`, `paket/page.tsx:61-63`, `giris-karti.tsx:88`, `site-footer.tsx:133` | Evet |
| Yöntem şeffaf / kara kutu değil | Evet | `/meraklisina` tamamı | **Hayır** — site içi 2 link |
| "Bu bir tahmin aracıdır" | Evet | `meraklisina-icerik.tsx:138+` | Hayır |
| Olasılık dili yasağı sistemsel | Evet (kodda zorlanıyor) | `src/lib/tadimlik-havuzu.ts:55-63` (`YASAK_GEREKCE_DILI`) | Hayır — kullanıcı bunu bilmiyor |
| **Üniversitelerden para almıyoruz** | **Hayır** | grep = 0 | Hayır |
| **Kim yaptı / kurucu kim** | **Hayır** | grep = 0 | Hayır |
| "Seni tanımıyor" itirazına cevap (öncelik çipleri) | Yarım | `sihirbaz-adimlar.tsx:487-490`: "Öncelikler yapay zekânın gerekçelerine ve program seçimine yön verir; listeyi daraltmaz." | Yalnız sihirbaz 3. adımda |
### 3.3 Güven açığı üreten kendi metinlerimiz
| Sorun | Birebir metin | Dosya:satır | Neden riskli |
|---|---|---|---|
| Yerleşme imâsı | "**Doğru strateji, doğru yerleşme.**" | `arama-funnel-karti.tsx:28` | "Garanti dili yasak" kuralımızla (`vizyon.md:88`) çelişiyor; ürün yerleşme hesaplamıyor |
| Kaynaksız yetkinlik iddiası | "**Uzman işi bir liste**, senin onayınla." | `arama-funnel-karti.tsx:42` | "Uzman" kimdir — doğrulanamaz. `[BİLAL]` |
| Aciliyet dili boş | "Boş kalan tercih, kaçan fırsattır." | `arama-funnel-karti.tsx:41` | Tercih dönemi kapalıyken anlamsız |
| İçeriksiz kanca | "Giriş yap**, çünkü kaçırmak istemezsin**" | `giris-baslik.tsx:11` | Karşılık söylemiyor; kapıda güven düşürüyor |
| Kategori çelişkisi | "**YKS Tercih Robotu 2026**" | `site-footer.tsx:49` | `vizyon.md:22`: "'Puanına göre bölüm listeleyen robot' DEĞİL". `[BİLAL]` — SEO değeri olabilir, tek başıma karar vermem |
| Takvim çelişkisi | Bant: "Tercih dönemi sona erdi" ↔ CTA: "Tercih dönemi bitmeden yerini al" | `site-top-banner.tsx:64` ↔ `hero-focus-button.tsx:45,65` | Aynı ekranda iki zıt mesaj |
| Rakip kıyası | "Sohbet botlarında belirsiz" / "Genelde yok" | `page.tsx:160-175` | Dünkü raporda düzeltildi, bugün **temiz** — genelleme yok [K] |
### 3.4 Kullanıma hazır güven cümleleri
**D — `/sonuc` tadımlık altına, giriş CTA'sının hemen üstüne (hedef: `tadimlik-satiri.tsx:172` içindeki `<p>`'ye ikinci satır):**
> "Yapay zekâ yalnızca sıralamanla açılan gerçek programlar arasından seçer; kılavuzda olmayan bir bölüm ya da üniversite öneremez."
> [K] doğrulandı: `huni-semasi.tsx:47,52`, `meraklisina-icerik.tsx:119-127`.
**E — `/paket` alt bilgisine ekleme (hedef: `src/app/paket/page.tsx:61-63`):**
> "Listendeki her satır resmî YÖK Atlas kaydına dayanır; yöntemin tamamı Meraklısına sayfasında adım adım yazılıdır."
> `/meraklisina` linkiyle. [K]
**F — Kim olduğumuz (hedef: yeni, `src/components/site-footer.tsx:128-135` bloğu):**
> "KolayTercih'i tek kişilik bir ekip geliştiriyor; hiçbir üniversiteden ücret ya da yönlendirme bedeli almıyoruz."
> `[BİLAL]` — hem kurucu kimliğini açma kararı hem de doğrulanması gereken bir ticari beyan. Doğruysa rakiplerin hiçbirinde olmayan bir ayrışma (`04-rakip-analizi.md` §1.6: Üsküdar asistanı kendi programlarını öne çıkarıyor [W]).
---
## 4. Sırayı isteme anı — çerçeve ve alternatifler
### 4.1 Bugünkü çerçeve
İstek **karşılıksız** yapılıyor. Hero'da sıralama input'unun etrafında (`hero-form.tsx:142-197`) *ne alacağını* söyleyen tek kelime yok; tek bağlam butonun kendisi. Katalog kartında ise karşılık **"programları gör"** — yani ziyaretçinin zaten baktığı tablonun filtrelenmiş hâli (`cta-sira-form.tsx:254,427`). Kapıda (`tercih-profili-kapisi.tsx:355-362`) gerekçe teknik: "Risk ve erişilebilir programlar sıralamana göre hesaplanır."
**Karşılık aynı ekranda görünmüyor.** Analitik: 621 → 28 (%4,5); katalogdan gelen 464 kişiden 12 (`03-donusum.md` §Özet-2).
Bir de örtülü maliyet var: öğrenci sıralamasını yazmak için **sıralamasını bilmek** zorunda; bilmeyen ya da utanan için çıkış yolu sunulmuyor.
### 4.2 İki alternatif çerçeve (kullanıma hazır)
**G — "Karşılık önde" (hedef: `hero-form.tsx:197` altına yeni `<p className="text-sm text-slate-600">`; ayrıca `cta-sira-form.tsx:362`'deki "Ücretsiz, üyelik gerekmez." yerine):**
> "Sıralamanı yazınca iki şey açılır: sana açık olan programların tam listesi — ücretsiz, üyeliksiz — ve istersen bu programlardan kurulmuş 24 satırlık gerekçeli tercih listen."
**H — "Maliyeti düşür" (hedef: `hero-form.tsx:177` ve `cta-sira-form.tsx:240` placeholder'ının altına yeni yardım satırı):**
> "Tek istediğimiz başarı sıralaman — ad, e-posta veya telefon sormuyoruz. Sıralamanı sonradan istediğin zaman değiştirebilirsin."
> [K] doğrulandı: form yalnızca `sira` + `tur` alıyor (`hero-form.tsx:60-93`), profil `tercihProfiliYaz` ile saklanıp `Farklı sıralama gir` ile değiştirilebiliyor (`hero-form.tsx:127-133`).
> Not: "verilerin bizde kalmaz" gibi bir cümle **kurulmamalı** — profil çereze de yazılıyor (`sihirbaz-profil.ts`, `sonuc/page.tsx:63-64`) ve her `/sonuc` isteğinde sunucuya gidiyor.
**Ek (sıralamasını bilmeyene çıkış):** `cta-sira-form.tsx:269` altına
> "Sıralamanı bilmiyorsan yanındaki puan türünü seçip tahmini bir sayı yazabilirsin; sonucu istediğin kadar değiştirebilirsin."
---
## 5. Giriş kapısı çerçevesi
### 5.1 Bugünkü metinler
| Nokta | Birebir metin | Dosya:satır |
|---|---|---|
| `/sonuc` hazır panel başlığı | "Seçimlerin hazır — Yapay Zeka listen bir adım uzakta" | `sihirbaz-cagri-karti.tsx:284` |
| Panel gövdesi | "Yukarıdaki tablo her zaman ücretsiz. 5 deneme kredinle 24 tercihlik Yapay Zeka listeni de kurabilirsin: ücretsiz giriş yap, seçimlerin kayıtlı — listen otomatik kurulsun (üretim 3 kredi, kalan 2 kredinle danışmana soru sorarsın)." | `sihirbaz-cagri-karti.tsx:286-291` |
| Panel butonu | "5 deneme kredinle Yapay Zeka listeni kur — giriş yap" + "Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede" | `sihirbaz-cagri-karti.tsx:303,308` |
| `/giris` H1 | "Giriş yap, çünkü listen seni bekliyor / …tercihine 1 adım kaldı / …kaçırmak istemezsin" (döngü) | `giris-baslik.tsx:6-13` |
| `/giris` alt metin | "Seçimlerin hazır — giriş yap, **5 deneme kredinle** listen hemen üretilsin." | `giris-karti.tsx:52-58` |
**Değerlendirme:** `/sonuc` paneli aslında iyi yazılmış — ürünün ücretsiz denenebildiğini, kredi kartı istenmediğini söylüyor. Ama üç sorun var:
1. Panel sayfanın en altında; 17 anonim oturumdan 6'sı gördü, 0 tık (`03-donusum.md`).
2. **Kapıya varınca vaat inceliyor:** `/giris`'te "kredi kartı gerekmez" cümlesi **yok**, 24 sayısı **yok**, listenin ne olduğu **yok** — yalnız "5 deneme kredisi" var, ki kullanıcı kredinin ne olduğunu bilmiyor.
3. `/giris` başlığı 6 varyantlı animasyon; ikisi içeriksiz ("kaçırmak istemezsin"). Kapıda güven değil aciliyet satıyor.
4. Sonuç: 30 günde /giris gören ~11 kişi, giriş deneyen 6 (`03-donusum.md` §1a).
### 5.2 Kullanıma hazır alternatifler
**I — `/giris` alt metni (hedef: `giris-karti.tsx:53-58`, `funnel` dalı):**
> "Seçimlerin hazır. Giriş yapınca hesabına 5 deneme kredisi tanımlanır: 3'ü 24 satırlık listeni kurar, kalan 2'siyle danışmana soru sorarsın. Kredi kartı istemiyoruz; listenin ilk 3 satırı ücretsiz açık gelir."
> [K] doğrulandı: `src/lib/credits.ts:11,14` (`DENEME_KREDISI=5`, `RAPOR_KREDI=3`), `src/lib/rapor-maske.ts:12` (`ACIK_SATIR=3`).
**J — `/giris` H1 (hedef: `giris-baslik.tsx:6-13`, döngü dizisi):**
Animasyonu koruyup içeriksiz varyantları değiştir:
> ", çünkü 24 satırlık listen üretilmeyi bekliyor" · ", çünkü 5 deneme kredin hazır" · ", çünkü seçimlerin kayıtlı" · ", çünkü kredi kartı istemiyoruz"
> ("çünkü kaçırmak istemezsin" ve "çünkü tercihine 1 adım kaldı" çıkarılır.)
**K — `/sonuc` H1 (hedef: `src/app/sonuc/page.tsx:98` ile `102` arası, `<ManuelHarita />` üstü — bugün sayfada hiç `<h1>` yok):**
> "\<sıra\>. sıralamanla açılan programlar"
> alt satır: "Aşağıdaki tablo ücretsiz ve üyeliksiz. Aynı programlardan 24 satırlık, her satırı gerekçeli bir tercih listesi kurmak istersen sayfanın altındaki adımı tamamla."
**L — Sihirbaz son butonu, girişsiz dal (hedef: `hero-form.tsx:222`, `cta-sira-form.tsx:334`):**
> "Ücretsiz tablonu gör — 24'lük liste bir sonraki adımda"
> (Bugün yalnız "Ücretsiz tablonu gör" — vaadin sessizce küçüldüğü tek nokta.)
---
## 6. Girişimler — hemen / yakın / sezon
Kurucu kapasitesi günde 1–2 saat (`docs/urun/vizyon.md:93`). Az ama bileşik iş seçildi. Hedef kitle ayrımı: **öğrenci = kullanan**, **veli = ödeyen**, **rehber öğretmen = dağıtım**.
### Hemen (bu hafta, ≤ 2 saat toplam, hepsi metin)
| # | İş | Dosya:satır | Kitle | Neden bileşik |
|---|---|---|---|---|
| H1 | Üst bandın sezon dışı metni + "tercih dönemi bitmeden" CTA'sını düzelt | `site-top-banner.tsx:60-65`, `hero-focus-button.tsx:44-46,63-66` | Hepsi | Her sayfada, her ziyaretçide; bugün doğrudan "buradan gitme" diyor |
| H2 | Hero alt başlığı ekle (öneri **A**) | `src/app/page.tsx:239→240` | Öğrenci | Ana sayfa 25/95 ziyaretin girişi ve en çok dönüştüren kanal |
| H3 | Katalog CTA açıklamasına vaadi koy (öneri **B** + **G**) | `sayfalama.tsx:40-41`, `cta-sira-form.tsx:362` | Öğrenci | 464/621 ziyaretin tek dönüşüm yüzeyi |
| H4 | `/sonuc`'a H1 + alt satır (öneri **K**) | `src/app/sonuc/page.tsx:98-102` | Öğrenci | Vaadin koptuğu yer; SEO'ya da yarar |
| H5 | `/giris` metinleri (öneri **I**, **J**) | `giris-karti.tsx:53-58`, `giris-baslik.tsx:6-13` | Öğrenci | Kapıdaki 6/11 oranı |
| H6 | Riskli 3 cümleyi çıkar | `arama-funnel-karti.tsx:28,41,42` | Hepsi | Marka tutarlılığı; "garanti dili yasak" kuralımız |
| H7 | "Havuz dışına çıkamaz" cümlesini satış anına taşı (öneri **D**, **E**) | `tadimlik-satiri.tsx:172`, `paket/page.tsx:61-63` | Veli | Tek gerçek farklılaştırıcı |
### Yakın (2–4 hafta)
| # | İş | Kitle | Not |
|---|---|---|---|
| Y1 | Rehber yazılarının sonundaki CTA'ya ürünün çıktısını yaz (27 yazı, tek bileşen: `rehber-makale.tsx:115`) | Öğrenci | Tek dosya değişikliğiyle 27 sayfa |
| Y2 | `/meraklisina`'ya site içi giriş sayısını 2'den artır: `/sonuc` dipnotu, `/paket` alt bilgisi, katalog CTA'sı | Veli | Veli "yöntem" arar; bu sayfa velinin sayfası |
| Y3 | Tadımlık havuzu kapsam denetimi — hangi kova×tür×kategori×tip kombinasyonlarında satır **yok**? Boşta vaat hiç görünmüyor | Öğrenci | `tadimlik-bolumu.tsx:19-21`, `data/app.db` = 522 satır |
| Y4 | Terim sözlüğü sabiti (`YZ_ETIKET`) — gelecekteki terim kararını ucuzlat | İç | Bugün 4 farklı yazım, ~30 dosya |
| Y5 | Veli sayfası taslağı: "Çocuğunuz ne aldı?" — 24 satır, PDF, kaynak, garanti yok | **Veli (ödeyen)** | Ödeme başlatan 0; ödeyen kişiye hitap eden tek yüzey yok |
### Sezon (Haziran–Ağustos 2027 hazırlığı)
| # | İş | Kitle |
|---|---|---|
| S1 | Rehber öğretmene yönelik tek sayfalık "sınıfta kullanılabilir çıktı" konumu (PDF + yöntem sayfası); rakiplerin hiçbiri öğretmene alet vermiyor (`04-rakip-analizi.md` §Özet-6) | **Rehber öğretmen (dağıtım)** |
| S2 | Sezon takvimine bağlı bant/CTA metin şeması: "hazırlık / sonuç bekleme / tercih / ek yerleştirme" dört durum | Hepsi |
| S3 | Kategori kararının uygulanması (aşağıda CEO-1) | Hepsi |
---
## 7. CEO karar listesi
| # | Karar | Tavsiyem | Geri dönüş maliyeti |
|---|---|---|---|
| 1 | **Sezon dışı çerçeve:** bant + CTA'lar "tercih dönemi" yerine "2027'ye hazırlık / 2026 verisi yüklendi" mi demeli? | **Evet, hemen.** Bugün her sayfanın en üstünde ürünün işe yaramadığını söylüyoruz | Düşük — metin + iki sabit; 1 commit revert |
| 2 | **CTA'dan "Yapay Zeka" çıkıp "24 tercihlik liste" gelsin mi?** (öneri C) | **Kısmi evet:** buton kalsın, yanına somut cümle gelsin. Tam değişimi ölçümden sonra yap | Orta — 11 görünür yer, tek sözlük yok; `[BİLAL]` |
| 3 | **Footer'daki "YKS Tercih Robotu 2026" adlandırması kalsın mı?** | Kalsın ama link metni "YKS Tercih Robotu 2026 — 24'lük liste kurucu" olsun; SEO'yu kaybetmeden kategori çelişkisi kapanır | Düşük; `[BİLAL]` (SEO etkisi ölçülmeli) |
| 4 | **"Üniversitelerden para almıyoruz" + kurucu kimliği sitede açılsın mı?** (öneri F) | **Evet** — rakiplerde yok, ölçeklenmiyor, ucuz | Geri dönüşü zor (kimlik açma); `[BİLAL]` |
| 5 | **`/sonuc`'a H1 eklensin mi?** (öneri K) | Evet — hem vaat sürekliliği hem erişilebilirlik | Çok düşük |
| 6 | **Veli için ayrı sayfa açılsın mı?** (Y5) | Hazırlık başlasın, yayın sezon öncesi | Orta — yeni sayfa; `[BİLAL]` (fiyat/konum dili içerir) |
| 7 | **Riskli 3 cümle ("Doğru strateji, doğru yerleşme", "Uzman işi bir liste", "Boş kalan tercih, kaçan fırsattır") çıkarılsın mı?** | **Evet** — kendi "garanti dili yasak" kuralımızı deliyorlar | Sıfır |
---
## Bilal'den istenen (3 madde)
1. **Karar-1'i onayla:** üst banttaki "Tercih dönemi sona erdi" ve "Tercih dönemi bitmeden yerini al" cümlelerinin sezon dışı karşılıklarını belirle — bugün her ziyaretçiye "geç kaldın" diyoruz. *(~10 dk)*
2. **Karar-2 ve Karar-4'ü işaretle:** CTA'da "Yapay Zeka" ibaresi kalsın mı, ve "üniversitelerden para almıyoruz / kurucu kimliği" sitede açılsın mı — ikisi de geri dönüşü pahalı marka kararı. *(~15 dk)*
3. **Tek doğrulama:** `tadimlik_havuzu`'nun (522 satır) hangi kova×tür×kategori kombinasyonlarını kapsamadığını çıkartmamı istiyor musun — kapsam dışı ziyaretçi vaadi `/sonuc`'ta hiç görmüyor. *(senden ~2 dk onay, bende ~30 dk)*
---
### Kanıt dosyaları (tam yollar)
- `/Users/bilalgursen/Desktop/kolaytercih/src/app/page.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/pazarlama/components/hero-baslik.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/sihirbaz/components/hero-form.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/sihirbaz/components/cta-sira-form.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/rapor/components/tadimlik-satiri.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/kullanici/components/giris-karti.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/kullanici/components/giris-baslik.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/components/site-top-banner.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/components/site-footer.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/components/arama-funnel-karti.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/katalog/components/sayfalama.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/app/sonuc/page.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/veri-yillari.ts`, `src/lib/credits.ts`, `src/lib/rapor-maske.ts`, `src/lib/risk.ts`
### Web kaynakları
- https://www.milliyet.com.tr/egitim/yapay-zeka-sizi-yaniltmasin-7637863 [W]
- https://www.hocamkocluk.com/blog/tercih-robotlarina-ne-kadar-guvenilmeli [W]

View File

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

View File

@@ -0,0 +1,137 @@
# 05 — CEO kararı: yapay zekâ listesine sevk
Hazırlayan: CEO ajanı · 22 Eyl 2026 gündüz · Kaynak: bugünün 01/02/03/04 raporları + kendi kod doğrulamam
**Rybbit bu oturumda bağlı değil** — bu raporda tek bir yeni ölçüm yok; rakamlar 21 Eyl raporlarından, kod iddiaları bugün tek tek açılıp doğrulandı.
---
## Tek cümlelik teşhis
> **Sevk sorunu bir "yeterince davet etmiyoruz" sorunu değil; kullanıcıyı listeye götüren yolda üç kırık halka var — + kapısı sihirbazı doldurtup kullanıcıyı yerinde bırakıyor, girişten sonra listeye dönecek kalıcı bir link yok, ve sitenin en üstünde her sayfada "tercih dönemi sona erdi" yazarken aynı sayfanın altında "bitmeden yerini al" yazıyor. Üçü de deney değil, kusur; üçünün toplam maliyeti bir saatlik kod.**
## Bu hafta yapılacak 5 iş
| # | İş | Neden (kanıt) | Boy | Yetki | Dal | Sezon dışı kabul ölçüsü (**adet**) |
|---|---|---|---|---|---|---|
| **P1** | Sezon çelişkisini kaldır: banda sezon-dışı durumu, kapanış CTA'sından yanlış aciliyeti çıkar | `site-top-banner.tsx:64` "Tercih dönemi sona erdi" ↔ `hero-focus-button.tsx:45,65` "Tercih dönemi bitmeden yerini al" (03 §3, benim doğrulamam) | S | [KARAR] (yanlış cümlenin kaldırılması) · **[BİLAL]** (bandın yeni metni) | `icerik/sezon-celiskisi` | Ölçüm konusu değil: Bilal'in 1 dakikalık göz kontrolü. Yayından sonra ana sayfa oturum sayısında düşüş **olmaması** izlenir |
| **P2** | `liste_uretim_basladi {kaynak, girisli, yeniden_deneme}` olayı — `uret()`'in ilk satırı | Üretim denemesinin **paydası yok**; 4 sessiz dal var (`liste-uretici.tsx:101-103, 143-148, 205-213`; 01 §2.3-2.4) | S | [KARAR] | `olcum/liste-uretim-basladi` | İlk 2 hafta: olay hiç düşüyor mu (beklenen 1–3/hafta); `basladi − (olusturuldu + hata + kredi_bitti)` farkı **kaç adet** |
| **P3** | + ölü ucunu bağla: `profilToplamaAc(null, …)` → `"sihirbaz"` | `program-ekle-butonu.tsx:82` ve `liste-cekmecesi.tsx:293` → `use-tercih-profili.ts:346` `null` → "Tercihlerin kaydedildi." toast'ı (`tercih-profili-kapisi.tsx:238`). Bu yol 30g'nin **en büyük sıra kaynağı**: 14/28 olay (01 §1d) | S | [KARAR] | `funnel/arti-olu-ucu` | 2 hafta: `sira_girildi{kaynak:"kapi"}` atan oturumların kaçında `sonuc_goruntulendi` de var (bugün **0 adet**, beklenen ≥1/hafta) |
| **P4** | Girişli kullanıcıya kalıcı `/listem` girişi + giriş callback'i + boş durum CTA'sı | Navbar'da `/listem` linki yok (`site-header.tsx:8-38`, `user-nav.tsx:45-64`); varsayılan callback `"/"` (`giris-karti.tsx:18-19`); `/listem` boş durumda profil yoksa CTA `"/"`'a atıyor (`listem-bos-cta.tsx:30`). Girişli 14 oturumun 7'si `/listem`'i hiç görmedi | S | [KARAR] | `funnel/listem-girisi` | 2 hafta: girişli oturumlarda `/listem` görüntülemesi **adedi** (bugün 30g'de 7); navbar linki tıklanır mı |
| **P5** | Tadımlık CTA'sının yanlış vaadi ve yanlış hedefi | "24 satırın tamamı için giriş yap" (`tadimlik-satiri.tsx:186`) ama maske 3 satır açıyor (`rapor-maske.ts:12`); callback `sonucHref()` = `/sonuc`, üretim başlamıyor (`tadimlik-satiri.tsx:111`) | S | [KARAR] (hedef + yanlış iddianın kaldırılması) · **[BİLAL]** (yeni cümle) | `icerik/tadimlik-vaat` | `tadimlik_goruntulendi` bugün 30g'de **0**; yayından sonra 2 hafta içinde ≥1 adet görülmeli (görülmezse sorun metin değil, konum) |
Toplam: 5 paket, hepsi S, toplam inceleme yükü ~1 saat. **Bu tur başka iş onaylanmadı** — yeni rehber yazısı da dahil (backlog #2 KYK yazısı 6 Ekim tarih kilidiyle zaten sırada, ona dokunulmadı).
---
## 1. İddiaların kod doğrulaması
| # | İddia | Sahibi | Hüküm | Kanıt (dosya:satır) |
|---|---|---|---|---|
| 1 | Navbar'da `/listem`'e giden hiçbir link yok; varsayılan giriş callback'i `"/"` | Analitik | **Doğru** | `site-header.tsx:8-38` (logo + `KatalogArama` + `UserNav`, başka link yok); `user-nav.tsx:45-64` (girişlide: kredi pill'i → `/paket?kaynak=nav`, `ListemButonu`, `SignOutButton`); `listem-butonu.tsx:24` (`if (liste.length === 0) return null;` — manuel liste boşken çekmece butonu **hiç render edilmiyor**); `giris-karti.tsx:18-19` (`callback && /^\/(?![/\\])/.test(callback) ? callback : "/"`); `user-nav.tsx:39` (`<Link href="/giris">` — callback **verilmiyor**) |
| 2 | + kapısı 3 adımı doldurtup toast'la katalogda bırakıyor; liste teklif edilmiyor | Tasarımcı | **Doğru** | `program-ekle-butonu.tsx:82` `profilToplamaAc(null, true, "arti_toast")`; `liste-cekmecesi.tsx:293` aynısı; `use-tercih-profili.ts:327-346` — `hedef==null` ve `duzenle==false` → `return null`; `tercih-profili-kapisi.tsx:234-249` — `yonlendir` null olduğu için `router.push` hiç çağrılmıyor, "Tercihlerin kaydedildi." toast'ı basılıyor |
| 3 | 24 satırın tamamı LLM'siz, milisaniyelerde kurulabilir; LLM yalnız gerekçe metinleri için gerekli | Yapay zekâ | **Doğru ama eksik** | Doğru olan: havuz saf SQL+JS (`rapor-havuzu.ts:97-157`), `riskNotu`/`trendOzeti` deterministik (`rapor.ts:143-150`), LLM'in şemadaki payı yalnız `gerekce` + `genelDegerlendirme` + `uyarilar` (`rapor.ts:304-326`). **Eksik olan:** üretimde 24 satırın **hangi** programlar olacağını LLM seçiyor; deterministik seçim yalnız kurtarma dalında var (`rapor.ts:349-385`, `efektifSira`'ya göre sıralama). **Rapor ayrıca şunu kaçırmış: deterministik 24'lük iskelet zaten kodda yazılı** — `mockRapor` (`rapor.ts:178-215`) tam olarak bunu yapıyor (dilim başına `efektifSira` sıralı `slice`). Önizleme işi düşünüldüğünden de ucuz; yeni algoritma değil, dev-only bir fonksiyonun prod yoluna açılması |
| 4 | Üst bant "Tercih dönemi sona erdi" basarken aynı sayfada CTA "Tercih dönemi bitmeden yerini al" diyor | Marka | **Doğru — ve rapordan biraz daha kötü** | `site-top-banner.tsx:7-8` (`TERCIH_BITISI = 2026-08-10`), `:60-65` (`asama === "sona-erdi"` → "Tercih dönemi sona erdi"), `layout.tsx:92` (her sayfada); `hero-focus-button.tsx:44-46` **ve** `:63-66` — cümle **her iki dalda da** var (profilli ve profilsiz), yani hiçbir ziyaretçi kaçmıyor; `page.tsx:651` `<KapanisCta />` |
### Raporların kaçırdığı / eklediğim bulgular
1. **`mockRapor` = hazır deterministik iskelet** (yukarıda #3). Yapay zekâ raporunun §3 önerisi "yeni bileşen + yeni yol" diye tarif edilmiş; aslında seçim mantığı `rapor.ts:178-215`'te duruyor.
2. **Sihirbazın son buton etiketi `/sonuc`'ta zaten doğru.** Marka ve tasarımcı "girişsizde etiket 'Ücretsiz tablonu gör'e düşüyor" derken üç yerden ikisini yakalamış: `hero-form.tsx:222` ve `cta-sira-form.tsx:334` gerçekten öyle, ama `/sonuc` modalında etiket **"Giriş yap ve listeni gör"** (`sihirbaz-cagri-karti.tsx:348`). Yani metin düzeltmesi 3 değil 2 yer + `tercih-profili-kapisi.tsx:463`.
3. **`ListemButonu` çifte gizli.** Yalnız "çekmece, `/listem` değil" değil — manuel liste boşken navbar'dan **tamamen kayboluyor** (`listem-butonu.tsx:24`). Yani ilk kez giriş yapan kullanıcının navbar'ında liste ile ilgili hiçbir şey yok. P4'ün gerekçesi analitiğin yazdığından güçlü.
4. **`/sonuc`'ta `<h1>` gerçekten yok** (`sonuc/page.tsx:95-130` — `ManuelHarita` → tablo → tadımlık → sihirbaz → dipnot). Marka §K doğru; bu hem erişilebilirlik hem SEO borcu.
5. **Footer ürünü "YKS Tercih Robotu 2026" diye adlandırıyor** (`site-footer.tsx:48`) — `docs/urun/vizyon.md` konumlandırmasının açıkça reddettiği kategori. Doğrulandı, ama bu tur kapsam dışı.
6. **Çalışma ağacındaki `liste-uretici.tsx` + `src/api/saglik/` işi canlıya çıkmamış.** `liste_uretim_hata {kod:"SUNUCUYA_ULASILAMIYOR"}` (`:171`) ve `GECIS_ZORLANDI` (`:179`) commit'lenmemiş durumda (`git diff --stat`: 97 satır). Bu, "kredi yandı, kullanıcı `.txt` indirdi" vakasının düzeltmesi — **bekleyen en yüksek öncelikli teslimat P1–P5'ten bile önce Bilal'de.**
---
## 2. Çelişki çözümü — neden bu sıra?
Dört ajanın dördü de kendi alanından bakarak haklı, ama aynı ağırlıkta değil, çünkü hacim küçük ve sezon kapalı. Sırayı belirleyen tek ilke şu: **kanıtın kesinliği × maliyetin düşüklüğü, beklenen dönüşüm artışından önce gelir.** Markanın çelişkisi (P1) ve tasarımcının ölü ucu (P3) "bunu yaparsak dönüşüm artar" iddiası değil, koddan birebir gösterilmiş **kusur** — ölçüme ihtiyaçları yok, çünkü aynı ekranda iki zıt cümle ya da 2 kapı geçip teklif almayan kullanıcı her hacimde yanlıştır. Analitiğin ölçüm işi (P2) bundan önce değil, **aynı yayında** gelir: tek satırlık bir olay için ayrı bir inceleme turu harcamak, 4 satırlık bir kusur düzeltmesini rehin tutmak olurdu; ama huni davranışı P3/P4 ile değişeceği için payda o değişiklikle **aynı anda** canlıda olmalı, yoksa "önce–sonra" diye bakacağımız hiçbir seri olmaz. Yapay zekânın `/sonuc` iskelet önizlemesi ise tek gerçek **yeniden tasarım**tır: haftada ~95 ziyaret ve ~0,5 liste ile (01 §5.1) etkisi 2027 sezonuna kadar okunamaz (01 §5.2: `/listem`→liste oranı için ~36 hafta), bu yüzden ertelendi — ama reddedilmedi, çünkü gerekçesi dönüşüm değil dürüstlük: bugün ücretsiz deneme ürünü değil paywall'u gösteriyor. Analitiğin "alt huni %86 sızdırırken üste trafik pompalamak boşa" tespitini aynen kabul ediyorum: bu turda hiçbir trafik/SEO işi onaylanmadı, beş işin beşi de alt huninin kırık halkaları.
---
## 3. İş paketleri (kapsam ve kabul kriteri)
Her paket ayrı dal, tek amaç, push/merge yok. Satır numaraları `main @ bda4d07` referanslı; `liste-uretici.tsx` için çalışma ağacındaki hâl geçerli.
### P1 · `icerik/sezon-celiskisi` — S
- **Amaç:** Aynı sayfada duran "geç kaldın" ↔ "acele et" çelişkisini kaldırmak.
- **Kapsam:** (a) `hero-focus-button.tsx:44-46` ve `:63-66` — "Tercih dönemi bitmeden yerini al." cümlesi **çıkar** (yerine sezona bağlı olmayan bir cümle). (b) `site-top-banner.tsx:60-65` — `sona-erdi` durumunda bandın yeni metni **ayrı `[Bilal]` commit'i** olarak hazırlanır, ana commit'e girmez. Kapsam dışı: hero başlığı, katalog CTA metni, footer adlandırması.
- **Kabul:** `grep -rn "Tercih dönemi bitmeden" src/` → 0 sonuç. `sona-erdi` dalında ekranda çelişkili iki cümle kalmaz. `[Bilal]` commit'i cherry-pick edilmeden de dal derlenir ve tutarlıdır.
### P2 · `olcum/liste-uretim-basladi` — S
- **Amaç:** Üretim denemesine payda yaratmak.
- **Kapsam:** `liste-uretici.tsx` `uret()` içinde `setDurum({ ad: "uretiliyor" })` yanına `olay("liste_uretim_basladi", { kaynak, girisli, yeniden_deneme })`; `olayBirKez` **değil**. "Tekrar dene" butonu `yeniden_deneme: "evet"` ile sayılır. Profil-yok dalı (`:205-213`) aynı olayı `sonuc: "profil_yok"` ile atar. `OlayAdi` birliğine tek ad eklenir. Kapsam dışı: `sihirbaz_acildi/kapatildi`, `sevk_tiklandi{yuzey}`, `rapor_yazdirildi`, sunucu tarafı olaylar — sonraki tura.
- **Kabul:** Dört yoldan (`sihirbaz`, `hazir_cta`, `bos_durum`, `giris_donusu`) gelindiğinde olay bir kez düşer; `kaynak` doğru dolar; mevcut `liste_olusturuldu` / `liste_uretim_hata` / `kredi_bitti` davranışı değişmez; tip kontrolü ve build temiz.
### P3 · `funnel/arti-olu-ucu` — S
- **Amaç:** Sihirbazı bitiren hiç kimse "kaydedildi" toast'ıyla yerinde kalmasın.
- **Kapsam:** `program-ekle-butonu.tsx:82` ve `liste-cekmecesi.tsx:293` → `profilToplamaAc("sihirbaz", true, "arti_toast")`. Gerekirse `use-tercih-profili.ts:346` `null` dalının davranışı buna göre sadeleşir. `tercih-profili-kapisi.tsx:237-240` toast koşulu zaten `hedef !== "sihirbaz"` kontrol ediyor; ek değişiklik gerekmez ama doğrulanır. Kapsam dışı: navbar "Sıralama gir" yolunun hedefi (`katalog-arama.tsx`), kapının tanıtım adımının kaldırılması, Ö2/Ö4/Ö5.
- **Kabul:** Katalogda + → toast → "Sıralamamı gir" → 3 adım → kullanıcı `/sonuc?hazir=1`'e (girişsiz) veya `/sonuc?sihirbaz=1`'e (girişli) **çıkar**; "Tercihlerin kaydedildi." toast'ı bu yolda görünmez; `/meraklisina` şeması etkilenmez (adım sayısı/sırası/havuz kuralları değişmiyor) ve bu rapora yazılır.
### P4 · `funnel/listem-girisi` — S
- **Amaç:** Giriş yapan kullanıcının listeye dönecek kalıcı bir yolu olsun.
- **Kapsam:** (a) `user-nav.tsx` girişli dalına `/listem` girişi (raporu varsa "Listem", yoksa "Listeni kur"); stil `ListemButonu`/kredi pill'iyle **birebir aynı** class setinden alınır, yeni pill tasarlanmaz (AGENTS.md). (b) `user-nav.tsx:39` "Giriş yap" linki `callback=/listem`. (c) `listem-bos-cta.tsx:30` profil yokken `"/"` yerine aynı sayfada profil kapısını açar. Kapsam dışı: `SectionEyebrow`/rozet değişikliği, mobil navbar yeniden düzeni, `ListemButonu`'nun boşken gizlenmesi kuralı.
- **Kabul:** Girişli kullanıcı her sayfadan tek tıkla `/listem`'e gidebilir; girişsiz görünüm değişmez; navbar mobilde (375 px) satır sarmaz; boş `/listem` CTA'sı kullanıcıyı ana sayfaya atmaz.
### P5 · `icerik/tadimlik-vaat` — S
- **Amaç:** Tek bir ekranın hem yanlış vaat vermesini hem yanlış yere göndermesini kesmek.
- **Kapsam:** `tadimlik-satiri.tsx:111` → callback `LISTEM_URET_HREF` (`/listem?uret=1`); `:186` metninden "24 satırın tamamı" iddiası **çıkar** (maske 3 satır açıyor, `rapor-maske.ts:12`). Yeni cümle **ayrı `[Bilal]` commit'i**; ana commit yalnız yanlış iddiayı kaldırır ve hedefi düzeltir. Kapsam dışı: maskenin kaç satır açtığı (gelir kararı), tadımlığın başka yüzeylere taşınması.
- **Kabul:** Girişten dönüşte üretim **başlar** (kullanıcı ek tık yapmaz); ekranda teslim edilmeyen bir sayı vaat edilmez; `giris_cta_tiklandi` davranışı korunur.
### Onaylanan rehber yazıları
**Yok.** Bu tur içerik değil kusur turu; Bilal'in inceleme kuyruğu 5 kod paketiyle dolu. Backlog #2 (KYK burs mu kredi mi, 6 Ekim tarih kilidi) ve #3 kendi sırasında kalır.
---
## 4. Bilal'e bırakılan kararlar
| Karar | Tavsiyem | Geri dönüş maliyeti |
|---|---|---|
| **Bandın sezon-dışı metni** — "Tercih dönemi sona erdi" yerine ne yazsın? | "2027 tercihine hazırlık · 2026 yerleştirme verisi yüklü" yönünde bir çerçeve. Geri sayım bileşeni kalsın, hedef 2027 takvimi açıklanınca tanımlanır. Bant her sayfada; bugün ürünün işe yaramadığını söylüyor | Düşük — metin + 2 sabit, 1 commit revert |
| **Tadımlık CTA'sının yeni cümlesi** — teslim edilenle uyumlu tek cümle | "Listenin ilk 3 satırı ücretsiz açılır" dürüst çerçevesi; "24 satırın tamamı" iddiası hiçbir hâlde kalmasın | Sıfır — metin |
| **Deneme maskesi 3 → kaç satır?** (`rapor-maske.ts:12`) | Bu hafta **değiştirme**. Gelir modeli kararı, ve hangi sayının doğru olduğunu söyleyecek veri yok (ödeme başlatan 30g'de 0). Sezon öncesi, ödeme hunisi çalıştığı doğrulandıktan sonra | Orta — fiyat/değer algısını değiştirir, geri alması müşteride kötü görünür |
| **CTA'da "Yapay Zeka" ibaresi kalsın mı?** (marka C) | Kalsın. 11 görünür yer + 84 kod içi geçiş ve tek sözlük sabiti yok; bugün ödeyeceğimiz bedel, alacağımız belirsiz faydadan büyük | Orta-yüksek — ~30 dosya |
| **Footer'daki "YKS Tercih Robotu 2026"** | Bu tur dokunma. SEO değeri ölçülmedi; kategori çelişkisi gerçek ama acil değil | Düşük ama SEO etkisi bilinmiyor |
| **Kurucu kimliği / "üniversitelerden para almıyoruz"** (marka F) | 21 Eyl'de `/hakkinda` zaten ertelendi; yeni kanıt yok, açmıyorum | Geri dönüşü zor (kimlik açma) |
---
## 5. Reddedilenler / ertelenenler — "şimdi değil, gerekçe"
| Öneri | Sahibi | Hüküm |
|---|---|---|
| `/sonuc`'ta LLM'siz 24 satırlık iskelet önizlemesi | Yapay zekâ §3 | **Ertelendi (sonraki tur, CTO şartnamesiyle).** En iyi fikir ama tek gerçek yeniden tasarım; sezon dışı hacimde etkisi okunamaz. Ucuzladı: `mockRapor` (`rapor.ts:178-215`) hazır |
| Aynı iskeletin katalog sayfalarına taşınması | Yapay zekâ §3 | **Reddedildi (bu tur).** Üst huniye yatırım; alt huni %86 sızdırırken sıra yanlış |
| `/sonuc` sıralamasının tersine çevrilmesi + boş haritanın gizlenmesi | Tasarımcı Ö4 | **Ertelendi.** M boy, CLS ve SSR etkisi var; P1–P5'ten sonra tek başına ele alınır |
| Mobil katalog satırının yeniden düzeni | Tasarımcı Ö2 | **Ertelendi.** M boy; ayrıca 992a01a'nın canlıda olup olmadığı bilinmiyor — önce o doğrulanmalı |
| `/sonuc` mobil sabit alt çubuk | Tasarımcı Ö5 | **Ertelendi.** Backlog #4'te duruyor; P3 + ölü ucunu bağladıktan sonra `/sonuc`'a gelen hacim değişecek, ondan sonra bakılır |
| Hero alt başlığı, katalog CTA açıklaması, `/giris` metinleri | Marka H2/H3/H5 | **Ertelendi.** Hepsi makul, ama bu tur 5 iş sınırı dolu; sırada ilk bunlar |
| `/sonuc`'a `<h1>` | Marka K | **Ertelendi — sonraki turun ilk işi.** Doğrulandı: bugün sayfada `<h1>` yok. Ucuz, a11y + SEO |
| `sihirbaz_acildi/kapatildi`, `sevk_tiklandi{yuzey}`, `rapor_yazdirildi` | Analitik #3/#5/#7 | **Ertelendi.** 11 kör nokta gerçek, ama bu hafta tek olay eklenir; ölçüm borcunu tek turda kapatmak inceleme kuyruğunu şişirir |
| Arama funnel kartının koyu lacivert/cyan yüzeyi | Tasarımcı §7 | **Ertelendi.** Marka kararı, dönüşümle ilgisi yok |
| CTA ikon/ok tutarsızlıkları, 36 px dokunma hedefleri, `secimlerim-paneli.tsx` ölü kodu | Tasarımcı §7 | **Ertelendi.** Tek "tutarlılık temizliği" paketi olarak sonraki tura; tek tek inceleme harcamayalım |
| `esles` alanı, çıktı dil denetimi, `gevsetildi`'nin UI'a çıkması, eval seti | Yapay zekâ İ1/İ2/§Eval | **Ertelendi.** Bu turda model/prompt/şema değişikliği onaylanmadı; eval işi onlarla birlikte gelir |
| Aşama mesajı + "uzun sürdü" eşiği 90→55 sn | Yapay zekâ #5 | **Ertelendi.** Haklı bir gözlem; ama çalışma ağacındaki `SUNUCUYA_ULASILAMIYOR` işi canlıya çıkmadan aynı dosyaya ikinci el değmesin |
| A/B testi, trafik artırma, yeni SEO yazısı | — | **Reddedildi.** Sezon dışı; her kol 47 ziyaret/haftaya düşer (01 §5.2-5.3) |
---
## 6. Diğer ajanlara açık sorular (sonraki tur)
- **CTO:** `/sonuc` iskelet önizlemesi için şartname — `mockRapor`'un seçim mantığını (`rapor.ts:178-215`) prod yoluna açmanın en küçük yolu nedir; 1–3. satırın gerekçesi tadımlık havuzundan gelirken 4–24 bulanık kalacaksa maske mantığıyla (`rapor-maske.ts`) çakışır mı? Ayrıca P2–P4'ün tek yayına nasıl paketleneceği.
- **Analitik:** Rybbit bağlandığında ilk üç sorgu sabit: (a) 21 Eyl sonrası `tadimlik_goruntulendi` ve `liste_uretim_hata` **adedi**, (b) girişli olup `/listem` görmeyen oturumların dizisi, (c) `/listem?uret=1` pageview adedi. Ek soru: P1–P5 yayınından sonra hangi **adetleri** haftalık sabit ritüelde okuyacağız — tek sayfalık bir "haftalık adet kartı" tanımla.
- **Yapay zekâ mühendisi:** `credit_ledger` sorgularının sonucu geldiğinde — `deneme − basarisiz_iade` ile Rybbit'teki `liste_olusturuldu`=3 arasındaki fark kaç, ve `reports` tablosunda kurtarma dalına düşmüş kaç liste var? Bu iki sayı "3 listenin yanında ne oldu" sorusunu Rybbit olmadan kapatır.
- **Tasarımcı:** P4'ün navbar girişi 375 px'te mevcut üç elemanla (kredi pill'i, `ListemButonu`, çıkış) aynı satıra sığıyor mu; sığmıyorsa hangisi gizlenir? Ayrıca `ListemButonu`'nun boşken tamamen kaybolması (`listem-butonu.tsx:24`) P4'ten sonra hâlâ doğru mu?
- **Marka:** Bandın sezon-dışı metni Bilal'den geldiğinde, 4 sezon durumu (hazırlık / sonuç bekleme / tercih / ek yerleştirme) için tek bir metin şeması yaz — her sezonda elle metin değiştirmeyelim.
- **QA:** P3 ve P4 dallarında tek senaryo: katalogda + → toast → sihirbaz → nereye çıkıyor; girişten dönüşte `/listem?uret=1` üretimi gerçekten başlıyor mu.
- **Ürün yöneticisi:** P1–P5 backlog'a "onaylı" olarak işlenir; ertelenenler tablosu (§5) backlog'a "aday" olarak geçer, `mockRapor` notu #önizleme işine iliştirilir.
---
## Bilal'den istenen (3 madde)
1. **Çalışma ağacındaki `liste-uretici.tsx` + `src/app/api/saglik/` işini bitir ve yayınla** — bugün bu düzeltme olmadan bir kullanıcı kredisini harcayıp ekranda `.txt` bulabiliyor; P1–P5'in hepsinden önce gelir. Aynı cevapta: 21 Eyl 23:34 commit'leri (`992a01a`, `ea3310a`) canlıda mı? — **~15 dk**
2. **Prod'da iki salt-okuma SQL'ini koş** (`04-uretim-engelleri.md` §5): `credit_ledger`'da 30 günlük `report_generate` / `refund` kırılımı ve `reports`'ta kurtarma dalı sayısı. "3 listenin yanında kaç başarısız deneme var" sorusunu Rybbit olmadan yanıtlayan tek yol bu — **~5 dk**
3. **İki metin kararı ver:** (a) üst bandın sezon-dışı hâli ne yazsın, (b) tadımlık CTA'sı "24 satırın tamamı" yerine ne desin. İkisi de her ziyaretçiyi gören cümleler; kalanı ajan yetkisinde — **~10 dk**
*(Listeden düşürdüklerim: Rybbit MCP bağlama — haftada ~0,5 listede bu hafta yeni bilgi vermez, madde 2 daha çok söyler; mobil ekran görüntüleri — + ölü ucu koddan kesin doğrulandı, fotoğraf gerekmiyor; tadımlık havuzu kapsam denetimi — marka ajanı salt okuma ile kendi koşabilir, onayı verildi; terim/footer/kurucu kararları — ertelendi.)*

View File

@@ -0,0 +1,88 @@
# 06 — CTO şartnamesi: P0-ek + P1–P4
Hazırlayan: CTO ajanı · 22 Eyl 2026 · Taban commit: `main @ bda4d07`
Kaynak kararlar: `05-ceo-karari.md`, `docs/ekip/KARARLAR.md` (22 Eyl iki kayıt)
Doğrulama koşusu (CTO): `next typegen` → `tsc --noEmit` → `pnpm lint`, baseline **yeşil** (Bilal'in kirli ağacı dâhil).
## Özet
1. `.txt` açığı gerçekten duruyordu: birincil yol (`uret()` içindeki `router.replace`) ölü sunucuda Next'in kendi kodunda tam-sayfa gezinmeye düşüyor. **P0-ek olarak 22 Eyl'de orkestratör tarafından uygulandı** (aşağıda).
2. `liste-uretici.tsx` çakışması (a) ile çözüldü: P2 o dosyaya hiç dokunmuyor, olay `listem-icerik.tsx`'e monte edilen yeni bir istemci bileşeninden atılıyor. Bedeli: `yeniden_deneme` bu turda ölçülmüyor.
3. `src/lib/analitik.ts` yalnız P2'nin. P3/P4 yeni olay adı eklemiyor → dört paketin dosya kümesi kesişimi **sıfır**, dördü paralel.
4. İki itiraz: (İ1) P3'te Ö1'in ikinci yarısı yapılmamalı — ölü kod olur ve `hedef` sözleşmesini bozar. (İ4) P4'te giriş callback'i `/listem` olmamalı — bağlam kaybı, ve `?uret=1` taşırsa rızasız 3 kredi yakar; callback **bulunulan sayfa** olmalı.
5. `/meraklisina` şeması etkilenmiyor (doğrulandı): `SEMA` adım/havuz/iskelet/gevşetme kurallarını belgeliyor, P3 yalnız kapı kapandıktan sonraki gezinme hedefini değiştiriyor.
## P0-ek — birincil yol koruması (UYGULANDI, 22 Eyl)
**Bulgu (Next 16.2.10 kaynağından doğrulandı):**
- `fetch-server-response.js` — cevap flight değilse ya da `!res.ok` ise `doMpaNavigation(url)` → string döner (bağlantı hiç kurulamazsa catch dalı da aynısını yapar ve konsola `Failed to fetch RSC payload for … Falling back to browser navigation.` basar).
- `segment-cache/navigation.js` — `typeof result === "string"` → `completeHardNavigation` → `pushRef.mpaNavigation = true`.
- `app-router.js` — `mpaNavigation` dalında `location.replace(canonicalUrl)`.
Yani `router.replace` ölü sunucuda tam olarak kaçınılmak istenen tam-sayfa gezinmeyi yapıyordu; ters vekilin düz metin 502 gövdesi tarayıcıya iniyor, WebKit `listem.txt` olarak indiriyordu. Üstelik iki yol birbirini eziyordu: RSC fetch'i 6 sn'den uzun asılırsa önce supap `SunucuYokEkrani`'nı basıyor, sonra MPA dalı o ekranı üstünden siliyordu.
**Uygulanan düzeltme** (`src/features/rapor/components/liste-uretici.tsx`):
- `sunucuAyaktaMi()` yoklaması `setDurum({ad:"geciliyor"})` ve `router.replace` **öncesine** taşındı; sunucu ölüyse `liste_uretim_hata {kod:"SUNUCUYA_ULASILAMIYOR"}` atılıp `sunucu-yok` ekranı basılıyor, gezinme hiç başlamıyor.
- Yoklama bilerek `"geciliyor"`dan önce: o durum 6 sn'lik supap zamanlayıcısını kuruyor; sonrasına konsa iki yol yarışıp aynı ekranı iki kez yazardı.
- `sunucuAyaktaMi` zamanaşımı sertleştirildi: `AbortSignal.timeout` yoksa (eski Safari) `Promise.race` ile 5 sn'lik yedek zamanaşımı; kaybeden fetch'in sonradan reddetmesi `.catch` ile yutuluyor (sahipsiz reddetme olmasın). Yoklama artık mutlu yolda koştuğu için asılması her başarılı üretimi kilitlerdi.
- Emniyet supabındaki mevcut yoklama **kaldı** (ikinci kalkan).
**Dürüst sınır:** ön-yoklama pencereyi saniyelerden milisaniyelere indirir, **kapatmaz** — konteyner yoklamadan sonra, `/listem` render'ı sırasında ölürse yine 502 gelir. Kalıcı çözüm `Dockerfile`'daki heap tavanıdır (`NODE_OPTIONS=--max-old-space-size=768`); bu ek, "kredisi yanan kullanıcı ekranda `.txt` bulmasın" garantisidir.
**Durum:** Bilal'in commit'lenmemiş işinin üstüne, çalışma ağacında uygulandı. `typegen + tsc + lint` temiz. Bilal'in kendi commit'iyle birlikte `main`'e girer.
**Denetim:** `guvenlik-uyum` — "listen kaydedildi, kredin yanmaz" iddiasının doğruluğu.
## Dosya sahipliği (kesişim: sıfır)
| Paket | Dal | Dosyalar (**Y** = yeni) |
|---|---|---|
| P1 | `icerik/sezon-celiskisi` | `src/lib/sezon.ts` **Y** · `src/components/site-top-banner.tsx` · `src/features/pazarlama/components/hero-focus-button.tsx` |
| P2 | `olcum/liste-uretim-basladi` | `src/lib/analitik.ts` · `src/features/rapor/components/uretim-basladi-olayi.tsx` **Y** · `src/features/rapor/components/listem-icerik.tsx` · `src/app/listem/page.tsx` · `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx` · `src/features/odeme/components/paket-satinal.tsx` |
| P3 | `funnel/arti-olu-ucu` | `src/features/liste/components/program-ekle-butonu.tsx` · `src/features/liste/components/liste-cekmecesi.tsx` |
| P4 | `funnel/listem-girisi` | `src/features/kullanici/components/user-nav.tsx` · `src/features/kullanici/components/giris-linki.tsx` **Y** · `src/features/rapor/components/listem-bos-cta.tsx` |
**Hiçbir paketin dokunmayacağı (Bilal'in kirli ağacı — PROTOKOL kural 3):**
`Dockerfile`, `src/app/globals.css`, `src/app/layout.tsx`, `src/features/rapor/components/liste-uretici.tsx`, `src/app/api/saglik/`, `docs/`, `content/rehber/*.md`.
`git add -A` / `git add .` **yasak** — yalnız kendi paketinin yollarını tek tek ekle.
## Ortak kurallar
1. Yalnız verilen worktree + dalda **lokal** commit. Push/merge/deploy yok, `main`'e commit yok.
2. Commit öncesi `git status --porcelain` ile Bilal'in kirli dosyalarının stage'e sızmadığını doğrula.
3. Doğrulama: `pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint`. (Depoda `typecheck` script'i yok; `pnpm lint` = `eslint`.)
4. **typegen'i atlama** — `PageProps` global tipi `.next/types`'tan gelir, taze worktree'de `tsc` onsuz baseline'da bile kırıktır.
5. `pnpm build`'i **yalnız P2** koşar (paralel build'ler belleği tüketir).
6. Worktree'de `node_modules` **symlink'i Turbopack'te patlar** — klon kullan: `cp -Rc <repo>/node_modules <worktree>/node_modules`.
7. Next bu sürümde farklı (16.2.10) — API'ye dokunmadan önce `node_modules/next/dist/docs/` altındaki ilgili sayfayı oku. Bu depoda `cacheComponents: true` (`next.config.ts:28`).
8. AGENTS.md bağlayıcı: rozet gerekirse `SectionEyebrow`; CTA'da `Sparkles` yok, metin **sonunda** `<ArrowRight className="size-4" aria-hidden />`; yeni modalda `DialogContent` varsayılan kapatma çarpısı.
9. Bu turda hiçbir paket `huni-semasi.tsx` / `meraklisina-icerik.tsx`'e dokunmaz.
10. Dev sunucusu yok, tarayıcı yok — UI'ı Bilal kontrol ediyor.
11. Uydurma veri yok: ÖSYM 2027 takvimi açıklanmadığı için P1'de tarih **uydurulmaz**, `null` bırakılır.
## Merge sırası ve denetim
Dördü paralel geliştirilir. Merge sırası **P2 → P3 → P4 → P1** (CEO'nun "payda önce" kuralı).
`guvenlik-uyum` denetimi merge koşulu: **P3** (kapı → `/sonuc?sihirbaz=1` → otomatik 3 kredi harcama yolu), **P4** (giriş callback'i / açık yönlendirme yüzeyi), **P0-ek**.
`tasarimci`: P4 navbar'ın 375 px davranışı ve "Yapay Zeka Listem" ↔ "Kendi Listem" ayrımı.
`qa-muhendisi`: P3/P4 dallarında + → toast → sihirbaz → nereye çıkıyor; boş `/listem` CTA'sı kapıyı açıyor mu.
## İtirazlar
| # | İtiraz | Düzeltilmiş kapsam |
|---|---|---|
| İ1 | P3'te `use-tercih-profili.ts:346` `null` dalının değiştirilmesi ölü kod olur ve `hedef` sözleşmesini bozar | Yalnız iki çağrı yeri değişir; `use-tercih-profili.ts` kapsam dışı |
| İ2 | P3 girişli kullanıcıda ek tık olmadan 3 kredi harcatıyor | Kapsam aynı, `guvenlik-uyum` denetimi merge koşulu |
| İ3 | P3, + toast'ının vaat ettiği risk rozetini göstermeden kullanıcıyı taşıyor | Bu tur uygulanmıyor; backlog |
| İ4 | P4'te `callback=/listem` bağlam kaybı + `?uret=1` ile rızasız kredi | Callback = **bulunulan sayfa**; yeni `giris-linki.tsx` |
| İ5 | P2'de `girisli` özelliği sabit (`/listem` auth kapılı) | `girisli` yerine `paketli` + `profil` |
| İ6 | P2'de `yeniden_deneme` kirli dosya olmadan ölçülemez | Bu turda çıkarıldı; `liste-uretici.tsx` açıldığında eklenir |
## Backlog önerileri
1. + kapısının ödülü yerinde teslim edilsin (İ3) — M, tasarımcı girdisi gerekir.
2. `liste_uretim_basladi`'nın gerçek çağrı yerine taşınması + `yeniden_deneme`.
3. `ListemButonu` boşken gizlenmesi kuralı yeniden değerlendirilsin (`listem-butonu.tsx:24`).
4. En küçük duman testi altyapısı (`vitest`): `sonucHref`, `sihirbazDogrula`, `sezonAsamasi`, `raporMaskele`, `siraKovasi`.
5. Kalan CTA ok/ikon tutarsızlıkları — tek temizlik paketi.
6. `secimlerim-paneli.tsx` ölü kod (grep ile doğrulanıp silinmeli).
7. Footer "YKS Tercih Robotu 2026" — vizyonla çelişiyor, yıl sabiti elle gömülü.

View File

@@ -0,0 +1,73 @@
# 07 — Güvenlik ve uyum denetimi: üç merge adayı dal + çalışma ağacı
Denetleyen: `guvenlik-uyum` · 22 Eyl 2026 · `main` = `e21cda4`
Kapsam: `funnel/arti-olu-ucu` (22c139a), `funnel/listem-girisi` (cb22faf, 7dc47ee, 419b617), `olcum/liste-uretim-basladi` (f60fbd1, e6fbc62) ve commit'lenmemiş `src/features/rapor/components/liste-uretici.tsx`.
Kod değiştirilmedi, commit atılmadı, canlıya dokunulmadı.
## Özet (5 madde)
1. **Kritik bulgu yok.** Üç dalın hiçbiri yetkilendirme, ödeme bütünlüğü ya da açık yönlendirme açığı açmıyor. Üçü de — aşağıdaki düzeltmelerle — merge edilebilir.
2. **P4 açık yönlendirme iddiası doğrulandı: açık yok.** `giris-karti.tsx:18-19` kalkanı `//evil.com`, `/\evil.com`, mutlak URL ve `javascript:`'i düşürüyor; better-auth 1.6.23 ayrıca hem POST hem magic-link GET yolunda kendi göreli-yol kalkanını koşuyor. **Ama** aynı kalkan `/rehber/ösym` gibi ASCII dışı ya da yüzde-kodlu her yolu better-auth'a 403 olarak gönderiyor → `GirisLinki` bu yolda girişi tamamen kırıyor (yeni regresyon, orta).
3. **P3 rıza iddiası doğrulandı ama yarım.** Ödeme anındaki buton gerçekten "Yapay Zeka listemi kur (3 kredi)" diyor (`tercih-profili-kapisi.tsx:462`) ve `raporVar`/`bekleyen.eslesir` korumaları tutuyor; çift üretim yolu açılmıyor. Kırık olan **girişteki vaat**: + toast'ı ve çekmece paneli hâlâ yalnız "sıralamanı gir → riskini gösterelim" diyor, oysa akış artık 3 kredilik bir satın almayla bitiyor (orta).
4. **P2'de allowlist iki yerde delik.** (a) `kaynak` ham hâliyle URL'de kaldığı için Rybbit'in `trackUrlParams` açık pageview'ına allowlist'ten bağımsız giriyor (`/listem` maskesiz); (b) otomatik üretim yolu **her zaman** `giris_donusu` etiketi atıyor, oysa o yol tam olarak giriş dönüşü *olmayan* yol — hero/arama/+/ödeme-sonrası hepsi bu tek yanlış etikete düşüyor, yani P2'nin ölçmek istediği şey ölçülmüyor (orta, ölçüm doğruluğu).
5. **Çalışma ağacındaki "kredin yeniden harcanmaz" iddiası DOĞRU.** `SunucuYokEkrani` yalnızca `listeOlustur` `ok:true` döndükten sonra görünür; o noktada `reports` satırı yazılmış ve kredi `spendCredits` ile bir kez düşmüştür, "Listemi aç" `?uret=1` taşımadığı için ikinci üretim başlatmaz. `/api/saglik` sabit gövdeli, DB'ye/oturuma dokunmuyor — bilgi sızdırmıyor, rate limit gerektirmiyor (zaten `main`'de, d41120c).
---
## Bulgu tablosu
| # | Dosya:satır | Sorun | Somut istismar / ihlal senaryosu | Önem | Düzeltme | Kesinlik |
|---|---|---|---|---|---|---|
| G1 | `src/features/kullanici/components/giris-linki.tsx:25-30` (+ `giris-karti.tsx:18-19`) | Callback'e konan `usePathname()` değeri ASCII dışı ya da `%` içerebiliyor; better-auth'un göreli-yol regex'i `[\w\-.+/@]` dışına çıkan her şeyi 403 `INVALID_CALLBACK_URL` ile reddediyor. Site içi kalkan geçiyor, auth katmanı geçmiyor. | Ziyaretçi `/{herhangi}/ösym-nedir` ya da `/bolum/t%C4%B1p` gibi bir adrese geliyor (yanlış/dış link, soft-404 sayfası da navbar'ı render ediyor — bkz. BACKLOG #5). Navbar'daki "Giriş yap" `/giris?callback=%2Fbolum%2Ft%25C4%25B1p` üretiyor; kullanıcı e-posta ya da Google'a basıyor, better-auth 403 dönüyor, `giris-form.tsx:99-103` "Bağlantı gönderilemedi" diyor. Kullanıcı o sayfadan **hiç giriş yapamıyor**, tekrar denemek de çözmüyor. `main`'de callback hep `/` olduğu için bu yol yoktu. | **orta** | `giris-linki.tsx`'te href kurmadan önce yolu süz: `/^\/[\w\-./+@]*$/.test(pathname)` değilse sade `/giris`. (Alternatif: `giris-karti.tsx` kalkanını aynı beyaz listeye daraltmak — iki yer yerine tek yer.) | DOĞRULANDI (better-auth 1.6.23 `auth/trusted-origins.mjs` regex'i lokalde payload setiyle koşturuldu; `/rehber/ösym`, `/rehber/%C3%B6sym` → `false`) |
| G2 | `src/features/liste/components/program-ekle-butonu.tsx:73,77,84` · `liste-cekmecesi.tsx:279,283,296` | Kapının **girişindeki** vaat ile **çıkışındaki** bedel uyuşmuyor. Toast: "Sıralamanı girersen bu programın risk seviyesini de gösteririz" + buton "Sıralamamı gir". Çekmece: "Sıralamanı girince her seçimin riskini gösteririz" + "Sıralamamı gir". Dal bu iki kapıyı `hedef="sihirbaz"`e çevirdiği için akışın sonu artık ücretsiz risk rozeti değil, 3 kredilik LLM üretimi. | 17 yaşındaki kullanıcı katalogda + ile program ekliyor, "Sıralamamı gir"e basıyor (beklenti: rozet). Sıra + 3 sihirbaz adımını dolduruyor, son butonda "(3 kredi)" ilk kez görünüyor; basınca `/sonuc?sihirbaz=1` → otomatik `/listem?uret=1` → 5 deneme kredisinin 3'ü yanıyor, kullanıcı baktığı katalog sayfasından koparılıyor. "Vazgeç" derse profil hiç kaydedilmediği için **istediği risk rozetini de alamıyor**. | **orta** | İki seçenek: (a) toast/çekmece metnini akışın gerçek sonucuna eşitle ("…sıralamanı girip birkaç seçim yaparsan 24'lük listeni de 3 krediyle kurarız") — metin `[BİLAL]`; ya da (b) bu iki yüzeyi `hedef=null` bırakıp AI'yı ayrı, adı konmuş bir CTA'ya taşı. Kod tarafı `[KARAR]`, cümle `[BİLAL]`. | DOĞRULANDI (koddan; buton etiketi zinciri `tercih-profili-kapisi.tsx:456-466` ile eşleştirildi) |
| G3 | `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx:225` (olcum dalı) | Otomatik üretim `kaynak="giris_donusu"` atıyor. Oysa `?sihirbaz=1` üreten **hiçbir** yer giriş dönüşü değil: `hero-form.tsx:104`, `cta-sira-form.tsx:172`, `use-tercih-profili.ts:331` (+ kapısı ve boş durum), `rapor-yok-cta.tsx:24`, `arama-funnel-karti.tsx:94`. Gerçek giriş dönüşü `/giris?callback=/listem?uret=1&kaynak=hazir_cta\|sihirbaz` ile **doğrudan** `/listem`'e iner, `/sonuc`'a uğramaz. | Saldırı değil, ölçüm ihlali: P2'nin tek amacı "üretimi hangi yüzey başlattı" sorusu. Merge edilirse hero (ana huni), katalog araması, + kapısı ve ödeme-sonrası CTA'sının hepsi tek bir `giris_donusu` kovasında toplanıyor; `sihirbaz` ve `hazir_cta` değerleri ise yalnız giriş dönüşünde düşüyor. Etiketler fiilen ters. | **orta** | `?sihirbaz=1`'i üreten taraf kaynağını URL'de taşısın (`sonucHref({sihirbaz:"1", kaynak:"hero"\|"arama"\|"arti"\|"bos_durum"\|"odeme_sonrasi"})`), `otomatikGonder` onu geçirsin; `IZINLI_KAYNAKLAR`'a `hero`, `arama`, `arti` eklensin. `giris_donusu` yalnız `/giris` callback'inden gelen yolda kalsın. | DOĞRULANDI (koddan; `?sihirbaz=1` üreticilerinin tamamı grep'lendi) |
| G4 | `src/features/rapor/components/uretim-basladi-olayi.tsx:25-32,54` · `src/app/layout.tsx:118` | Allowlist yalnız **özel olay özelliğini** koruyor. `kaynak` ham hâliyle adres çubuğunda kalıyor ve Rybbit `trackUrlParams: true` ile çalışıyor (`docs/gece-vardiyasi/2026-09-21/01-analitik-bulgular.md:181`); `data-mask-patterns` yalnız `/sonuc` ve `/odeme/sonuc`'u kapsıyor, `/listem` kapsam dışı. | Ücretsiz hesap açan biri `/listem?uret=1&kaynak=<istediği 200 karakter>` ile geziniyor. `liste_uretim_basladi.kaynak` doğru şekilde `bilinmiyor`a düşüyor **ama** aynı isteğin pageview'ı querystring'i olduğu gibi Rybbit'e yazıyor: panelde keyfi metin + `/listem` için kardinalite şişmesi. Giriş round-trip'i üzerinden de taşınabiliyor (`listem-icerik.tsx:51-53` → better-auth query karakter seti `%` ve `&`'a izin veriyor, yani `%3Cscript%3E` geçiyor; `<`/`>` ham hâli 403'e takılıyor). | **düşük** | `/listem`'i `data-mask-patterns`'a ekle **ya da** `listem/page.tsx`'te `kaynak`ı `ListemIcerik`'e vermeden önce allowlist'ten geçir (tek doğrulama noktası, hem URL hem olay için). İkincisi G3 düzeltmesiyle aynı yere düşüyor. | OLASI (`trackUrlParams: true` ekip raporundan alındı; canlı Rybbit'e sorgu atılmadı) |
| G5 | `src/features/rapor/rapor-actions.ts:118-124` + `liste-uretici.tsx:104,120-126` | Eşzamanlı ikinci üretim kilidi yok: iki paralel `ListeUretici` mount'u iki ayrı `requestId` üretir, `spendCredits` ikisini de geçirir → 6 kredi, 2 LLM çağrısı, tek rapor. | Üretim sürerken (20–60 sn) kullanıcı geri→ileri basıyor ya da `/listem?uret=1`'i ikinci sekmede açıyor: `raporVar` hâlâ `false` olduğu için `listem-icerik.tsx:73` ikinci kez `ListeUretici` render ediyor. **Not:** bu `main`'de de var; `funnel/arti-olu-ucu` yalnızca bu URL'e varan yolu bir tık kısaltarak maruziyeti artırıyor. | **yüksek** (mevcut, dalların doğurduğu değil) | BACKLOG #1 ("dalda") ile aynı iş: `SURUYOR` kodu + kullanıcı başına üretim kilidi. P3/P4'ün merge'i bunu beklemek zorunda değil, ama **aynı yayında** çıkmalı. | DOĞRULANDI (koddan; BACKLOG #1 ile örtüşüyor) |
| G6 | `src/features/rapor/components/listem-bos-cta.tsx:35-36` (listem-girisi) · `src/features/odeme/components/paket-satinal.tsx:157` (olcum) · `rapor-yok-cta.tsx:24-27` · `sihirbaz-cagri-karti.tsx:199-201,333` | Bedeli **hiç** yazmayan tek tık → 3 kredi yolları. "Yapay Zeka listeni kur", "listeni oluştur", "24'lük listeni oluştur", `/sonuc`'un büyük "Yapay Zeka listemi kur" butonu (kayıtlı eşleşen seçim varsa modal hiç açılmaz, `ilerle()` doğrudan koşar). | `rapor-yok-cta.tsx:31` ayrıca yanlış söylüyor: "sonuç sayfasındaki sihirbazla listeni kur" — oysa sihirbaz açılmıyor, `otomatikGonder` üretimi anında başlatıyor. Ödemesini yeni yapmış kullanıcı için zarar düşük (60 kredi), ama deneme kredisiyle gezen öğrenci `/listem` boş durumundan tek tıkla 3 kredisini yakıyor. | **düşük** | Bu dört yüzeyin etiketine "(3 kredi)" ekle — kanonik metin zaten `tercih-profili-kapisi.tsx:462`'de var. `rapor-yok-cta.tsx:31`'in yanlış cümlesi düzeltilsin. Metin `[BİLAL]`. | DOĞRULANDI (koddan) |
| G7 | `src/features/rapor/components/liste-uretici.tsx:56-72,159` (çalışma ağacı) | Sağlık yoklaması artık **mutlu yolda** ve fail-closed: `fetch("/api/saglik")` herhangi bir nedenle başarısız olursa (kurumsal proxy, 5 sn'yi aşan yavaş mobil bağlantı, geçici 503) liste gerçekten hazırken kullanıcıya "sunucuya ulaşamıyoruz" ekranı gösteriliyor. | Zarar sınırlı: liste DB'de, kredi tek düşmüş, "Listemi aç" ikinci yoklamada geçince listeye götürüyor. Yani **para riski yok**, yanlış alarm riski var. `SAGLIK_YOKLAMA_MS = 5000` yavaş 3G'de gerçek bir eşik. | **düşük** | Bulunduğu hâliyle kabul edilebilir. İstenirse: yoklama bir kez başarısız olunca 1 kez daha denensin (toplam ~2 sn ek), ya da eşik 8 sn'ye çıksın. | DOĞRULANDI (koddan; ağ koşulu simüle edilmedi) |
| G8 | `package.json` → `next@16.2.10` | `pnpm audit --prod`: 2 kritik + 12 yüksek. Ulaşılabilirlik denetlendi — **2 kritik ulaşılamıyor**: AVIF RCE için `images.remotePatterns` gerekiyor, `next.config.ts`'te tanımlı değil (optimizer yalnız yerel dosya); Windows RCE'nin karşılığı yok (Linux/Docker). Ulaşılabilir olan: "DoS in App Router using Server Actions" — bu uygulama server action ağırlıklı (`listeOlustur`, `odeme-actions`). | Kimliksiz saldırgan server action uçlarına biçimsiz yük göndererek süreci tüketebiliyor (advisory GHSA detayına bakılmalı). Dallarla ilgisi yok, mevcut durum. | **orta** | `next` 16.2.10 → **16.2.11** (yama sürümü, 9 advisory kapanıyor; 2 kritik için 16.3.3 gerekiyor ama minor atlama ayrı bir iş). | DOĞRULANDI (`pnpm audit --prod`, salt okuma) |
### Bulunamadı (arandı, yok)
- **Açık yönlendirme:** `//evil.com`, `/\evil.com`, `/%2fevil.com`, `/%5cevil.com`, `%2f%2f…`, `https://evil.com`, `javascript:` payload'larının hiçbiri `giris-karti.tsx:18-19` kalkanından geçip dış hedefe çıkmıyor; `/%2f…` kalkanı geçiyor ama tarayıcı `%2f`'i yolda çözmediği için aynı köken içinde 404 oluyor ve better-auth zaten reddediyor. `dogrula-karti.tsx:9-11`'in kalkanı zayıf (`/\evil.com`'u geçiriyor) **ama** better-auth `magic-link/verify` ucunda `originCheck` ile `(?!\/|\\|%2f|%5c)` uyguluyor → sömürülebilir değil. Yine de iki kalkanın farklı olması ileride kırılgan; birleştirilmesi önerilir (düşük, mevcut).
- **Çift üretim / çifte kredi (dalların açtığı):** yok. Otoritatif koruma sunucuda: `listem-icerik.tsx:52,54` raporu her istekte taze okuyor, rapor varsa `ListeUretici` hiç render edilmiyor. `/sonuc`'taki `raporVar` bayatlasa bile sonucu değiştirmiyor. Geri tuşu yolu kapalı (`otomatikGonder` `router.replace` kullanıyor, `ListeUretici` başarıda `router.replace("/listem")`).
- **Kredi iadesi gereken yeni dal:** yok. Üretim hatasında iade `rapor-actions.ts:163-170`'te duruyor; dallar bu yolu değiştirmiyor. `SunucuYokEkrani` iade gerektirmiyor (rapor yazılmış).
- **`/api/saglik` bilgi sızıntısı:** yok. Gövde sabit `{ok:true}`, sürüm/uptime/DB durumu yok, `Cache-Control: no-store`. Kimliksiz erişim sorun değil (Docker HEALTHCHECK zaten kullanıyor); rate limit gerektirmiyor — istek başına DB/AI maliyeti sıfır.
- **`?kaynak=` üzerinden LLM prompt enjeksiyonu / SQL:** yok. `kaynak` yalnız analitik etiketi ve URL olarak dolaşıyor; `raporUret(params)`'a giren tek şey `sihirbazDogrula`'dan geçmiş seçimler ve `siraTurGecerli`'den geçmiş sayı (`rapor-actions.ts:99-110`).
- **Yeni yetkilendirme açığı:** yok. Üç dal da yeni route/action eklemiyor; `kullanicininRaporu(session.user.id)` ve `spendCredits({userId: user.id})` sahiplik kapsamını koruyor. Id tahminiyle başkasının raporuna erişilen yeni yüzey yok.
- **İstemci paketine sızan sır:** yok. Dalların dokunduğu dosyalarda `process.env` okuması yok; `RYBBIT_API_KEY` yalnız `analitik-sunucu.ts`'te ve dosya `server-only`.
---
## Metin × kod uyumsuzlukları
1. **`gizlilik/page.tsx:97-98` — "Yalnızca oturumunu açık tutmak için zorunlu çerezler kullanılır."** Kod ayrıca `PROFIL_CEREZ_ADI` çerezini yazıyor: `max-age=31536000` (1 yıl), içeriği öğrencinin **başarı sıralaması + puan türü + ilgi alanları + iller** (`sihirbaz-profil.ts:51-57`). Reklam/izleme çerezi değil, işlevsel — ama "yalnızca oturum" ifadesi yanlış ve süresi bir yıl. KVKK aydınlatma yükümlülüğü açısından metin genişletilmeli: hangi çerez, ne tutuyor, ne kadar duruyor. **Taslak cümle önerisi ([BİLAL], avukat teyidi gerekir):** "Oturum çerezinin yanında, girdiğin başarı sıralamasını ve tercih seçimlerini cihazında saklayan işlevsel bir çerez kullanılır (1 yıl); bunu tarayıcı ayarlarından silebilirsin." — Mevcut, dalların doğurduğu değil.
2. **`rapor-yok-cta.tsx:31` — "sonuç sayfasındaki sihirbazla listeni kur."** Kod sihirbazı açmıyor; `/sonuc?sihirbaz=1` `otomatikGonder`'i tetikleyip üretimi doğrudan başlatıyor (`sihirbaz-cagri-karti.tsx:218-228`). Yanlış vaat + bedel bildirilmeden harcama. Bkz. G6.
3. **`program-ekle-butonu.tsx:73` / `liste-cekmecesi.tsx:283`** — bkz. G2: "riskini gösteririz" vaadi 3 kredilik üretimle bitiyor.
4. **Uyum — 18 yaş altı:** bu üç dal yeni bir veri toplama noktası açmıyor, ama P3 ile ücretli aksiyona ulaşan tık sayısı azalıyor. Mesafeli satış/cayma hakkı metinlerinde değişiklik gerekmiyor (kredi harcaması satın alma değil, satın alınmış kredinin kullanımı) — yine de G2'nin çözümü bedel şeffaflığının tek gerçek koruması.
## KVKK — yeni kişisel veri akışı
- **Üç dalın doğurduğu yeni akış: yok.** `kaynak` kişisel veri değil; `liste_uretim_basladi` özellikleri (`kaynak`, `paketli`, `profil: var|yok`) kişisel veri taşımıyor ve `src/lib/analitik.ts:10-11` ham sıralama kuralına uyuyor — sıralama hiçbir yeni yerde gönderilmiyor. `GirisLinki` bilinçli olarak yalnız pathname taşıyor, query taşımıyor (doğru tercih).
- **Mevcut, dikkat çekmek istediğim iki akış (dalların dışı):**
- `liste-giris-url.ts:15-17` pathname **+ query**'yi callback'e koyuyor. Eski tip `/sonuc?sira=123456&tur=say` adresinde bu, öğrencinin **ham başarı sıralamasını** `/giris?callback=…` üzerinden better-auth'a, oradan magic-link doğrulama URL'ine ve **Resend ile gönderilen e-postanın gövdesine** taşıyor (`auth.ts:19-24` `hedef.search = kaynak.search`). Gizlilik metninin "ham sıralama analitiğe gönderilmez" sözü analitik için doğru, ama e-posta sağlayıcısı için böyle bir söz yok ve akış var. **orta**, mevcut.
- `rybbit-identify.tsx:29-30` e-posta adresini ve adı Rybbit trait'i olarak gönderiyor. Gizlilik metni bunu **açıkça yazıyor** (`gizlilik/page.tsx:102-105`) ve Rybbit kendi sunucumuzda → uyumlu, aksiyon gerekmiyor.
---
## Dal dal merge hükmü
| Dal | Hüküm | Koşul |
|---|---|---|
| `olcum/liste-uretim-basladi` (P2) | **Şu düzeltmeden sonra merge edilebilir** | **G3 zorunlu** (`giris_donusu` etiketi yanlış — düzeltilmezse dalın tek amacı olan ölçüm yanlış veri üretir, üstelik seri kırılması yaratır). **G4 önerilir** (aynı düzeltmeyle tek noktada çözülüyor: `kaynak`ı `listem/page.tsx`'te allowlist'ten geçirip `ListemIcerik`'e temiz ver). Güvenlik açısından merge engeli yok. |
| `funnel/arti-olu-ucu` (P3) | **Şu düzeltmeden sonra merge edilebilir** | **G2**: + toast'ı ve çekmece panelinin metni akışın gerçek sonucuna eşitlenmeli (cümle `[BİLAL]`). Kod olduğu gibi kalabilir — rıza anı (`(3 kredi)` butonu) ve `raporVar`/`eslesir` korumaları sağlam, çifte harcama yolu açmıyor. Metin düzeltilmeden merge edilirse 17–19 yaş kullanıcıya yanlış vaatle kredi harcatmış oluruz. |
| `funnel/listem-girisi` (P4) | **Şu düzeltmeden sonra merge edilebilir** | **G1 zorunlu**: `giris-linki.tsx`'e yol beyaz listesi eklenmeli, yoksa ASCII dışı/yüzde-kodlu adreslerde giriş tamamen kırılıyor (açık yönlendirme değil ama daha kötü: kullanıcı kaybı). Navbar `/listem` linki ve boş durum CTA'sı güvenlik açısından temiz. Sıra notu: `listem-bos-cta.tsx:35` `kaynak=bos_durum` kullanıyor, bu değer `olcum` dalında tanımlı — CEO'nun "P2 önce merge edilir" kararı korunmalı (aksi hâlde zararsız ama ölçülmeyen bir parametre kalır). |
| Çalışma ağacı — `liste-uretici.tsx` | **Merge edilebilir (düzeltme koşulu yok)** | "Listen oluşturuldu ve hesabına kaydedildi — kredin yeniden harcanmaz" iddiası doğrulandı. G7 (fail-closed yanlış alarm) isteğe bağlı iyileştirme. |
---
## Bilal'den istenen
1. **G2'nin cümlesi** — + toast'ı ve çekmece panelindeki "sıralamanı gir → riskini gösterelim" metni, akış 3 kredilik listeyle bittiği için değişmeli; yeni cümleyi sen yazmalısın (**~10 dk**).
2. **`next` 16.2.10 → 16.2.11 yama yükseltmesi onayı** — 9 advisory kapanıyor, biri gerçekten ulaşılabilir (server action DoS); yama sürümü olduğu için build riski düşük (**~20 dk, build dahil**).
3. **Gizlilik metnindeki çerez cümlesi** — "yalnızca oturum çerezi" ifadesi 1 yıllık tercih profili çerezini kapsamıyor; önerdiğim taslak cümle için avukat teyidi gerekir (**~5 dk karar, teyit ayrı**).

View File

@@ -0,0 +1,47 @@
# URAP izin e-postası — taslak (gönderilmedi)
**Kime:** info@urapcenter.org
**Konu:** URAP Türkiye sıralaması verisinin kaynak gösterilerek yayımlanması hakkında izin talebi
---
Merhabalar,
Ben Bilal Gürşen. kolaytercih.com adresinde, YKS'ye giren öğrencilerin tercih listesi
hazırlamasına yardımcı olan bir web uygulaması yürütüyorum. Site, ÖSYM ve YÖK Atlas'ın açık
verilerine dayanarak 229 üniversite ve 21 binden fazla program için taban sıralama, kontenjan ve
yerleşen bilgisi sunuyor.
Üniversite sayfalarını zenginleştirmek için, öğrencilerin "bu üniversite akademik olarak nerede
duruyor" sorusuna Türkiye kaynaklı, yöntemi açık bir cevap vermek istiyoruz. Bu nedenle **URAP
Türkiye Sıralaması**'nı kullanmayı planlıyoruz. Somut olarak:
- Her üniversite sayfasında yalnız **URAP Türkiye genel sırası, toplam puanı ve bir önceki yıla
göre değişimi** gösterilecek (basın bülteninizdeki Tablo 10–11'deki değerler).
- Her değerin yanında **"Kaynak: URAP Türkiye 2025-2026"** ibaresi ve urapcenter.org'a bağlantı
yer alacak; veri dönemi tarihiyle birlikte yazılacak.
- Alt göstergeleriniz (makale, atıf, doktora, öğretim üyesi/öğrenci oranı vb.) ayrı ayrı
yayımlanmayacak; sıralamanın tamamı bir liste olarak kopyalanmayacak.
- Veri yılda bir, siz yeni sıralamayı yayımladığınızda güncellenecek.
Site ücretli bir paket de sunduğu için ticari bir kullanım söz konusu. Sitenizde açık bir lisans
metni göremediğim için, bu kullanımın sizce uygun olup olmadığını ve varsa uymamızı istediğiniz
atıf biçimi / koşulları sormak istedim.
Uygun görmezseniz ya da farklı bir kullanım biçimi önerirseniz ona göre hareket ederiz; yanıtınızı
beklerken veriyi yayımlamayacağız.
İlginiz için şimdiden teşekkür ederim.
Saygılarımla,
Bilal Gürşen
kolaytercih.com
---
## Gönderdikten sonra
- Yanıt gelince `docs/ekip-raporlari/2026-09-21/06-uni-veri.md` §2'deki URAP satırının lisans
hücresi güncellensin ("[BİLAL] kısa e-posta ile izin teyidi önerilir" → gerçek durum).
- Olumsuz/yanıtsız kalırsa 8 alanlık ilk sürümün **6. maddesi (URAP sırası)** çıkarılır; diğer
7 alan (YÖK İstatistik, OpenAlex, TÜBİTAK, ROR, kendi verimiz) izne bağlı değil.

View File

@@ -119,3 +119,15 @@ Kayıt biçimi:
- Yetki: [BİLAL] (Bilal onayladı)
- Gerekçe: `docs/ekip-raporlari/2026-09-21/` 01 (QA), 03 (analitik §4), 04 (marka §7 #1–#2), 05 (SEO T1); prod `orders` ve `tadimlik_havuzu` sorguları (21 Eyl 2026 gece, Bilal sunucuda koştu).
- Yerine geçtiği karar: 2026-09-21 — Yayın sonrası denetim… (bekleyen push onayı, yönlendirme kararı ve `tadimlik --force` maddeleri)
## 2026-09-22 — Sevk sorunu: sıra "önce çelişkiyi kaldır, sonra ölü ucu bağla", yeniden tasarım ertelendi
- Karar: 22 Eyl gündüz oturumunda dört ajanın (analitik/tasarım/marka/yapay zekâ) tek soruya verdiği dört farklı "en yüksek etkili iş" önerisi şu sıraya kondu ve bu hafta **5 iş** onaylandı: **P1** sezon çelişkisi (`icerik/sezon-celiskisi`), **P2** `liste_uretim_basladi` olayı (`olcum/liste-uretim-basladi`), **P3** + ölü ucu (`funnel/arti-olu-ucu`), **P4** girişli kullanıcıya kalıcı `/listem` girişi + giriş callback'i (`funnel/listem-girisi`), **P5** tadımlık CTA'sının yanlış vaadi ve hedefi (`icerik/tadimlik-vaat`). Hepsi S; P2 önce merge edilir ve P3/P4 ile **aynı yayında** çıkar (payda olmadan huni değişikliği okunamaz). Sezon dışı olduğu için A/B yok, oran yok: kabul ölçüsü **adet** (haftalık olay sayısı).
- Yetki: [KARAR] (P2, P3, P4; P1 ve P5'in yanlış/çelişkili cümleyi kaldıran kısmı) · [BİLAL] (P1'de bandın yeni sezon metni, P5'te tadımlık CTA'sının yeni cümlesi — ayrı `[Bilal]` commit'i olarak hazırlanır)
- Gerekçe: Dört iddia da koddan doğrulandı — navbar'da `/listem` linki yok ve giriş callback'i `"/"` (`src/components/site-header.tsx:8-38`, `src/features/kullanici/components/user-nav.tsx:45-64`, `src/features/kullanici/components/giris-karti.tsx:18-19`); + kapısı sihirbazın 3 adımını doldurtup `profilTamamlandi`'nın `null` dalında bırakıyor (`src/features/liste/components/program-ekle-butonu.tsx:82`, `liste-cekmecesi.tsx:293`, `use-tercih-profili.ts:346`, toast `tercih-profili-kapisi.tsx:238`) ve bu, 30g'deki en büyük sıra kaynağı (14/28 olay, `01-ai-listesi-hunisi` §1d); üst bant bugün "Tercih dönemi sona erdi" (`src/components/site-top-banner.tsx:7-8,64`) derken aynı sayfada CTA "Tercih dönemi bitmeden yerini al" diyor (`src/features/pazarlama/components/hero-focus-button.tsx:45,65` — her iki dalda da); tadımlık CTA'sı "24 satırın tamamı için giriş yap" diyor ama maske 3 satır açıyor ve callback `/sonuc`'a düşüyor (`tadimlik-satiri.tsx:111,186`, `src/lib/rapor-maske.ts:12`).
- Yerine geçtiği karar: —
## 2026-09-22 — `/sonuc`'ta LLM'siz 24 satırlık önizleme ve diğer yeniden tasarımlar bu hafta yapılmaz
- Karar: Yapay zekâ mühendisinin "senin 24'lük iskeletin" önizlemesi (0 LLM, `04-uretim-engelleri` §3), tasarımcının Ö2 (mobil katalog satırı), Ö4 (`/sonuc` sıralamasının tersine çevrilmesi) ve markanın H2/H3 (hero alt başlığı, katalog CTA metni) işleri **ertelendi**; sıradaki turda önce CTO şartnamesi yazılır. Ertelemeyen tek istisna `/sonuc` H1'i (`src/app/sonuc/page.tsx:98-102` arasında bugün hiç `<h1>` yok) — gelecek turun ilk işidir. Deneme maskesinin gevşetilmesi (3→8 satır) gelir modeli kararıdır, Bilal'e bırakıldı.
- Yetki: [KARAR] (erteleme) · [BİLAL] (maske/gelir kararı)
- Gerekçe: Sezon 10 Ağu 2026'da kapandı; hız ~95 ziyaret/hafta ve haftada ~0,5 liste (`01-ai-listesi-hunisi` §5.1). Bu hacimde hiçbir oran makul sürede okunamıyor (`§5.2`: en iyi aday bile ~6 hafta, `/listem`→liste ~36 hafta) ve A/B her kolu 47 ziyaret/haftaya düşürür. Bu hafta onaylanan 5 iş "ölçülemeyecek deney" değil, koddan kesin gösterilmiş **kusur ve çelişki** düzeltmesidir. Kurucunun inceleme kapasitesi günde 1–2 saat (`docs/urun/vizyon.md`); onaylanan iş = inceleme borcu.
- Yerine geçtiği karar: —

View File

@@ -0,0 +1,61 @@
# Yayın kuyruğu — Search Console'a bildirilecek adresler
Kural: `AGENTS.md` → "Yayın sonrası arama motoru bildirimi". Bir adres buraya **yazı dosyası yazıldığında** girer, **canlıda 200 döndüğü ve Search Console'a bildirildiği gün** düşer. Canlıda olmayan adres Search Console'a verilmez — 404 gönderilmiş olur ve mülk başına günde ~10-13 olan indeksleme kotası boşa yanar.
Mülk: **`sc-domain:kolaytercih.com`**, Bilal'in **ikinci** Google hesabında (Search Console adresinde `/u/1/`). Birinci hesap (`bilalgursen777@gmail.com`) bu mülkü görmüyor — "Maalesef bu mülke erişiminiz yok" diyor.
Durum: `yazıldı` (dosya var, commit yok) → `yayında` (canlıda 200) → **`sitemap ✓`** (sitemap.xml'de görünüyor) → `bildirildi` (URL denetimi yapıldı).
**Bildirimden önce iki zorunlu kapı** (`AGENTS.md` → "Yayın sonrası arama motoru bildirimi"):
1. **Canlıda 200.** `curl -s -o /dev/null -w "%{http_code}" https://kolaytercih.com/rehber/<slug>`
2. **Sitemap'te var.** `curl -s https://kolaytercih.com/sitemap.xml | grep -c "/rehber/<slug><"` → **1 değilse bildirilmez.** (22 Eyl'de `kyk-burs-mu-kredi-mi`'de çıkan "Yönlendiren site haritası algılanmadı" tam bu kontrol atlandığı için oluştu.)
## Kota kullanımı (günlük ~10-13 istek, mülk başına)
Her URL denetimi isteğinden sonra o günün satırı güncellenir. **13'e varınca o gün durulur**, kalan adresler ertesi güne yazılır. Boşa giden istek de sayılır — kotadan düşen odur, sonuç değil.
| Gün | Kullanılan / kota | Not |
|---|---|---|
| 22 Eyl 2026 | **6 / 13** | 4 başarılı bildirim + 2 boşa giden istek (arama kutusu dar pencerede kapandı — aşağıdaki nota bak) |
| *(sonraki bildirim günü)* | — / 13 | Deploy sonrası doldurulur |
## Bekleyenler — 22 Eylül gece vardiyasının yazıları
Hepsi `yazıldı`. Bilal commit'leyip deploy ettikten sonra canlıda 200 **ve sitemap'te var** doğrulanır, sonra tek tek bildirilir. Kota günde ~10-13 olduğu için 11 adres tek güne sığmaz — **sıra sütunundaki öncelikle** ilk 11'e kadar gidilir, kalan ertesi güne.
| Sıra | Adres | Durum |
|---|---|---|
| 1 | https://kolaytercih.com/rehber/taban-siralamalari-alti-yilda-nasil-degisti | yazıldı |
| 2 | https://kolaytercih.com/rehber/kac-net-ile-hangi-bolum | yazıldı |
| 3 | https://kolaytercih.com/rehber/siralama-bandlari-hangi-kapilar-acilir | yazıldı |
| 4 | https://kolaytercih.com/rehber/bilgisayar-mi-yazilim-muhendisligi-mi | yazıldı |
| 5 | https://kolaytercih.com/rehber/yeni-acilan-bolumler-nasil-degerlendirilir | yazıldı |
| 6 | https://kolaytercih.com/rehber/kktc-universiteleri-okunur-mu | yazıldı |
| 7 | https://kolaytercih.com/rehber/ek-madde-1-puanim-yetiyor-mu | yazıldı |
| 8 | https://kolaytercih.com/rehber/universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma | yazıldı |
| 9 | https://kolaytercih.com/rehber/yks-2027-takvimi | yazıldı |
| 10 | https://kolaytercih.com/rehber/yapay-zekaya-tercih-sordum-guvenilir-mi | yazıldı |
| 11 | https://kolaytercih.com/rehber/bolumumu-sevmedim-hangi-kapilar-var | yazıldı |
**Güncellenen yazı (yeni adres değil, bildirim önceliği düşük):** `https://kolaytercih.com/rehber/veliler-icin-tercih-rehberi` — kapanışı veli diline çevrildi; adres zaten dizinde, yeniden denetim **ancak kota artarsa** yapılır, yeni adreslerin önüne geçmez.
Deploy sonrası tek komutla kontrol (HTTP kodu **ve** sitemap sayımı birlikte):
```
for s in taban-siralamalari-alti-yilda-nasil-degisti kac-net-ile-hangi-bolum siralama-bandlari-hangi-kapilar-acilir bilgisayar-mi-yazilim-muhendisligi-mi yeni-acilan-bolumler-nasil-degerlendirilir kktc-universiteleri-okunur-mu ek-madde-1-puanim-yetiyor-mu universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma yks-2027-takvimi yapay-zekaya-tercih-sordum-guvenilir-mi bolumumu-sevmedim-hangi-kapilar-var; do printf "%s -> " "$s"; printf "%s " "$(curl -s -o /dev/null -w "%{http_code}" "https://kolaytercih.com/rehber/$s")"; curl -s https://kolaytercih.com/sitemap.xml | grep -c "/rehber/$s<"; done
```
Her satır `<slug> -> 200 1` olmalı. `200 0` çıkan adres **bildirilmez**: önce sitemap yeniden gönderilir, birkaç dakika sonra sayım tekrarlanır.
## Bildirilenler
| Adres | Bildirildiği tarih | Sonuç |
|---|---|---|
| https://kolaytercih.com/rehber/kyk-burs-mu-kredi-mi | 22 Eyl 2026 | "URL Google'da yok" → dizine eklenmesi istendi. Not: bu adreste **"Yönlendiren site haritası algılanmadı"** çıktı, diğer üçünde sitemap görünüyor — Google sitemap'i o yazıyı eklemeden önce okumuş olabilir; sitemap yeniden gönderildiği için bir sonraki okumada düzelmeli, **29 Eyl 2026'da kontrol edilsin**. → Bu olay yüzünden yukarıdaki **sitemap ön kontrolü** kuralı kondu; bir daha bildirimden önce `grep -c` yapılmadan devam edilmez |
| https://kolaytercih.com/rehber/bos-kontenjanlar-ne-anlatiyor | 22 Eyl 2026 | "Keşfedildi - şu anda dizine eklenmiş değil" → dizine eklenmesi istendi |
| https://kolaytercih.com/rehber/en-cok-ogrenci-alan-devlet-universiteleri | 22 Eyl 2026 | "URL Google'da yok" → dizine eklenmesi istendi |
| https://kolaytercih.com/rehber/en-secici-devlet-universiteleri | 22 Eyl 2026 | "Keşfedildi - şu anda dizine eklenmiş değil" → dizine eklenmesi istendi |
**Site haritası:** `https://kolaytercih.com/sitemap.xml` 22 Eyl 2026'da yeniden gönderildi ("Site haritası başarıyla gönderildi"). Önceki gönderim 21 Eyl, durum "Başarılı", 897 sayfa keşfedilmiş.
**Kotadan kaybedilen 2 istek (22 Eyl — yukarıdaki kota tablosunda 6/13'ün 2'si; notu duruyor ki tekrarlanmasın):** Search Console'un arama kutusu dar pencerede kapandığı için (a) `kyk-burs-mu-kredi-mi` için ikinci kez istek gönderildi, (b) iki adresin birbirine yapışmasıyla oluşan bozuk bir adres denetlendi. Doğru yöntem: pencereyi genişlet → büyüteç düğmesine bas → kutunun açıldığını **gör** → ancak o zaman yaz. Kutuya `form_input` ile değer basma, açılmamış kutuya yazma.

View File

@@ -0,0 +1,24 @@
# Kurucu brief — 22 Eylül 2026 gece vardiyası
Bu, Bilal'in (kurucu) bu vardiya için verdiği yönergenin ajanlar için sadeleştirilmiş hâlidir. Çelişki olursa bu dosya `05-ceo-karari.md`'nin (22 Eyl gündüz) "yeni rehber yazısı onaylanmadı" satırının **üstündedir** — kurucu talimatı sonradan geldi.
## Gecenin tek ana çıktısı
**Kreatif tercih rehberi yazılarını çoğaltmak.** Neden: marka bilinirliği ve internette yer tutmak. Yazılar gerçekten işe yarasın, öğrenciye dürüstçe hizmet etsin — doldurma içerik değil.
## Kurucunun çerçevesi (kendi cümleleriyle, özetlenmiş)
1. KolayTercih, tercih yapmayı **yapay zekâ ile insan arasında** kolaylaştıran bir konumda.
2. Her şey **sade ve basit** olsun. **Gereksiz over-engineering yapma.**
3. Ekipten görüş isteniyor: marka bu adla yalnızca üniversite tercih uygulaması olmaktan çıkıp başka alanlara geçebilir mi? Ekibin şimdiki görüşü: "kolaytercih güzel bir isim."
4. Kararlar **lean product** mantığıyla alınacak; Türkiye ölçeğinde internette başarılı olmuş girişimler nasıl büyüdü, hangi pazarlar/durumlar Türk kullanıcısına ödeme yaptırıyor?
5. **Öğrenciler bugüne kadar hiç ödeme yapmadı.** Neyi yanlış yapıyoruz? Bu ayrıca değerlendirilecek.
6. CEO ajanı Bilal adına karar verebilir. Sade, yalın, ne için olduğu belli kararlar.
7. Sabah Bilal'e tek özet sunulacak.
## Sınırlar (PROTOKOL.md geçerli)
- Push yok, deploy yok, `main`'e commit yok, canlıya dokunma yok.
- Çalışma ağacındaki Bilal'e ait commit'lenmemiş değişikliklere dokunma (`src/features/rapor/components/liste-uretici.tsx`, `docs/ekip/BACKLOG.md`, `docs/ekip/KARARLAR.md`).
- Uydurma veri yok: her rakamın yanında kaynağı (sorgu / dosya:satır / URL). ÖSYM-YÖK tarih ve kural bilgisi resmî kaynaktan teyit edilir, emin değilsen "doğrulanmalı" yaz.
- Yazılar `content/rehber/<slug>.md` altına yazılır. Merkezi kayıt dosyası **yok** (`src/lib/rehber.ts` klasörü tarar), bu yüzden paralel yazarlar birbirinin dosyasına dokunmaz. Commit atma; dosyayı bırak, raporla.

View File

@@ -0,0 +1,99 @@
# Orkestratör günlüğü — 22 Eylül 2026 gece vardiyası
Kurucu yönergesi: `00-kurucu-brief.md`. Ana çıktı: kreatif rehber yazılarını çoğaltmak. Yan çıktı: marka adı genişlemesi ve "neden hiç ödeme yok" sorularına CEO kararı.
## Tur 1 — başlangıç (~01:15)
| Ajan | İş | Çıktı dosyası |
|---|---|---|
| `seo-geo` | 20 kreatif konu planı (mevcut plandaki yazılmamış 4 + yedek havuzun ÜSTÜNE) | `02-seo-konu-plani.md` |
| `marka` | Soru 1: "KolayTercih" adı üniversite dışına çıkar mı · Soru 2: Türk kullanıcısı neye öder, biz neyi yanlış yapıyoruz | `03-marka-ve-odeme.md` |
| `urun-yoneticisi` | Sıfır ödeme teşhisi — değer anı, zorunlu adımlar, fiyat/paketleme, en fazla 5 lean öneri | `04-sifir-odeme-teshisi.md` |
| `rehber-yazari` ×5 | Dalga 1 yazıları (aşağıda) | `10`–`14-yazar-*.md` |
### Yazar dalgası 1 (5 yazı, paralel, ayrık dosyalar)
| Slug | Kaynak şartname | Rapor |
|---|---|---|
| `universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma` | 21 Eyl SEO planı §4 #4 | `10-yazar-ilk-hafta.md` |
| `yks-2027-takvimi` | §4 #7 | `11-yazar-2027-takvimi.md` |
| `ek-madde-1-puanim-yetiyor-mu` | §4 #8 | `12-yazar-ek-madde-1.md` |
| `bilgisayar-mi-yazilim-muhendisligi-mi` | §4 yedek havuz + DB açısı | `13-yazar-bilgisayar-yazilim.md` |
| `kktc-universiteleri-okunur-mu` | §4 yedek havuz + DB açısı | `14-yazar-kktc.md` |
Dalga 1'e alınmayan tek plan yazısı: `vakif-universitesi-burslu-indirimli-ucretli-farki` — şartnamesinde "isimde etiketi olmayan 3.839 vakıf programı çözülmeden tablo yayımlanmaz" kilidi var; veri işi önce çözülmeli, dalga 2'ye bırakıldı.
## Çalışma düzeni kararı (orkestratör, [KARAR])
Yazarlar ana çalışma ağacında, `content/rehber/` altında **yeni ve ayrık** dosyalara yazıyor; merkezi kayıt dosyası olmadığı için (`src/lib/rehber.ts` klasörü tarar) çakışma yok. Ayrı worktree + dal kurulmadı — beş markdown dosyası için worktree kurulumu kurucunun "over-engineering yapma" talimatına aykırı olurdu. Commit atılmıyor: sabah Bilal dosyaları görüp kendi commit'ini atar. Bilal'in commit'lenmemiş dosyalarına (`liste-uretici.tsx`, `BACKLOG.md`, `KARARLAR.md`) dokunulmadı.
## Tur 1 — gelen raporlar
- **`04-sifir-odeme-teshisi.md` (ürün yöneticisi) geldi.** Ana bulgu: "öğrenciler ödemedi" henüz bir pazar bulgusu değil — 30 günde paywall'a 2 kişi geldi, `odeme_baslatildi` 60+ ama `/odeme` sayfa görüntülemesi 0. Ayrıca satış sayfası girişsiz ziyaretçiye "Paketi sonra alırsın." diyor (`paket-satinal.tsx:141-143`) ve 299 TL'lik butonu göstermiyor. Beş öneri, üçü kaldırma/düzeltme.
- **`03-marka-ve-odeme.md` (marka) geldi.** Ad kalsın; genişleme tetiği adet olsun. Ödeyecek kişi (veli) için sitede tek düğme yok. Satıcı kimliği/fatura/makbuz e-postası yok; taksit kapalı. Gerçek rakip MEB'in 81 ildeki ücretsiz danışmanlık birimleri ve MEB'in kendi LGS tercih robotu.
- İki rapor birbirini bağımsız olarak doğruluyor: **kasa kırıktı, dolayısıyla "Türk öğrencisi ödemiyor" hipotezi bugün test edilmemiş durumda.** CEO'nun çözeceği asıl çelişki bu değil; asıl soru fiyat/maske kararının ne zaman verileceği.
## Tur 2 — yazarlar ve CEO
Dalga 1'in 5 yazısı + dalga 2'nin 5 yazısı bitti: **10 yeni rehber yazısı**, hepsi `content/rehber/` altında commit'lenmemiş. CEO kararı `05-ceo-kararlari.md`'de.
## `main` dalındaki 12 commit — kimin işi? (çözüldü)
**Bulgu:** Vardiya sırasında yerel `main` 12 commit ilerledi (`cb22faf`…`bca1849`, 22 Eyl 01:21–01:45), içinde P1–P4 dallarının merge'leri var. PROTOKOL md.2 "main dalına commit yok" diyor, bu yüzden kaynak araştırıldı.
**Sonuç: bu vardiyanın ajanları yapmadı.**
- Bütün yazarlar raporlarında commit atmadıklarını ayrıca belirtti; çalışma ağacında yalnız kendi yeni dosyaları duruyor.
- CEO ajanına doğrudan soruldu: hiçbir yazma/git işlemi yapmadığını, commit'leri oturum açılışındaki git anlık görüntüsünde **hazır bulduğunu** bildirdi; raporundaki "vardiya sırasında merge edildi" ifadesi zaman damgasından çıkardığı bir sonuç.
- Oturum listesinde **"AI-generated list user routing issue" oturumu hâlâ çalışıyor** (son etkinlik 22 Eyl 01:52) ve konusu tam olarak bu paketler. Merge'ler o oturumun işi.
**Etki: yok.** `origin/main` hâlâ `e21cda4` — hiçbir şey push edilmedi, canlıya bir şey gitmedi. Bilal'in commit'lenmemiş dosyaları (`liste-uretici.tsx`, `BACKLOG.md`, `KARARLAR.md`) olduğu gibi duruyor. Karar Bilal'in: bu 12 commit'i build'den geçirip push edecek mi.
**Not:** İki oturum aynı çalışma ağacında paralel çalışıyor. Bu gece sorun çıkarmadı (biri `src/`, biri `content/rehber/`) ama ileride aynı dosyaya denk gelirlerse çakışır.
## Tur 3 — editör kapısı
CEO kalite eşiği koydu: *bir dalga editör geçişinden ve rakam yeniden üretiminden geçmeden sonraki dalga başlamaz.* Üç yazıda rakam yazının kendi yöntemiyle yeniden üretilemedi (`bilgisayar…` 56/54 ↔ 57/55, `kktc…` "ÖSYM ile birebir aynı" iddiası, `siralama-bandlari…` 9.304/271/81 ↔ 9.482/277/84).
- `rehber-editoru` (tek kopya) → 10 yazının rakam/link/vaat dili denetimi → `20-editor-denetimi.md`
- `rehber-yazari` → CEO'nun onayladığı kodsuz içerik işi: `veliler-icin-tercih-rehberi.md`'ye veli diliyle kapanış (ayrık dosya, editörle çakışmıyor) → `21-yazar-veli-kapanisi.md`
- Editör bitince CEO'nun onayladığı 4 yeni konu başlatılacak: `ayni-bolum-farkli-universite-siralama-farki` · `hangi-bolumlerin-kontenjani-azaldi` · `rehber-ogretmenler-icin-veri-kaynaklari` · `bolumumu-sevmedim-hangi-kapilar-var`
## Search Console (Bilal'in gece talimatı)
Kural `AGENTS.md`'ye eklendi ("Yayın sonrası arama motoru bildirimi"), kuyruk `docs/ekip/YAYIN-KUYRUGU.md`'de. Yapılanlar `YAYIN-KUYRUGU.md`'de kayıtlı: sitemap yeniden gönderildi, canlıdaki 4 yazının URL denetimi yapılıp dizine eklenmeleri istendi. Bu gecenin 10 yazısı **canlıda olmadığı için** bildirilmedi — deploy sonrasına kuyruğa alındı.
## Tur 4 — CEO kapanış turu ve kod zinciri (02:00–)
Bilal gece yarısı ikinci talimat verdi: **"buradaki tüm sıkıntıların giderilmesini istiyorum."** CEO'ya iletildi; kapanış turu `24-ceo-kapanis.md`. Sonuç: §5'teki ertelenenler tablosu 9 KAPANIR / 5 KALICI RET / 13 ÖLÇÜLEBİLİR TETİK olarak bölündü, "ertelendi" satırı kalmadı; `[BİLAL]` listesi 3 → 1 indi (yalnız satıcı kimliği bilgileri — ajan üretemez).
**İki önermem düzeltildi:** (a) `main` push edilmiş — `origin/main = main = 9bd448b`, ahead 0, site 200; sabah listesinden "push" düştü, yerine bu gecenin içerik commit'i geçti. (b) `.next` zaten yok; asıl disk yükü Desktop'taki 4 eski worktree + `.claude/worktrees` ≈ 7,1 GB, üçü `main`'e tam merge. Silme yıkıcı olduğu için **çalıştırılmadı**, Bilal'in kararına bırakıldı.
### Editör kapısı sonucu — CEO'nun bulgusu kısmen düzeltildi
CEO dört rakamın yazının kendi yöntemiyle üretilemediğini söylemişti. Editör dördünü de kendi koştu: **üçünde yazar haklıydı**, eksik olan yöntem cümlesiydi (CEO'nun sorgusu yazının filtresini uygulamamıştı).
- `bilgisayar…` 56/54 **doğru** (ODTÜ hariç); ODTÜ dahil edilince CEO'nun 57/55'i çıkıyor → istisna rakamın geçtiği 4 yere taşındı.
- `siralama-bandlari…` 9.304/271/81 **doğru**; eksik olan `il` filtresiydi → 104 satırlık fark (61 açıköğretim + 9 boş `il` + 34 KKTC/Bosna) yazıya girdi. 8 bandın 56 hücresi ayrıca doğrulandı.
- `kac-net…` Hukuk 30,1 (51) ve Psikoloji 28,8 (72) **doğru**; CEO `sira2025 IS NOT NULL` koşulunu atlamış.
- `kktc…` **gerçek düzeltme aldı**: "ÖSYM ile birebir aynı" iddiası çıkarıldı; CEO'nun farkının kaynağı bulundu (Kıbrıs Amerikan Ü.'nün `unitur='DEVLET'` etiketli 42 satırı).
Editörün kimsenin yakalamadığı iki bulgusu: `kktc`'de çeyreklik yönü ters yazılmış; medyan tablosunun altyazısı havuzu yanlış tarif ediyormuş. Kalan 6 yazıda 60'tan fazla DB rakamının tamamı tuttu. 42 yazıda 682 link tarandı, **0 kırık hedef**. 10 yeni yazının birbirine **sıfır** linki vardı → 13 doğal çapraz link eklendi. Hüküm: **12 yazının 12'si yayımlanabilir.**
### Paralel doküman turu
`seo-geo` (netler çerçevesi 9 yerde düzeltildi + §0'a bağlayıcı kural; Search Console kota/mülk kuralı; 14 konunun 24 Eyl–15 Eki dalga takvimi) · `veri-muhendisi` (il temizliği + vakıf burs etiketi kök nedeni) · `marka` (TÜRKPATENT engeli + paket adı) · `cto` (G1+G3+G5 şartnamesi).
### Editör kapısı açıldıktan sonra başlatılan yazılar
`ayni-bolum-farkli-universite-siralama-farki` · `hangi-bolumlerin-kontenjani-azaldi` — ikisine de editörün bu gece çıkardığı tuzak listesi (yöntem kutusu, kirli `il`, `unitur` güvenilmezliği, ODTÜ KKK, vakıf burs etiketi) baştan verildi.
## Disk — teşhis (02:28)
Boş alan 5,3 GB → **4,0 GB** (%99). Kaynak ölçüldü, **bu vardiyanın ajanları değil**:
| Yer | Boyut | Kimin |
|---|---|---|
| `/private/tmp/claude-501/…/d7cdee61-…/scratchpad/dogrula` | **2,3 GB** | **Başka oturumun build doğrulama worktree'si** (`git worktree list` bunu detached HEAD @ 9bd448b olarak gösteriyor; hafıza notundaki `cp -Rc node_modules` deseni). O oturum hâlâ çalışıyor — dokunulmadı. |
| Bu vardiyanın scratchpad'i | 30 MB | bu oturum |
| Desktop'taki 4 eski worktree | 8,0 GB | Bilal'in; üçü `main`'e tam merge (`ahead=0`), ~7,1 GB geri alınabilir |
**Hiçbir şey silinmedi.** Eski worktree'lerin silinmesi yıkıcı işlem → Bilal'e komutuyla birlikte soruldu, yanıt beklendi. Diğer oturumun build worktree'sine dokunmak o oturumun işini bozar.
**Etki:** ajanlar `pnpm install`/`pnpm build` koşmadı (CEO kısıtı). Bu yüzden **bu gecenin hiçbir dalı build'den geçmedi** — G1/G3/G4/G2+G5 dalları yalnız `typecheck` + `lint` ile doğrulandı. Build doğrulaması Bilal'in sabah işinde (`24-ceo-kapanis.md` §C3 komut bloğu).

View File

@@ -0,0 +1,633 @@
# 02 — SEO/GEO konu planı: 20 yeni rehber yazısı (gece vardiyası, 22 Eylül 2026)
**Rol:** seo-geo · **Durum:** PLAN — `content/` ve `src/` altına dokunulmadı, kod değiştirilmedi, yazı yazılmadı.
**Dayanak:** `docs/gece-vardiyasi/2026-09-22/00-kurucu-brief.md` (kurucu: yazı çoğalt, marka bilinirliği ve internette yer tut, doldurma içerik değil) · `docs/ekip/PROTOKOL.md` · `docs/ekip-raporlari/2026-09-21/05-seo-plan.md` (§2 yazım kuralları, §4 konu listesi) · `docs/geo/geo-raporu.md` §8.1.1.
**Kanıt işaretleri:** **[D]** birincil kaynak / kod / DB okundu · **[A]** yalnızca arama özeti veya ikincil kaynak · **[Ç]** çıkarım · **[doğrulanmalı]** yayın öncesi resmî kaynaktan teyit şart.
**Veri kısıtı (önemli):** Arama hacmi aracı (Ahrefs/Similarweb) yetkisiz — **hiçbir hacim rakamı verilmedi ve uydurulmadı**. Talep kanıtı olarak yalnızca şunlar kullanıldı: Search Console AI gösterim tablosu (`docs/geo/geo-raporu.md` §8.1.1, 19.06–18.09.2026 [D]), rakip taban-puan sitelerinin aynı soruya ayırdığı sayfa yoğunluğu [A], haber/forum başlık sıklığı [A]. Tüm DB rakamları `data/yokatlas.db` üzerinde bu gece koşturulan sorgulardan [D]; `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z` [D]. **2026 net verisi yok** — `netler` tablosu 2023–2025 arası (62.975 satır, 25.166 program) [D]. Web sayfalarında bana yönelik talimat görülmedi.
---
## Özet (5 madde)
1. **Elimizde rakiplerin yazamayacağı üç veri sırtı var ve üçü de sezon dışı çalışır:** (a) 2021→2026 **altı yıllık eşleşmeli taban sıralaması trendi** (ör. İlköğretim Matematik Öğretmenliği 76 programda 83.225 → 218.963; Tarih 64 programda 276.363 → 120.510) [D]; (b) **program bazında "en son yerleşen kişinin netleri"** (YÖK Atlas Net Sihirbazı verisi; 2025, 20.821 program satırı, hepsi dolu) — "kaç net ile hangi bölüm" sorusunun tek gerçek cevabı [D]. **Dikkat: bu veri yerleşenlerin ortalaması değildir**, o programın taban puanını yapan **tek kişinin** profilidir (kanıt: `18-yazar-kac-net.md` §1); (c) **2025→2026 kontenjan kısıntısı** (İngiliz Dili ve Edebiyatı −1.096, Görsel İletişim Tasarımı −1.084, Hukuk −1.072, Diş Hekimliği −792) [D]. Bu üçü 20 konunun omurgası.
2. **Sezon dışıyız, bu yüzden dağılım niyet bazlı:** 6 konu saf veri raporu (yıl boyu arandığı için evergreen), 4 konu 2027'ye hazırlanan 11. sınıf/mezun, 4 konu yeni yerleşmiş 1. sınıf, 4 konu **veli ve rehber öğretmen** (ayrı dağıtım kanalı — istenen asgari 3'ü aştık), 2 konu GEO/marka. Her konunun niyeti tabloda yazılı.
3. **Takvime bağlı hiçbir konu ana 20'ye alınmadı.** ÖSYM 2027 sınav takvimi 22 Eylül itibarıyla **açıklanmamış** [A: memurlar.net arşivi + ÖSYM sınav grubu sayfası, arama özeti]; KYK burs/kredi ve ek yurt tarihleri GSB tarafından duyurulmamış [A]. Bunlar §3'teki "şimdi yazılmaz" listesinde; ana 20 tarih bağımsız.
4. **Paralel yazarlar için çakışma haritası §1'de.** Dört konu (#1, #4, #5, #10) aynı `programs` trend iddiasını paylaşıyor: **#1 kanonik kaynak**, diğer üçü kendi rakamını yeniden hesaplamak yerine #1'e iç link verir. Ayrıca #6 mevcut `kac-siralama-ile-hangi-bolume-girebilirim` yazısıyla **kanibalizasyon riski taşıyor** — ayrım kuralı yazılı, editör denetleyecek.
5. **GEO tarafında biçim kanıtı net:** AI gösteriminde ilk 10'un 7'si rehber yazısı, 24 rehber 864 katalog sayfasından fazla gösterim çekiyor [D: geo-raporu §8.1.1]. İlk cümlesi tek başına cevap veren, soru biçimli H2 kullanan yazı formatı çalışıyor → 20 konunun tamamı bu formatta, her birinin "ilk paragraf cevabı" aşağıda yazılı hâlde veriliyor (yazar cümleyi kurmakla uğraşmasın).
---
## 0. Yazarlara ortak kurallar (her konu için geçerli, tekrar edilmeyecek)
`05-seo-plan.md` §4 başındaki ortak kurallar aynen geçerli. Özetle:
- Slug'da **yıl yok**; yıl başlıkta ve gövdede olabilir.
- Frontmatter yalnızca `baslik`, `aciklama`, `tarih` (+ gerekirse `guncelleme`) — `src/lib/rehber.ts` düz `anahtar: değer` satırları parse ediyor [D].
- **1 adet `flowchart TD` mermaid şeması**, içinde `%% aria:` satırı **zorunlu** (erişilebilirlik metni), `%% altyazi:` önerilir. İkisi de mermaid tanımından ayıklanıyor [D: `src/lib/rehber.ts`].
- En az **1 tablo**; ilk paragraf tek başına cevap; H2'ler soru biçiminde; sonda "Kaynaklar" + erişim tarihi.
- **Vaat dili yasak** ("yerleşirsin", "garanti", "kesin"). Risk dilimi görünen adı **"Güvenli"** (`src/lib/risk.ts` `DILIM_ETIKET`). Renk tek başına anlam taşımaz — her renkli düğümde metin etiketi.
- **Rakam yalnızca** (a) aşağıda sorgu metni verilen DB sorgusundan ya da (b) resmî belgeden. Doğrulanamayan cümle yazıdan çıkarılır, "muhtemelen" diye yazılmaz.
- CTA linki `/tercih-robotu`'na **verilmez** (301'e gidiyor, `next.config.ts:77` [D]); doğrudan `/` ya da `/bolumler`.
- DB rakamı kullanan her yazının sonunda **"Bu yazıdaki tablolar nasıl hesaplandı"** kutusu: hangi tablo, hangi yıl kolonu, hangi filtre, kaç program. (GEO'da alıntılanmanın en güçlü sinyali; rakiplerde yok.)
- Her yazı DB'den rakam veriyorsa **veri tarihi** yazılır: 21 Eylül 2026 (`KATALOG_VERI_TARIHI`, `src/lib/seo.tsx:24` [D]).
- **`netler` tablosu kuralı (bağlayıcı, her yazı için).** Bu tablo YÖK Atlas'ın **Net Sihirbazı** verisidir: her satır, o programa **en son yerleşen tek kişinin** netleridir — yerleşenlerin ortalaması **değildir**. Kanıt: `src/features/katalog/components/program-netleri.tsx:3` ve `scripts/detay.ts:5` kod yorumları; 2025'e ait 20.821 satırın 20.820'sinde net tam 0,25'in katı (tek kişilik gözlemin imzası); `netler.tabanPuan` = `programs.puan2025` %99,8 eşleşme — ayrıntı `docs/gece-vardiyasi/2026-09-22/18-yazar-kac-net.md` §1 [D]. Bundan türeyen üç kural: (a) "yerleşenlerin ortalama neti", "ortalama net", "net barajı", "net eşiği" ifadeleri **yasak**; doğru dil **"o programa en son yerleşen kişinin netleri"**. (b) Birden çok program üzerinden `AVG()` alındığında doğru okuma "N programın **en son yerleşenlerinin** neti, program ortalaması" olur — tablo başlığı bunu yazar, kolon adı "ortalama net" olmaz. (c) **`netler` 2025'te bitiyor** (2023–2025; 2026 net verisi YÖK Atlas'ta yayımlanmamış — 22 Eyl 2026'da canlı servisten teyit edildi [D: `18-yazar-kac-net.md` §3]): **her net rakamının yanında yıl etiketi zorunlu**, katalogdaki 2026 taban rakamıyla aynı cümlede yılsız yan yana yazılmaz.
---
## 1. Paralel çalışma: çakışma ve tutarlılık haritası (editör denetleyecek)
| Çakışma | Konular | Kural |
|---|---|---|
| **Altı yıllık trend iddiası** (`sira2021` vs `sira2026`) | #1 (kanonik), #4, #5, #10 | #1 rakamı üretir ve yöntemi anlatır. #4/#5/#10 aynı sorguyu **yeniden yorumlamaz**, kendi dar kesitini verir ve "yöntem ve tüm liste: #1" diye iç link koyar. Ortak cümle: "Sıralama küçüldükçe program seçicileşir." |
| **Net / sıralama okuryazarlığı** | #2, #15 | #2 net rakamlarının sahibi. #15 (veli) net tablosu **tekrarlamaz**, tek örnek verir + #2'ye link. **İkisi de §0'daki `netler` kuralına tabidir:** rakam "en son yerleşen kişinin netleri (2025)" diye tanıtılır, "yerleşenlerin ortalaması" diye **değil**. #15 tek örnek verirken bu ibareyi ve yıl etiketini birlikte taşır. |
| **"Sıralamamla ne olur"** | #6 ↔ mevcut `kac-siralama-ile-hangi-bolume-girebilirim` | **Kanibalizasyon riski.** Mevcut yazı: "hangi bölüme girebilirim" (bölüm adı odaklı). #6: "kaç seçeneğim var, arz nasıl dağılmış" (sayı odaklı). #6 girişinde mevcut yazıya link **zorunlu**; #6 bölüm adı listesi vermez. Editör iki yazının H2'lerini karşılaştırsın. |
| **Önlisans verisi** | #12 (DGS), #20 (en çok yerleşilen önlisans) | #20 envanteri verir, #12 sonraki adımı. İkisi de 354.627 önlisans yerleşen rakamını kullanacak — **aynı sorgudan**, aynı biçimde yazılsın. |
| **"Bölümümden memnun değilim"** | #11 ↔ mevcut `yatay-gecis-cap-yandal`, `universite-okurken-tekrar-yks`, `mezuna-kalmak-mi-kayit-olmak-mi` | #11 **hub**: hiçbir kapıyı detaylandırmaz, karar ağacı + mevcut üç yazıya yönlendirme. 400–600 kelime + şema yeterli. Detay yazarsa üç yazıyı da kanibalize eder. |
| **Mezuna kalma kararı** | #16 (veli tarafı) ↔ mevcut `mezuna-kalmak-mi-kayit-olmak-mi` (öğrenci tarafı) | #16 OBP/kırık OBP mekaniğini **anlatmaz**, mevcut yazıya link verir; kendisi maliyet, ev içi anlaşma ve "kayıtlı kalıp hazırlanmak" seçeneğini işler. |
| **Burs/destek** | #14 ↔ bu gece yazılan `kyk-burs-mu-kredi-mi`, mevcut `yurt-burs-ve-yillik-maliyet` | #14 **KYK dışını** işler (belediye, vakıf, üniversite başarı bursu). KYK bölümü tek paragraf + link. |
| **İl/şehir** | #18 ↔ teknik T7 (`/il/[slug]` sayfası yok) | #18 yazısı T7'nin talep kanıtı; yazı yayımlanırken T7 yoksa il linkleri `/universiteler`'e gider, **ölü link yazılmaz**. |
| **Vakıf burs etiketi** | Hiçbiri | 3.821 vakıf lisans programında isimde burs etiketi yok (Burslu 339 / İndirimli 416 / Ücretli 199 / etiketsiz 3.821) [D]. **Bu 20 konunun hiçbiri burs etiketi kırılımına dayanmıyor** — bilerek. Veri sorusu çözülene kadar o kesit yalnızca bu gece atanan `vakif-universitesi-burslu-indirimli-ucretli-farki` yazısının sorunu. |
---
## 2. Yirmi konu
Niyet kodları: **H** = 2027'ye hazırlanan (11. sınıf / mezun) · **B** = yeni yerleşmiş 1. sınıf · **E** = evergreen (yıl boyu) · **V** = veli / rehber öğretmen.
### Dalga A — Veri sırtı (öncelik 1–6). Sezondan bağımsız, rakiplerde karşılığı yok.
---
#### 1. `taban-siralamalari-alti-yilda-nasil-degisti` — **öncelik 1** · zorluk **L** · niyet **E + H**
- **Başlık:** Altı Yılda Hangi Bölümlerin Tabanı Sıkılaştı, Hangileri Geriledi? (2021–2026)
- **Hedef sorgular:** "taban sıralamaları nasıl değişti", "hangi bölümün puanı düştü", "bölümlerin popülerliği değişiyor mu", "2021 2026 taban puan karşılaştırma"
- **İlk paragraf cevabı (tek cümle):** Hem 2021'de hem 2026'da öğrenci alan lisans programlarını tek tek eşleştirip baktığımızda son altı yılda **en çok sıkılaşan** bölümler İktisat (51 programda ortalama taban sırası 256.761'den 131.892'ye), Tarih (64 programda 276.363 → 120.510) ve İşletme (126 programda 246.703 → 130.604), **en çok gerileyen** bölümler ise İlköğretim Matematik Öğretmenliği (76 programda 83.225 → 218.963), Yazılım Mühendisliği (51 programda 90.332 → 145.425) ve Psikoloji (184 programda 152.325 → 270.358) oldu.
- **5 maddelik iskelet:**
1. Yöntem, en başta ve dürüstçe: "aynı program hem 2021 hem 2026 listesinde olmalı" kuralı, kaç program kaldı, neyi ölçmediğimiz (kapanan/yeni açılan programlar dışarıda, kontenjan değişimi ayrı etki).
2. **Sıkılaşan 10 bölüm** tablosu + tek cümlelik okuma: sözel/eşit ağırlık tarafında sınava giren sayısı ve kontenjan davranışı sıralamayı yukarı çekmiş olabilir [Ç, "olabilir" diye yazılır].
3. **Gerileyen 10 bölüm** tablosu: öğretmenlik ve yazılım/bilgisayar tarafındaki hareket. Mühendislik toplamı 890 programda 124.792 → 108.205 (sıkılaşmış) ama Bilgisayar ve Yazılım Mühendisliği ayrıksı — "bölüm adı değil program sayısı arttı" açıklaması.
4. **"Taban gerilemesi = bölüm kötüleşti mi?"** — hayır: kontenjan artışı, yeni program açılışı, puan türü nüfusu ve o yılın sınav zorluğu hepsi sıralamayı oynatır. Öğrenciye asıl söylenecek: tek yıla değil **yöne** bak.
5. **2027 tercihçisi bu tabloyu nasıl kullanır:** hedef bölümünün son 3 yıl yönü + kendi sıralama bandı → `hedef-siralama-nasil-belirlenir`'e köprü.
- **Şema ne anlatacak:** `flowchart TD` — "Bir bölümün tabanı geriledi" düğümünden dört olası neden dallanır (kontenjan arttı · yeni program açıldı · puan türü nüfusu değişti · talep gerçekten düştü); her dalın altında "2027'de ne bekle" kutusu ve **metin etiketli** uyarı/güvenli işareti. Amaç: tek yılın rakamından sonuç çıkarmanın neden yanlış olduğunu göstermek.
- **Tablo kolonları:** bölüm adı · eşleşen program sayısı · 2021 ortalama taban sırası · 2026 ortalama taban sırası · fark (%) · yön (sıkılaştı/geriledi)
- **DB sorgusu:**
```sql
SELECT isim, COUNT(*) n, CAST(AVG(sira2021) AS INT) s21, CAST(AVG(sira2026) AS INT) s26,
ROUND(100.0*(AVG(sira2026)-AVG(sira2021))/AVG(sira2021),1) degisim
FROM programs
WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
GROUP BY isim HAVING n>=25 ORDER BY degisim ASC; -- DESC = gerileyenler
```
Mühendislik/öğretmenlik toplamı için `isim LIKE '%Mühendisliği%'` / `'%Öğretmenliği%'` ile aynı sorgu.
- **İç link:** `taban-siralamalar-nasil-degisir`, `taban-puan-mi-siralama-mi`, `hedef-siralama-nasil-belirlenir`, `bos-kontenjanlar-ne-anlatiyor`, `/bolum/iktisat`, `/bolum/tarih`, `/bolum/psikoloji`, `/bolum/isletme`, `/bolum/ilkogretim-matematik-ogretmenligi`
- **Not:** Bu yazı 20'nin kanonik veri kaynağı. Önce bu yazılsın; #4, #5, #10 buna link verecek.
---
#### 2. `kac-net-ile-hangi-bolum` — **öncelik 2** · zorluk **L** · niyet **H + E**
> **DÜZELTME (22 Eyl 2026 gece, CEO §C5 · A6).** Bu maddenin ilk hâli `netler` tablosunu "yerleşenlerin ortalama netleri" diye tanımlıyordu — **yanlıştı.** Tablo YÖK Atlas Net Sihirbazı verisidir: **o programa en son yerleşen tek kişinin** netleri (§0'daki `netler` kuralı, kanıt `18-yazar-kac-net.md` §1). Aşağıdaki başlık, ilk paragraf ve iskelet bu doğru çerçeveyle yeniden yazıldı. Yayımlanan yazı (`content/rehber/kac-net-ile-hangi-bolum.md`) zaten doğru çerçeveyi kullanıyor — hata yalnız plandaydı, düzeltilmesinin sebebi sonraki dalgaların kopyalamaması.
- **Başlık:** Kaç Net İle Hangi Bölüm? Devlet Üniversitelerine En Son Yerleşenlerin Netleri (2025)
- **Hedef sorgular:** "kaç net ile tıp", "kaç net ile hukuk", "kaç netle bilgisayar mühendisliği", "tyt ayt net ortalamaları bölümlere göre"
- **İlk paragraf cevabı:** YÖK Atlas, her programa **en son yerleşen kişinin** netlerini yayımlıyor; 2025 yerleştirmesinde devlet üniversitelerindeki programlara **en son yerleşenlerin** netleri program program ortalandığında tablo şöyle: Tıp'ta TYT matematik 28,2 / TYT Türkçe 31,5 / AYT matematik 33,8; Diş Hekimliği'nde 25,5 / 30,2 / 30,9; Hukuk'ta 19,2 / 29,9 / 21,8; Bilgisayar Mühendisliği'nde 18,9 / 27,6 / 20,2; Hemşirelik'te 16,1 / 26,6 / 17,2; Psikoloji'de 12,2 / 28,0 / 11,5 — yani "kaç net" sorusunun cevabı bölüme değil, **o bölümün hangi üniversitesine** baktığına göre değişiyor. *(Rakam çerçevesi: bunlar bir bölüme yerleşen herkesin ortalaması değil, o bölümün N programına **en son giren N kişinin** netlerinin ortalamasıdır — kapıda son duran profil.)*
- **5 maddelik iskelet:**
1. Neyi ölçtüğümüz: bu rakamlar hedef değil, **o programa en son yerleşen kişinin gerçekte yaptığı netler** (YÖK Atlas Net Sihirbazı verisi). Yerleşenlerin ortalaması **değil** — tek kişilik bir gözlem, bu yüzden "net barajı/eşiği" diye okunamaz ve yıldan yıla çok oynar. **En güncel yıl 2025** — 2026 net verisi henüz yayımlanmadı, bu açıkça yazılır ve her rakamın yanında yıl etiketi durur.
2. Popüler bölümler tablosu (devlet, lisans): TYT Türkçe / TYT Matematik / AYT Matematik / AYT Fen netleri yan yana.
3. **Net → sıralama → bölüm zinciri:** net tek başına hiçbir şey söylemez; aynı net farklı yıllarda farklı sıralama verir. Burada `taban-puan-mi-siralama-mi` ve `merkezi-yerlestirme-nasil-calisir`'a köprü.
4. **TYT Türkçe tuzağı:** İşletme'de TYT Türkçe 23,9 iken Tıp'ta 31,5 — yani "sayısalcıyım, Türkçe'yi bırakıyorum" hatası rakamla gösterilir.
5. Kendi netinden nereye: deneme netini sıralamaya çevirme adımı + sıra formu.
- **Şema:** `Deneme netin` → TYT/AYT ayrımı → "net sıralamaya çevrilir, sıralama bölüm açar" → üç çıkış (hedefin üstünde / bandında / altında), her biri metin etiketli. Amaç: net ile sıralama arasındaki dolaylı ilişkiyi görselleştirmek.
- **Tablo kolonları:** bölüm · program sayısı (devlet) · TYT Türkçe · TYT Matematik · AYT Matematik · AYT Fizik · AYT Biyoloji · 2025 ortalama taban sırası. **Tablo başlığı ve altyazısı zorunlu ibareyi taşır:** "Devlet üniversitelerinde bu bölümün N programına **2025'te en son yerleşen** kişilerin netleri, program ortalaması". Kolon başlığı "ortalama net" **yazılmaz**.
- **DB sorgusu:**
```sql
SELECT p.isim, COUNT(*) n,
ROUND(AVG(n25.tytTrkNet),1) tyt_trk, ROUND(AVG(n25.tytMatNet),1) tyt_mat,
ROUND(AVG(n25.aytMatNet),1) ayt_mat, ROUND(AVG(n25.aytFizNet),1) fiz,
ROUND(AVG(n25.aytBioNet),1) bio, CAST(AVG(p.sira2025) AS INT) s25
FROM netler n25 JOIN programs p ON p.id = n25.program_id
WHERE n25.yil = 2025 AND p.onlisans = 0 AND p.unitur = 'DEVLET'
GROUP BY p.isim HAVING n >= 30 ORDER BY tyt_mat DESC;
```
Kapsama kontrolü: `SELECT yil, COUNT(*) FROM netler GROUP BY yil;` → 2025'te 20.821 satır [D].
- **İç link:** `taban-puan-mi-siralama-mi`, `merkezi-yerlestirme-nasil-calisir`, `hedef-siralama-nasil-belirlenir`, `kac-siralama-ile-hangi-bolume-girebilirim`, `/bolum/tip`, `/bolum/hukuk`, `/bolum/bilgisayar-muhendisligi`
- **Not:** `netler` tablosu bugüne kadar hiçbir **yazıda** kullanılmadı (katalogdaki net modalinde kullanılıyor — `src/features/katalog/components/program-netleri.tsx`, `src/app/api/netler/route.ts` [D: `18-yazar-kac-net.md` §5.2]; planın ilk hâlindeki "hiçbir yerde kullanılmıyor" ifadesi bu ölçüde yanlıştı). geo-raporu T11 bunu "rakiplerde olmayan özgün veri" diye işaretliyor. **Bu yazı 20 konunun içindeki en büyük farklılaştırıcı.** Yazının dili modalin dilini (aynı "son yerleşen kişi" çerçevesi) bozmamalı.
- **Durum (22 Eyl 2026): YAZILDI ve doğrulandı.** `content/rehber/kac-net-ile-hangi-bolum.md`; 6 program YÖK Atlas canlı servisinden alan alan teyit edildi, 10/10 tuttu [D: `18-yazar-kac-net.md` §3]. Yayımlanan yazının kesiti `tur` filtreli (SAY / EA-SÖZ-DİL ayrı tablolar) olduğu için rakamları yukarıdaki filtresiz sorgudan ufak farkla ayrılıyor — **kanonik rakamlar yayımlanan yazıdakilerdir**; sonraki yazılar net alıntılarını oradan alsın, sorguyu yeniden yorumlamasın.
---
#### 3. `ayni-bolum-farkli-universite-siralama-farki` — **öncelik 3** · zorluk **M** · niyet **E + H**
- **Başlık:** Aynı Bölüm, Farklı Üniversite: Sıralama Farkı Ne Kadar Olabiliyor?
- **Hedef sorgular:** "aynı bölüm farklı üniversite fark eder mi", "hangi üniversitede okumak önemli mi", "psikoloji taban puanları neden bu kadar farklı"
- **İlk paragraf cevabı:** Yalnızca İstanbul'daki programlara bakmak bile yeter: 2026'da Psikoloji İstanbul'da 87 ayrı programda açıldı ve taban sıralamaları 329 ile 1.402.765 arasında değişti; İşletme'de 96 program 128 ile 1.414.685 arasına, Tıp'ta 70 program 1 ile 49.623 arasına yayıldı — yani "bölüm adı" tek başına ne okuyacağını değil, yalnızca diplomanın üstünde ne yazacağını söylüyor.
- **5 maddelik iskelet:**
1. Rakamla şok: tek şehir, tek bölüm adı, 4.000 kat sıralama farkı. Tablo hemen.
2. **Fark nereden geliyor?** devlet/vakıf ayrımı, burslu/ücretli kontenjan, öğretim dili, ikinci öğretim, yeni açılan program.
3. **Dar aralıklı bölümler** de var: Tıp 1–49.623, Elektrik-Elektronik Mühendisliği 123–281.699 — yani "her bölümde uçurum var" demek yanlış; ayrım bölümün kendisinde değil **program çeşitliliğinde**.
4. Öğrenciye ne demek: tercih listesine bölüm adı değil **program** yazılır; aynı adın 20 satırını üst üste yazmak liste yapmak değildir (→ `olu-tercih-nedir`, `tercih-listesi-nasil-yapilir`).
5. Karar sırası: bölüm → program grubu → şehir/bedel → sıralama bandı.
- **Şema:** `"X bölümünü istiyorum"` → aynı adı taşıyan kaç program var? → devlet/vakıf, dil, bedel dallanması → "listeye program yazılır, bölüm adı değil" sonucu.
- **Tablo kolonları:** bölüm · İstanbul'daki program sayısı · en düşük (en seçici) taban sırası · en yüksek taban sırası · oran (kaç kat) · bu programların devlet/vakıf dağılımı
- **DB sorgusu:**
```sql
SELECT isim, COUNT(*) n, MIN(sira2026) en_secici, MAX(sira2026) en_genis,
SUM(unitur='DEVLET') devlet
FROM programs WHERE il='İSTANBUL' AND onlisans=0 AND sira2026 IS NOT NULL
GROUP BY isim HAVING n>=8 ORDER BY (MAX(sira2026)*1.0/MIN(sira2026)) DESC;
```
Ankara (35 üniversite, 1.831 program) ve İzmir (13 / 793) için `il` değiştirilerek ikinci tablo yapılabilir [D].
- **İç link:** `bolum-mu-universite-mi-sehir-mi`, `olu-tercih-nedir`, `tercih-listesi-nasil-yapilir`, `devlet-mi-vakif-mi`, `/bolum/psikoloji`, `/bolum/isletme`, `/bolum/tip`
---
#### 4. `ogretmenlik-bolumlerine-talep-nasil-degisti` — **öncelik 4** · zorluk **M** · niyet **H + V**
- **Başlık:** Öğretmenlik Bölümlerinin Tabanı Altı Yılda Ne Oldu? Branş Branş Tablo (2021–2026)
- **Hedef sorgular:** "öğretmenlik bölümleri taban puanları düştü mü", "hangi öğretmenlik bölümü daha zor", "ilköğretim matematik öğretmenliği taban sıralaması", "öğretmenlik tercih edilmiyor mu"
- **İlk paragraf cevabı:** Öğretmenlik tek bir blok gibi hareket etmiyor: 2021'den 2026'ya İlköğretim Matematik Öğretmenliği'nin ortalama taban sırası 76 programda 83.225'ten 218.963'e, Sosyal Bilgiler Öğretmenliği'nin 64 programda 78.391'den 100.470'e gerilerken, **Özel Eğitim Öğretmenliği** 64 programda 29.431'den 19.324'e ve **Okul Öncesi Öğretmenliği** 88 programda 26.268'den 20.837'ye sıkılaştı — yani bazı branşlara talep düşerken bazıları altı yılda daha seçici hâle geldi.
- **5 maddelik iskelet:**
1. Tek cümlelik cevap + "öğretmenlik toptan düştü" cümlesinin neden yanlış olduğu (652 programda genel ortalama 60.111 → 78.498, ama dağılım iki yönlü).
2. Branş tablosu: gerileyen (İlköğretim Matematik, Sosyal Bilgiler, Türkçe, İngilizce) vs sıkılaşan (Özel Eğitim, Okul Öncesi, Sınıf).
3. **Kontenjan tarafı:** Sınıf Öğretmenliği kontenjanı 105 programda 3.578 → 3.737 artarken Sosyal Bilgiler 66 programda 2.665 → 2.121 ve Türkçe 95 programda 3.357 → 2.845 azaldı [D] — kontenjanın sıralamayı hangi yönde ittiği.
4. **Yazmayacağımız şey, açıkça:** atama kontenjanı, KPSS şansı, "hangi branş atanır" — bu veriler bizde **yok**, MEB atama sayıları ayrı bir kaynak; okuyucu MEB'in kendi duyurularına yönlendirilir [doğrulanmalı]. Vaat cümlesi kurulmaz.
5. 2027'ye hazırlanan için: branş kararını tek yılın tabanına göre verme, üç yıllık yöne ve kendi sıralama bandına bak.
- **Şema:** `Öğretmenlik istiyorum` → branş seçimi → üç yıllık yön (sıkılaşıyor / yatay / geriliyor) → "kendi bandınla kesişiyor mu" kontrolü → `hedef-siralama-nasil-belirlenir`. Atama/istihdam düğümü **yok**.
- **Tablo kolonları:** branş · program sayısı · 2021 ort. taban sırası · 2026 ort. taban sırası · yön · 2025→2026 kontenjan değişimi
- **DB sorgusu:** #1'deki sorgu, `WHERE ... AND isim LIKE '%Öğretmenliği%'`, `HAVING n>=20`. Kontenjan kolonu için:
```sql
SELECT isim, COUNT(*) n, SUM(kontenjan2025) k25, SUM(kontenjan2026) k26
FROM programs WHERE onlisans=0 AND isim LIKE '%Öğretmenliği%'
AND kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL
GROUP BY isim HAVING n>=20;
```
- **Resmî kaynak:** Branş adları ve kontenjanlar için 2026-YKS tercih kılavuzu (`cdn.osym.gov.tr/pdfdokuman/2026/YKS/TERCIH/kontkilavuz_yktd21072026.pdf` [A — yazar açıp teyit etsin]). Atama iddiası yazılmayacağı için MEB kaynağı gerekmez.
- **İç link:** #1, `hedef-siralama-nasil-belirlenir`, `bolumun-is-imkanini-nasil-arastirirsin`, `/bolum/ilkogretim-matematik-ogretmenligi`, `/bolum/ozel-egitim-ogretmenligi`, `/bolum/sinif-ogretmenligi`
- **Uyarı:** Bu konu istihdam/YMYL sınırına en yakın olanı. Yazar **tek bir** istihdam cümlesi bile kurmasın; editör bu yazıyı ayrıca okusun.
---
#### 5. `hangi-bolumlerin-kontenjani-azaldi` — **öncelik 5** · zorluk **M** · niyet **H + E**
- **Başlık:** 2026'da Hangi Bölümlerin Kontenjanı Kısıldı, Hangilerininki Arttı?
- **Hedef sorgular:** "kontenjanlar azaldı mı 2026", "hukuk kontenjanı azaldı", "yök kontenjan kısıtlaması hangi bölümler", "diş hekimliği kontenjan 2026"
- **İlk paragraf cevabı:** İki yılda da öğrenci alan lisans programlarını eşleştirdiğimizde 2025'ten 2026'ya kontenjanı en çok kısılan bölümler İngiliz Dili ve Edebiyatı (108 programda 5.029 → 3.933, −1.096), Görsel İletişim Tasarımı (97 programda 5.448 → 4.364, −1.084), Hukuk (157 programda 9.403 → 8.331, −1.072), Fizyoterapi ve Rehabilitasyon (−897) ve Diş Hekimliği (177 programda 6.481 → 5.689, −792); artan tarafta ise Siyaset Bilimi ve Kamu Yönetimi (+383), Hemşirelik (+229) ve Sınıf Öğretmenliği (+159) var.
- **5 maddelik iskelet:**
1. Cevap + yöntem: yalnızca **hem 2025 hem 2026'da kontenjanı olan** programlar; kapanan ve yeni açılan programlar (2026'da ilk kez kontenjan alan **1.208 program** [D]) bu tablonun dışında.
2. En çok kısılan 10 / en çok artan 10 tablosu.
3. **Kontenjan kısıntısı tabanı nasıl etkiler?** Arz azalınca aynı talep daha dar kapıdan geçer → taban sıralaması sıkılaşma eğilimi. Hukuk örneği: kontenjan −1.072 iken taban 105 programda 40.136 → 22.675 (altı yıllık, #1'den).
4. **Ama otomatik değil:** Diş Hekimliği'nde kontenjan −792 olmasına rağmen 181 programda 5.879 kontenjana 5.487 yerleşen var, yani bazı programlar dolmadı [D]. Kontenjan tek başına tabanı belirlemez.
5. 2027 tercihçisine: kontenjan haberlerini "fırsat/tehlike" diye değil, **arz sinyali** olarak oku; kılavuz çıkınca hedef programının kontenjanını kendin kontrol et.
- **Şema:** `Bölümün kontenjanı azaldı` → talep aynı mı / düştü mü → taban sıkılaşır / yatay kalır / program boş kalır → her uçta "2027'de ne yap" metin etiketli kutu.
- **Tablo kolonları:** bölüm · eşleşen program sayısı · 2025 kontenjan · 2026 kontenjan · fark · fark (%) · 2026 yerleşen
- **DB sorgusu:**
```sql
SELECT isim, COUNT(*) n, SUM(kontenjan2025) k25, SUM(kontenjan2026) k26,
SUM(kontenjan2026)-SUM(kontenjan2025) fark, SUM(yerlesen2026) y26
FROM programs WHERE onlisans=0
AND kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL
GROUP BY isim HAVING n>=15 ORDER BY fark ASC; -- DESC = artanlar
-- yeni açılan: WHERE kontenjan2026 IS NOT NULL AND kontenjan2025 IS NULL AND kontenjan2024 IS NULL → 1208
```
- **Resmî kaynak:** Kontenjan kararlarının gerekçesi YÖK'ün kendi duyurularında olabilir — **iddia edilmeden önce açılmalı** (`yok.gov.tr/tr/announcements`) [doğrulanmalı]. Açılamazsa yazı "YÖK'ün gerekçesi" cümlesi kurmaz, yalnızca ölçülen değişimi anlatır.
- **İç link:** #1, `bos-kontenjanlar-ne-anlatiyor`, `taban-siralamalar-nasil-degisir`, `/bolum/hukuk`, `/bolum/dis-hekimligi`, `/bolum/ingiliz-dili-ve-edebiyati`
---
#### 6. `siralama-bandina-gore-kac-secenek-var` — **öncelik 6** · zorluk **M** · niyet **E + H**
- **Başlık:** Sıralaman Kaça Kadar Kaç Kapı Açıyor? Lisans Programlarının Sıralama Haritası (2026)
- **Hedef sorgular:** "100 bin sıralama ile ne okunur", "300 bin sıralama ile hangi bölümler", "sıralamama göre kaç seçeneğim var", "düşük sıralama ile lisans"
- **İlk paragraf cevabı:** 2026 verisine göre ilk 1.000 sıralamanın açtığı lisans programı sayısı 64, ilk 5.000'in 276, ilk 10.000'in 516, ilk 50.000'in 2.104, ilk 100.000'in 3.361, ilk 250.000'in 6.272 ve ilk 500.000'in 8.201 — yani seçenek sayısı sıralamayla doğrusal değil, **basamaklı** artıyor ve asıl sıçrama 50.000 ile 250.000 arasında yaşanıyor.
- **5 maddelik iskelet:**
1. Cevap + haritanın okunuşu: "kaç seçeneğim var" ile "hangi bölüme girerim" farklı sorular; ikincisi için mevcut `kac-siralama-ile-hangi-bolume-girebilirim` yazısı (link **ilk 200 kelimede zorunlu**).
2. Bant tablosu + kümülatif eğrinin anlamı: 10.000 ile 50.000 arasında seçenek 4 katına çıkıyor.
3. **300.000–800.000 bandı:** bu aralıkta 2.322 lisans programı var, 1.739'u devlet, 434'ü vakıf, 135'i KKTC [D]. "Sıralamam kötü, lisans okuyamam" cümlesinin rakamla yanlışlanması — bu yazının duygusal çekirdeği.
4. Önlisans katmanı: 9.254 önlisans programı ve 354.627 yerleşen [D] — bant haritasının ikinci katı (→ #20).
5. Kendi bandını bulma: deneme sıralaması → bant → hayal/dengeli/**güvenli** üçlüsü (görünen etiket "Güvenli") → sıra formu.
- **Şema:** Sıralama ekseninde basamaklı bir karar akışı: `Sıralaman hangi bantta?` → beş bant düğümü → her bandın altında "kaç lisans + kaç önlisans programı" ve "listeni nasıl kur" çıkışı. Renkler **metin etiketiyle** birlikte.
- **Tablo kolonları:** sıralama bandı (≤1.000 … ≤500.000) · o banda kadar açılan lisans programı sayısı · bir önceki banda göre artış · devlet payı · vakıf payı
- **DB sorgusu:**
```sql
SELECT '1k' bant, COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=1000
UNION ALL SELECT '5k', COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=5000
UNION ALL SELECT '10k', COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=10000
UNION ALL SELECT '50k', COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=50000
UNION ALL SELECT '100k',COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=100000
UNION ALL SELECT '250k',COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=250000
UNION ALL SELECT '500k',COUNT(*) FROM programs WHERE onlisans=0 AND sira2026<=500000;
-- alt bant: WHERE onlisans=0 AND sira2026 BETWEEN 300000 AND 800000 → 2322
```
- **İç link:** `kac-siralama-ile-hangi-bolume-girebilirim` (zorunlu, girişte), `hedef-siralama-nasil-belirlenir`, `taban-puan-mi-siralama-mi`, `onlisans-mi-lisans-mi`, `/bolumler`
- **Not:** geo-raporu T12 (`/siralama/[bant]` sayfaları) için talep kanıtı ve prototipi; AI gösteriminde 1 numaralı sayfa tam bu niyette [D]. **Kanibalizasyon riski en yüksek konu — editör zorunlu.**
---
### Dalga B — 2027'ye hazırlananlar (öncelik 7–10)
---
#### 7. `puan-turu-nasil-secilir` — **öncelik 7** · zorluk **M** · niyet **H**
- **Başlık:** Sayısal mı, Eşit Ağırlık mı, Sözel mi, Dil mi? Puan Türü Kararını Neye Göre Vermelisin?
- **Hedef sorgular:** "hangi puan türünü seçmeliyim", "eşit ağırlık mı sayısal mı", "puan türü değiştirmek", "sayısaldan eşit ağırlığa geçmek"
- **İlk paragraf cevabı:** Puan türü kararı "hangi dersler bana kolay geliyor" sorusundan önce **"o puan türünde kaç kapı var"** sorusuyla verilir: 2026'da sayısal puanıyla öğrenci alan 5.744 program, eşit ağırlıkla 3.900, sözelle 1.914, dille 681 ve TYT ile (önlisans) 9.254 program vardı — yani puan türü değiştirmek sadece ders programını değil, önüne açılan program havuzunun büyüklüğünü de değiştiriyor.
- **5 maddelik iskelet:**
1. Cevap + arz tablosu (puan türü başına program sayısı, kontenjan, yerleşen).
2. **Karar sırası:** önce hedef bölüm(ler) → onların puan türü → ders yükü. Tersi (önce ders kolaylığı) yaygın hata.
3. **Geçiş maliyeti:** 11. sınıfta tür değiştirmenin ders açığı, 12'de değiştirmenin maliyeti; hangi noktadan sonra geri dönüşü zor (genelleme değil, kendi okulunun ders programına bakma yönergesi).
4. **Ortak bölümler:** birden fazla puan türünden öğrenci alan bölüm adları ve bunun ne anlama geldiği.
5. Kendi hedefini test et: bölüm sayfasındaki puan türü kolonunu oku → `/bolumler`.
- **Şema:** `Hangi bölümü istiyorum?` → bölümün puan türü → "o türde şu kadar program var" → ders yükü karşılaştırma → karar. "Kolay tür" düğümü **yok** (yanlış modeli beslememek için).
- **Tablo kolonları:** puan türü · program sayısı (2026) · taban sırası açıklanan program sayısı · toplam kontenjan · toplam yerleşen · örnek 5 bölüm
- **DB sorgusu:**
```sql
SELECT tur, COUNT(*) prog, SUM(sira2026 IS NOT NULL) tabani_var,
SUM(kontenjan2026) kont, SUM(yerlesen2026) yer
FROM programs GROUP BY tur ORDER BY prog DESC;
-- SAYISAL 5744 / EŞİT AĞIRLIK 3900 / SÖZEL 1914 / DİL 681 / TYT 9254 [D]
```
- **Resmî kaynak:** Puan türü tanımları ve ders/katsayı yapısı için 2026-YKS kılavuzu [doğrulanmalı]; 2027 için değişiklik iddiası **yazılmaz** (takvim/kılavuz yok).
- **İç link:** `merkezi-yerlestirme-nasil-calisir`, `onlisans-mi-lisans-mi`, `hedef-siralama-nasil-belirlenir`, #9, `/bolumler`
---
#### 8. `on-bir-sinifta-tercih-hazirligi` — **öncelik 8** · zorluk **M** · niyet **H + V**
- **Başlık:** 11. Sınıfta Tercih İçin Ne Yapılır? Sınav Yılından Önce Verilecek Beş Karar
- **Hedef sorgular:** "11. sınıfta ne yapmalıyım yks", "tercih hazırlığı ne zaman başlar", "11. sınıf bölüm seçimi", "üniversite bölümü nasıl seçilir lise"
- **İlk paragraf cevabı:** 11. sınıfta verilecek şey tercih listesi değil **beş karar**: puan türü, hedef bölüm ailesi (tek bölüm değil), şehir/bedel sınırı, hedef sıralama bandı ve "bu hedef gerçekçi mi" ölçümü — tercih listesi bunların üstüne 12. sınıfın yazında bir haftada kurulur, tersi olmaz.
- **5 maddelik iskelet:**
1. Cevap + "tercih dönemi iki haftadır ama karar bir yıl sürer" çerçevesi.
2. **Karar 1–2:** puan türü (→ #7) ve tek bölüm yerine **bölüm ailesi** (3–5 yakın bölüm) belirleme; tek bölüme kilitlenmenin riski.
3. **Karar 3:** bedel ve şehir sınırının **ailede** konuşulması — burada veliyle konuşma yazısına köprü (#16, `veliler-icin-tercih-rehberi`).
4. **Karar 4–5:** hedef sıralama bandı ve deneme sıralamasıyla ölçüm; bandın altında kalırsan ne değişir (→ #6, `hedef-siralama-nasil-belirlenir`).
5. **Ne yapılmaz:** taban puan listesi ezberlemek, "şu bölüm tutar" tahminleri, sınav takvimi açıklanmadan tarih planı yapmak (ÖSYM 2027 takvimi henüz yok [A]).
- **Şema:** Zaman ekseni yerine karar zinciri: `Puan türü` → `Bölüm ailesi` → `Bedel/şehir sınırı` → `Hedef band` → `Ölçüm (deneme)` → geri besleme oku (ölçüm bandı tutmuyorsa bölüm ailesine dön).
- **Tablo kolonları:** karar · ne zaman verilir · kim karar verir (öğrenci / birlikte / veli) · nereye bakılır · ertelenirse ne olur
- **Kaynak:** DB gerekmez; #6 ve #7'den rakam alıntılanır. Tarih iddiası yok → takvim bağımlılığı **yok** (bilerek).
- **İç link:** #6, #7, `hedef-siralama-nasil-belirlenir`, `bolum-mu-universite-mi-sehir-mi`, `bolumun-is-imkanini-nasil-arastirirsin`, `veliler-icin-tercih-rehberi`
---
#### 9. `dil-puaniyla-hangi-bolumler-var` — **öncelik 9** · zorluk **S** · niyet **H + E**
- **Başlık:** Dil Puanıyla Hangi Bölümler Okunur? YDT'nin Açtığı Programların Tam Tablosu (2026)
- **Hedef sorgular:** "dil puanıyla hangi bölümler", "ydt ile ne okunur", "mütercim tercümanlık taban sıralaması", "dil bölümleri taban puanları"
- **İlk paragraf cevabı:** 2026'da dil puan türüyle öğrenci alan toplam 681 program vardı; lisans tarafında devlet üniversitelerinde 431 program 17.280 kontenjanla 17.797 öğrenci aldı, vakıf üniversitelerinde 209 program 4.360 kontenjana karşılık 3.268 öğrenci aldı, KKTC'de ise 35 programın 659 kontenjanının 467'si doldu — yani dil puanı, en küçük ama **devlet tarafında doluluğu en yüksek** havuzlardan biri.
- **5 maddelik iskelet:**
1. Cevap + havuzun büyüklüğü. "Az program var" endişesine karşı: az program, ama devlet tarafında kontenjanı aşan yerleşme.
2. Bölüm aileleri: öğretmenlik (İngilizce Öğretmenliği), mütercim-tercümanlık, dil-edebiyat, dilbilim, bölge/kültür programları — her ailenin taban aralığı.
3. **Dil puanıyla okunan bölümler ne iş yapar?** — istihdam vaadi yok, `bolumun-is-imkanini-nasil-arastirirsin` yöntemine köprü.
4. Altı yıllık yön: İngilizce Öğretmenliği 89 programda 19.667 → 24.946, İngilizce Mütercim ve Tercümanlık 37 programda 18.931 → 21.478 [D, #1 sorgusu] — hafif gevşeme, ama ikisi de hâlâ ilk 25.000 bandında.
5. Karar: dil puanını tek başına mı çalışacaksın, ikinci tür de var mı; havuz dar olduğu için liste kurarken kaç satır doldurabilirsin.
- **Şema:** `Dil puanı çalışıyorum` → bölüm ailesi seçimi (4 dal) → devlet/vakıf → "bu ailede kaç program var, tabanı nerede" → liste kurma uyarısı (havuz dar → `olu-tercih-nedir`).
- **Tablo kolonları:** bölüm ailesi · program sayısı · devlet/vakıf dağılımı · en seçici taban sırası · medyan taban sırası · 2026 kontenjan · 2026 yerleşen
- **DB sorgusu:**
```sql
SELECT unitur, COUNT(*) prog, SUM(kontenjan2026) k, SUM(yerlesen2026) y
FROM programs WHERE tur='DİL' AND onlisans=0 GROUP BY unitur;
SELECT isim, COUNT(*) n, MIN(sira2026) en_secici, CAST(AVG(sira2026) AS INT) ort,
SUM(kontenjan2026) k, SUM(yerlesen2026) y
FROM programs WHERE tur='DİL' AND onlisans=0 GROUP BY isim ORDER BY n DESC;
```
- **İç link:** #7, `hazirlik-sinifi-ve-ogretim-dili`, `olu-tercih-nedir`, `bolumun-is-imkanini-nasil-arastirirsin`, `/bolumler`
- **Not:** Dar niş, düşük rekabet, **S zorlukta**; yeni bir yazara ilk iş olarak verilebilir.
---
#### 10. `psikoloji-okumak-2026-tablosu` — **öncelik 10** · zorluk **M** · niyet **H + E**
- **Başlık:** Psikoloji Okumak: Programlar, Taban Aralığı ve Altı Yılda Değişen Tablo
- **Hedef sorgular:** "psikoloji taban puanları", "psikoloji okumak mantıklı mı", "psikoloji bölümü kaç sıralama", "psikoloji taban puanı neden düştü"
- **İlk paragraf cevabı:** Psikoloji 2026'da yüzlerce programda açıldı ve altı yılda ortalama taban sırası 184 programda 152.325'ten 270.358'e geriledi; ama bu gerileme bölümün "değersizleşmesi" değil arzın büyümesi: yalnızca İstanbul'da 87 farklı Psikoloji programı var ve bunların taban sıralaması 329 ile 1.402.765 arasında değişiyor — yani "Psikoloji'nin tabanı" diye tek bir rakam yok.
- **5 maddelik iskelet:**
1. Cevap + "tek taban yok" tezi (İstanbul aralığı, #3'ten).
2. Altı yıllık yön tablosu ve gerilemenin nedeni: program sayısı ve kontenjan artışı (#1 ve #5'e link, rakam **yeniden hesaplanmaz**).
3. **Devlet / vakıf / bedel katmanı:** aynı ad altında çok farklı programlar; okuyucu bölüm sayfasındaki program listesini nasıl okur.
4. **Ne okunuyor, ne okunmuyor:** ders içeriği hakkında genel bilgi + "klinik psikolog olmak lisansla olmaz, lisansüstü gerekir" gibi iddialar **yalnızca** YÖK/ilgili mevzuat kaynağı açılabilirse yazılır [doğrulanmalı]; açılamazsa bölüm bu yazıdan çıkar.
5. Kendi sıralamanla Psikoloji: hangi bantta hangi program grubu → `/bolum/psikoloji` + sıra formu.
- **Şema:** `Psikoloji istiyorum` → devlet / vakıf-burslu / vakıf-ücretli dalları → her dalda taban bandı ve 4 yıllık bedel sorusu → "listeye hangi programları yazarım".
- **Tablo kolonları:** kesit (devlet / vakıf / KKTC) · program sayısı · en seçici taban sırası · medyan · en geniş · 2026 kontenjan · 2026 yerleşen
- **DB sorgusu:**
```sql
SELECT unitur, COUNT(*) n, MIN(sira2026) en_secici, CAST(AVG(sira2026) AS INT) ort,
MAX(sira2026) en_genis, SUM(kontenjan2026) k, SUM(yerlesen2026) y
FROM programs WHERE isim LIKE 'Psikoloji%' AND onlisans=0 GROUP BY unitur;
```
- **İç link:** #1, #3, #5, `/bolum/psikoloji`, `devlet-mi-vakif-mi`, `bolumun-is-imkanini-nasil-arastirirsin`
- **Not:** Bu yazı **şablondur.** Aynı iskelet sonraki turlarda Hemşirelik (`/bolum/hemsirelik` organik giriş alıyor [D: 05-seo-plan §3]), Beslenme ve Diyetetik, Moleküler Biyoloji ve Genetik için tekrarlanabilir. Aynı anda birden fazla bölüm yazısı yazılacaksa **önce bu bitsin**, diğerleri onu kopyalasın.
---
### Dalga C — Yeni yerleşmiş 1. sınıf (öncelik 11–14)
---
#### 11. `bolumumu-sevmedim-hangi-kapilar-var` — **öncelik 11** · zorluk **M** (kısa yazı) · niyet **B**
- **Başlık:** Bölümümü Sevmedim: Önümde Hangi Kapılar Var? (Karar Şeması)
- **Hedef sorgular:** "bölümümü sevmedim ne yapmalıyım", "üniversitede bölüm değiştirme", "okuduğum bölümü bırakmalı mıyım", "1. sınıfta bölüm değiştirme"
- **İlk paragraf cevabı:** Okuduğun bölümden memnun değilsen önünde birbirinden çok farklı beş kapı var — kurum içi/kurumlar arası yatay geçiş, merkezi yerleştirme puanıyla yatay geçiş (Ek Madde-1), çift anadal/yandal, kayıt dondurup ya da kayıtlı kalıp sınava tekrar girmek, ve önlisanstaysan DGS — ve hangisinin sana uyduğu tek bir şeye bağlı: **not ortalaman mı yoksa sınav sıralaman mı daha güçlü.**
- **5 maddelik iskelet:**
1. Cevap + "acele etme, ilk dönemi bitir" uyarısı (ders kaydı/danışman penceresi için bu gece yazılan ilk hafta yazısına link).
2. **Beş kapının tek cümlelik tanımı** ve her birinde neye bakıldığı (AGNO mu, merkezi puan mı, sınav sıralaması mı).
3. **Karar sorusu:** not ortalaman güçlüyse yatay geçiş/ÇAP; merkezi puanın hedef programın o yılki tabanının üstündeyse Ek Madde-1; ikisi de değilse sınav.
4. **Bu yazı detay vermez** — her kapı için mevcut yazıya yönlendirir: `yatay-gecis-cap-yandal`, `universite-okurken-tekrar-yks`, `mezuna-kalmak-mi-kayit-olmak-mi`, bu gece yazılan `ek-madde-1-puanim-yetiyor-mu` ve #12 (DGS).
5. Kapılardan hiçbiri uymuyorsa: bölümü tanımaya bir dönem daha verme; hangi dersler/staj/kulüp kararı değiştirir.
- **Şema:** Bu yazının **asıl ürünü şema.** `Bölümümden memnun değilim` → ilk soru: önlisans mı lisans mı → ikinci soru: notum mu güçlü, merkezi puanım mı, sınav sıralamam mı → beş çıkış düğümü, her biri bir mevcut yazıya karşılık geliyor. Metin etiketli, renk tek başına anlam taşımıyor.
- **Tablo kolonları:** kapı · neye bakılır (AGNO / merkezi puan / yeni sınav) · ne zaman başvurulur · ne kaybedersin · hangi yazıda anlatılıyor
- **Kaynak:** DB gerekmez. Başvuru pencereleri için genel tarih **yazılmaz** ("üniversitenin akademik takvimine bak"); yalnızca mevzuatın adı verilir [doğrulanmalı: Yükseköğretim Kurumlarında Önlisans ve Lisans Düzeyindeki Programlar Arasında Geçiş… Yönetmeliği].
- **İç link:** yukarıdaki beş yazı + `onlisans-mi-lisans-mi`
- **Not:** Hub yazısı. **600 kelimeyi geçmesin**, yoksa dört yazıyı birden kanibalize eder. Editör uzunluğu denetlesin.
---
#### 12. `onlisanstan-lisansa-dgs-yol-haritasi` — **öncelik 12** · zorluk **M** · niyet **B + E**
- **Başlık:** Önlisanstan Lisansa Geçiş (DGS): Yol Haritası ve Hangi Bölüm Nereye Bağlanıyor?
- **Hedef sorgular:** "dgs nedir nasıl yapılır", "dgs ile hangi bölümlere geçilir", "önlisanstan lisansa geçiş", "dgs ne zaman başvuru"
- **İlk paragraf cevabı:** 2026'da önlisans programlarına 354.627 öğrenci yerleşti ve bunların lisansa geçmek için kullanacağı yol Dikey Geçiş Sınavı (DGS); DGS'de hangi lisans programına başvurabileceğini **kendi önlisans programının adı** belirliyor, yani geçiş hakkın bölüm seçtiğin gün büyük ölçüde belirlenmiş oluyor.
- **5 maddelik iskelet:**
1. Cevap + ölçek: 9.254 önlisans programı, 354.627 yerleşen [D]. Yani her yıl üniversiteye yerleşenlerin çok büyük bir kısmı önlisansta.
2. **DGS nasıl işler:** sınav içeriği, ÖSYM'nin yayımladığı önlisans programı → lisans programı eşleştirme tablosu, kontenjan mantığı — **tamamı ÖSYM DGS kılavuzundan** [doğrulanmalı: kılavuz yazım anında açılacak].
3. **En çok yerleşilen önlisans programları** (Bilgisayar Programcılığı 333 programda 24.995 yerleşen, İlk ve Acil Yardım 235/7.016, Muhasebe ve Vergi Uygulamaları 224/6.866, Lojistik 119/6.679 [D]) ve bunların tipik DGS bağlantıları (eşleştirme yalnızca kılavuzdan yazılır, tahmin yok).
4. **Ne zaman ne yapılır:** 1. sınıfta AGNO, 2. sınıfta DGS hazırlığı; intibak/ders saydırma gerçeği (genelleme yok, üniversitenin yönetmeliği).
5. DGS mi, yeniden YKS mi? Karşılaştırma → `universite-okurken-tekrar-yks`, #11.
- **Şema:** `Önlisandayım, lisans istiyorum` → iki yol (DGS / yeniden YKS) → DGS dalında: önlisans programın hangi lisanslara bağlanıyor → kontenjan var mı → intibak → giriş. Diğer dalda mevcut yazıya çıkış.
- **Tablo kolonları:** önlisans programı · program sayısı · 2026 yerleşen · tipik DGS bağlantısı (kılavuzdan) · not
- **DB sorgusu:**
```sql
SELECT isim, COUNT(*) n, SUM(kontenjan2026) k, SUM(yerlesen2026) y
FROM programs WHERE onlisans=1 GROUP BY isim HAVING n>=40 ORDER BY y DESC LIMIT 20;
SELECT COUNT(*), SUM(yerlesen2026) FROM programs WHERE onlisans=1; -- 9254 / 354627
```
- **Resmî kaynak:** ÖSYM DGS kılavuzu ve eşleştirme tablosu (`osym.gov.tr` → DGS) [doğrulanmalı — **eşleştirme tablosu açılamazsa o bölüm yazılmaz**, yazı DGS mekaniğiyle sınırlı kalır]. DGS 2027 **tarihi yazılmaz** (takvim yok).
- **İç link:** #11, #20, `onlisans-mi-lisans-mi`, `universite-okurken-tekrar-yks`, `yatay-gecis-cap-yandal`
---
#### 13. `birinci-sinifta-ders-secimi-agno-ve-butunleme` — **öncelik 13** · zorluk **M** · niyet **B**
- **Başlık:** Üniversitede Not Sistemi: AGNO, Kredi, Bütünleme ve Ders Seçimi Nasıl İşler?
- **Hedef sorgular:** "agno nedir nasıl hesaplanır", "üniversitede bütünleme nedir", "akts kredi nedir", "üniversitede dersten kalmak ne olur"
- **İlk paragraf cevabı:** Üniversitede notun tek bir ortalamaya değil iki ortalamaya işler — dönem not ortalaman (DNO) ve genel ağırlıklı not ortalaman (AGNO) — ve AGNO yalnızca mezuniyet için değil, yatay geçiş, çift anadal, burs devamı ve bazı üniversitelerde ders yükü hakkı için de kullanılan **en önemli sayıdır**; bu yüzden birinci sınıfın ilk döneminde alınan kararlar dört yıl boyunca taşınır.
- **5 maddelik iskelet:**
1. Cevap + "AGNO neden bu kadar önemli" (yatay geçiş, ÇAP, burs — #11'e köprü).
2. **AKTS/kredi ve ders yükü:** zorunlu-seçmeli ayrımı, ön koşullu ders, danışman onayı.
3. **Harf notu, bütünleme, dersten kalmak:** mekanik anlatılır ama **rakam verilmez** — her üniversitenin yönetmeliği farklı, okuyucu kendi yönetmeliğine yönlendirilir. Bu yazının dürüstlük ekseni bu.
4. **Birinci sınıfta üç yaygın hata:** ilk dönem aşırı ders alma, danışman onayını atlama, "sonra telafi ederim" varsayımı (AGNO'nun geri toplanma zorluğu, aritmetikle).
5. AGNO hedefi belirleme: hangi kapı (yatay geçiş / ÇAP / burs) hangi ortalamayı ister → kendi yönetmeliğinden kontrol listesi.
- **Şema:** `Dönem başı` → ders seçimi → danışman onayı → dönem sonu → geçti/kaldı → bütünleme → AGNO'ya etkisi → (AGNO hedefin altındaysa) `sonraki dönem ders yükü` geri besleme oku.
- **Tablo kolonları:** terim · ne demek · nerede karşına çıkar · nereden öğrenirsin (kaynak) · atlarsan ne olur
- **Kaynak:** DB yok. Kaynak: 2–3 farklı üniversitenin önlisans/lisans eğitim-öğretim yönetmeliği (birbirinden farklı olduklarını göstermek için **bilerek farklı** üniversiteler) + YÖK'ün ilgili çerçeve mevzuatı [doğrulanmalı]. **Genelleme cümlesi kurulmaz.**
- **İç link:** bu gece yazılan `universitede-ilk-hafta-...`, #11, `yatay-gecis-cap-yandal`, #14
- **Not:** Ürün bağı zayıf (sihirbaza taşımaz); değeri **marka ve yıl boyu trafik**. CTA yumuşak: "kardeşin/arkadaşın tercih yapacaksa".
---
#### 14. `kyk-disinda-burs-ve-destek-haritasi` — **öncelik 14** · zorluk **M** · niyet **B + V**
- **Başlık:** KYK Dışında Hangi Burslar Var? Üniversite Öğrencisi İçin Destek Haritası
- **Hedef sorgular:** "kyk dışında burs veren kurumlar", "üniversite bursu nasıl alınır", "belediye öğrenci bursu", "vakıf bursları başvuru"
- **İlk paragraf cevabı:** KYK burs/kredisi tek kanal değil: üniversitenin kendi başarı ve ihtiyaç bursları, belediyelerin öğrenci destekleri, vakıf ve dernek bursları, meslek odaları ile şirket bursları ayrı ayrı başvuru gerektiren dört farklı kanal — ve çoğu **KYK ile birlikte alınabiliyor**, bu da "bir yere başvurdum, yeter" varsayımını en pahalı hata hâline getiriyor.
- **5 maddelik iskelet:**
1. Cevap + dört kanalın haritası; KYK bölümü **tek paragraf** + bu gece yazılan `kyk-burs-mu-kredi-mi` yazısına link.
2. **Üniversitenin kendi bursları:** başarı bursu, ihtiyaç bursu, kısmi zamanlı öğrenci çalışması — nereden öğrenilir (SKS/Sağlık Kültür Spor daire başkanlığı sayfası), ne zaman açılır.
3. **Belediye ve vakıf bursları:** başvuru belgeleri ortak paydası, "burs bulma" sitelerine karşı uyarı (ücret isteyen aracı = alarm).
4. **Dolandırıcılık ve veri güvenliği:** hiçbir burs başvurusu ön ödeme istemez; e-Devlet dışında kimlik/IBAN paylaşımı. (Güven içeriği — marka için değerli.)
5. **Tek sayfalık takip listesi:** kanal × başvuru dönemi × belge × durum — okuyucunun kopyalayacağı tablo.
- **Şema:** `Burs arıyorum` → dört kanal dalı → her dalda "nereden öğrenilir / ne zaman açılır / birlikte alınır mı" → uyarı düğümü (ücret isteyen aracı). Metin etiketli.
- **Tablo kolonları:** kanal · kim veriyor · tipik başvuru dönemi · gereken belge · KYK ile birlikte alınabilir mi · kaynak
- **Kaynak:** DB yok. **Tarih yazılmaz** (GSB 2026-27 dönemini duyurmadı [A]); "tipik dönem" kolonu yerine "üniversitenin/belediyenin kendi duyurusuna bak" yönergesi. Kurum adı verilecekse **yalnızca kendi resmî sayfasından** teyitle [doğrulanmalı].
- **İç link:** `kyk-burs-mu-kredi-mi`, `yurt-burs-ve-yillik-maliyet`, `devlet-mi-vakif-mi`, #13
- **Not:** Bu yazı **kurum adı listesi yayımlamamalı** (liste eskir, yanlış bilgi riski yüksek). Kanal ve yöntem anlatılır, kaynak gösterilir.
---
### Dalga D — Veli ve rehber öğretmen (öncelik 15–18). Ayrı dağıtım kanalı.
---
#### 15. `veliler-icin-taban-siralama-okuma-kilavuzu` — **öncelik 15** · zorluk **M** · niyet **V**
- **Başlık:** Veliler İçin: Çocuğunuzun Sıralaması Ne Anlama Geliyor?
- **Hedef sorgular:** "başarı sırası nedir veli", "taban puan nasıl okunur", "çocuğumun sıralaması yeterli mi", "puan mı sıralama mı önemli"
- **İlk paragraf cevabı:** Tercih konuşmasında evde en çok karışan iki şey puan ile sıralama: **puan yıldan yıla karşılaştırılamaz, sıralama karşılaştırılabilir** — bu yüzden "geçen sene 400 puanla giriliyordu" cümlesi bir şey ifade etmezken "geçen sene 120.000. sıraya kadar alıyordu" cümlesi gerçek bir ölçüdür.
- **5 maddelik iskelet:**
1. Cevap: puan vs sıralama, tek paragrafta, örnekle. (→ `taban-puan-mi-siralama-mi`)
2. **Taban sırası ne değildir:** garanti değil, geçen yılın sonucudur; kontenjan ve talep değişince oynar (→ #1, #5; rakam **tekrarlanmaz**, tek örnek yeter).
3. **"Aynı bölümün tabanı neden bu kadar farklı?"** — velinin en sık takıldığı yer; tek örnekle (İstanbul'da Psikoloji 329–1.402.765) ve #3'e link.
4. **Veli olarak neyi sorabilirsin:** "bu satır hangi bantta?", "bu liste hayal/dengeli/güvenli olarak dengeli mi?", "bedeli dört yıl taşıyabilir miyiz?" — üç soru, üçü de listeyi ele geçirmeden.
5. **Nerede durulur:** listeyi doldurmak, sıralamayı değiştirmek velinin işi değil (→ `veliler-icin-tercih-rehberi`).
- **Şema:** `Elimde bir sıralama var` → puan mı sıralama mı → geçen yılın tabanıyla karşılaştırma → üç bant (hayal / dengeli / **Güvenli**) → "listeye kim karar verir" düğümü. Renk + metin etiketi.
- **Tablo kolonları:** veli sorusu · yanlış cevap · doğru cevap · nereye bakılır
- **Kaynak:** DB rakamı #1/#3'ten alıntı (yeniden hesaplanmaz). Yeni sorgu gerekmez → **zorluk düşük, değer yüksek**.
- **`netler` çerçevesi (DÜZELTME, 22 Eyl 2026 · CEO §C5 · A6):** Bu yazı #2'den **tek bir net örneği** alacaksa, örnek "yerleşenlerin ortalama neti" diye **tanıtılamaz** — doğru ibare **"o programa 2025'te en son yerleşen kişinin netleri"**, yıl etiketiyle (§0 `netler` kuralı). Veliye söylenecek cümle: "bu rakam sınıfın ortalaması değil, kapıdan en son giren kişinin karnesi; bu yüzden hedef değil, ölçü." Alıntı yapılacak kanonik kaynak `content/rehber/kac-net-ile-hangi-bolum.md`.
- **İç link:** `taban-puan-mi-siralama-mi`, `veliler-icin-tercih-rehberi`, #1, #2, #3, `hedef-siralama-nasil-belirlenir`
- **Not:** Dil tamamen veli diliyle; "sen" değil "çocuğunuz". Ürün CTA'sı sonda, vaatsiz.
---
#### 16. `cocugum-bir-yil-daha-istiyor-veli-rehberi` — **öncelik 16** · zorluk **M** · niyet **V**
- **Başlık:** Çocuğum "Bir Yıl Daha" Diyor: Veli Olarak Neye Bakmalı?
- **Hedef sorgular:** "çocuğum sınava tekrar girmek istiyor", "mezun olarak bir yıl daha hazırlanmak", "üniversiteye kayıt olmalı mı yoksa beklemeli mi", "oğlum bölümü beğenmedi"
- **İlk paragraf cevabı:** "Bir yıl daha" kararı tek bir karar değil üç ayrı karardır — kayıt yaptırılacak mı (yerleştikten sonra kayıt yaptırmanın gelecek yılki ortaöğretim başarı puanı katsayısına etkisi var), hazırlık nasıl yapılacak ve bu yılın maliyeti nedir — ve bunların ikisi veliyle, biri tamamen çocuğunuzla ilgilidir.
- **5 maddelik iskelet:**
1. Cevap + üç karara ayırma. "Kayıt yaptırma" tarafının mekaniği burada **anlatılmaz**, `mezuna-kalmak-mi-kayit-olmak-mi` yazısına gönderilir (kırık OBP tek cümleyle tanıtılır, hesap yapılmaz).
2. **Veli tarafındaki gerçek sorular:** bir yılın maliyeti (kurs/kaynak/barınma), ailenin diğer çocuklarına etkisi, "ikinci yıl da olmazsa" planı.
3. **Motivasyon mu, kaçış mı?** — ayırt edici sorular (hangi bölüme, neden, geçen yıl neyi değiştirecek). Tanı koymaya çalışmadan, sorularla.
4. **Üçüncü yol:** kayıtlı kalıp okurken hazırlanmak; kimin için işe yarar, kimin için yaramaz (→ `universite-okurken-tekrar-yks`).
5. **Karara nasıl varılır:** bu üç seçeneği yazılı karşılaştırma tablosu; kararı verenin çocuk, maliyeti taşıyanın aile olduğu çerçevesi.
- **Şema:** `"Bir yıl daha istiyorum"` → yerleşti mi / yerleşemedi mi → kayıt yaptır / yaptırma / kayıtlı oku dalları → her dalda "veli neyi taşıyor, öğrenci neyi taşıyor" → ortak karar düğümü.
- **Tablo kolonları:** seçenek · öğrenci için ne değişir · aile için maliyet · geri dönüşü var mı · hangi yazıda anlatılıyor
- **Kaynak:** DB yok. OBP/katsayı iddiası **yalnızca** ÖSYM kılavuzundan, tek cümle, kaynak linkiyle [doğrulanmalı — kılavuzun ilgili maddesi açılacak].
- **İç link:** `mezuna-kalmak-mi-kayit-olmak-mi`, `universite-okurken-tekrar-yks`, `yerlesemedim-ne-yapmaliyim`, `veliler-icin-tercih-rehberi`, #11
- **Not:** Duygusal yük yüksek; yazar tanı/teşvik dili kullanmasın ("bırakmalı", "devam etmeli" **yok**). Editör tonu denetlesin.
---
#### 17. `rehber-ogretmenler-icin-veri-kaynaklari` — **öncelik 17** · zorluk **M** · niyet **V**
- **Başlık:** Rehber Öğretmenler İçin: Tercih Verisi Nereden Alınır, Hangi Rakam Neyi Söyler?
- **Hedef sorgular:** "rehber öğretmen tercih sunumu", "yök atlas nasıl kullanılır rehber öğretmen", "taban puan verisi nereden alınır", "tercih semineri içeriği"
- **İlk paragraf cevabı:** Tercih döneminde sınıfa gösterilen her rakamın tek bir sahibi olmalı — kontenjan ve koşullar **ÖSYM tercih kılavuzundan**, taban puan/başarı sırası **ÖSYM yerleştirme sonuçları ve YÖK Atlas'tan**, yerleşen/kontenjan toplamları **ÖSYM'nin sayısal bilgiler belgesinden** gelir; aracı sitelerin tablosu bu üç kaynaktan türetilmiş olabilir ama hangi yılın verisi olduğunu ve nasıl yuvarlandığını çoğu yazmaz.
- **5 maddelik iskelet:**
1. Cevap + üç birincil kaynağın adı, ne verdiği, ne vermediği.
2. **Rakam tuzakları:** "taban puan" ile "başarı sırası" karışması; yılı yazılmamış tablo; yerleşen sayısının kontenjanı aşması (ek kontenjanlar) [D: bu durum bizim veride de var]; aynı bölüm adının onlarca programı.
3. **Sınıfa ne anlatılır:** sıralama bandı mantığı, hayal/dengeli/**Güvenli** dağılımı, "tek bölüme kilitlenme" uyarısı. Sunumda kullanılabilir 5 slaytlık iskelet.
4. **Öğrenciye verilecek kontrol listesi:** her satır için "hangi yıl, hangi program, hangi bedel" üçlüsü.
5. **Bizim verimizi nasıl kullanırsınız:** hangi sayfada ne var, veri tarihi (21 Eylül 2026), hata bildirimi nereden. Atıf/link verilmesini açıkça rica eden kapanış — bu yazı aynı zamanda **bağlantı kazanma** aracı.
- **Şema:** `Sınıfa bir rakam göstereceğim` → hangi tür rakam (kontenjan / taban sırası / toplam) → hangi birincil kaynak → "yıl ve program adı yazıldı mı?" kontrolü → sunuma girer / girmez.
- **Tablo kolonları:** rakam türü · birincil kaynak · güncellenme zamanı · sık yapılan hata · sınıfta nasıl söylenir
- **Kaynak:** ÖSYM tercih kılavuzu, ÖSYM yerleştirme sonuçlarına ilişkin sayısal bilgiler, YÖK Atlas — **üçü de yazım anında açılıp erişim tarihiyle yazılacak** [doğrulanmalı].
- **İç link:** `tercih-robotu-nedir-yok-atlas-nasil-kullanilir`, `taban-puan-mi-siralama-mi`, `merkezi-yerlestirme-nasil-calisir`, #1, #6, `/bolumler`, `/universiteler`
- **Not:** Dağıtım değeri trafikten büyük: rehberlik servisleri ve il MEM sayfaları bu tür sayfalara link verir. `marka` ajanının rehber öğretmen kanalı işiyle birlikte değerlendirilsin.
---
#### 18. `kendi-sehrinde-okumak-il-il-universite-haritasi` — **öncelik 18** · zorluk **L** · niyet **V + H**
- **Başlık:** Kendi Şehrinde Okumak: Hangi İlde Kaç Üniversite ve Kaç Program Var?
- **Hedef sorgular:** "şehrimde hangi üniversiteler var", "ilimdeki üniversite bölümleri", "istanbul'daki devlet üniversiteleri", "memleketimde okumak mantıklı mı"
- **İlk paragraf cevabı:** Türkiye'de üniversite arzı illere çok eşitsiz dağılmış: 2026 verisinde İstanbul'da 87 üniversitenin 6.442 programı varken Ankara'da 35 üniversite 1.831 program, İzmir'de 13 üniversite 793 program sunuyor; öbür uçta Hakkâri'de tek üniversitenin 43 programı (18'i lisans), Ardahan'da 47 (21 lisans), Şırnak'ta 50 (19 lisans) program var — yani "evde kalarak okumak" seçeneğinin ne kadar gerçekçi olduğu doğrudan hangi ilde oturduğuna bağlı.
- **5 maddelik iskelet:**
1. Cevap + eşitsizlik tablosu (en büyük 10 il / en küçük 10 il).
2. **"Evde kalmak" ne kazandırır, ne kaybettirir:** barınma maliyeti (→ `yurt-burs-ve-yillik-maliyet`) vs program çeşitliliği. Sayıyla: küçük ilde lisans seçeneği 20–30 program, yani bölüm ailen o ilde yoksa seçenek yok.
3. **İl içinde de devlet/vakıf ayrımı** ve bedel katmanı (İstanbul'da 795 devlet, 5.647 vakıf program satırı [D]) — "şehrimde üniversite var" ≠ "bütçeme uygun program var".
4. **Karar sırası:** bölüm ailesi → o ailenin kendi ilinde karşılığı var mı → yoksa yakın il / bedel karşılaştırması.
5. Kendi iline bak: il listesi + katalog bağlantıları.
- **Şema:** `Kendi şehrimde okumak istiyorum` → ilimde bölüm ailem var mı → evet: bedel/devlet-vakıf kontrolü / hayır: yakın il veya barınma bütçesi → karar. Maliyet düğümü metin etiketli.
- **Tablo kolonları:** il · üniversite sayısı · toplam program · lisans program sayısı · devlet program satırı · vakıf program satırı
- **DB sorgusu:**
```sql
SELECT il, COUNT(DISTINCT universite) uni, COUNT(*) prog, SUM(onlisans=0) lisans,
SUM(unitur='DEVLET') devlet, SUM(unitur LIKE 'VAKIF%') vakif
FROM programs WHERE il IS NOT NULL AND il <> '' AND il NOT LIKE '%-%'
GROUP BY il ORDER BY prog DESC;
```
**Veri uyarısı:** `il` alanında KKTC ve yurt dışı değerleri var (KIBRIS, LEFKOŞA, GİRNE, BAKÜ-AZERBAYCAN vb.) ve **boş `il` değerli 110 program satırı** mevcut [D] — tablo yayımlanmadan önce bunlar ayrı kutuya alınmalı, 81 il tablosuna karıştırılmamalı.
- **İç link:** `bolum-mu-universite-mi-sehir-mi`, `yurt-burs-ve-yillik-maliyet`, `/universiteler`, ilgili `/universite/<slug>` sayfaları
- **Not:** **T7 bağımlılığı:** `/il/[slug]` sayfası yok. Yazı yayımlanırken il adları `/universiteler`'e ya da o ildeki üniversite sayfalarına link verir; **olmayan bir URL'e link yazılmaz.** Bu yazı T7'nin talep gerekçesi olur.
---
### Dalga E — GEO ve marka (öncelik 19–20)
---
#### 19. `yapay-zekaya-tercih-sordum-guvenilir-mi` — **öncelik 19** · zorluk **M** · niyet **E + H**
- **Başlık:** Yapay Zekâya "Hangi Bölümü Yazayım" Diye Sorulur mu? Neyi Yapar, Neyi Uydurur?
- **Hedef sorgular:** "yapay zeka ile tercih yapılır mı", "chatgpt taban puan soruyorum doğru mu", "yapay zeka tercih robotu", "ai tercih listesi güvenilir mi"
- **İlk paragraf cevabı:** Genel amaçlı bir sohbet botu tercih sürecinde iki işi iyi yapar — kavram açıklamak ve senin yazdığın listeyi tartışmak — ama **taban sıralaması, kontenjan ve koşul gibi sayıları güvenilir biçimde veremez**, çünkü bu sayılar her yıl değişir ve modelin eğitim verisinde ya yoktur ya eskidir; bu yüzden sayı sorulacak yer veri kaynağı, yorum sorulacak yer modeldir.
- **5 maddelik iskelet:**
1. Cevap + ayrım: **sayı ≠ yorum.** Hangi soru hangi araca sorulur tablosu.
2. **Kendi testimiz:** birkaç güncel modele "X bölümünün 2026 taban sıralaması nedir" sorulur, verdikleri sayı bizim 2026 verimizle karşılaştırılır; tarih ve model adı yazılır, ekran görüntüsü yerine **metinle** aktarılır. (Yazar bu testi kendisi yapacak; test yapılamazsa bu bölüm yazıdan çıkar, iddia edilmez.)
3. **Neden uydurur:** eğitim verisi kesme tarihi, yılların karışması, "yakın görünen sayıyı üretme" davranışı — öğrenci diliyle, teknik terim yığmadan.
4. **Doğru kullanım:** kavram sorusu, listeni eleştirtme, "bu bölümde ne okunur" sorusu; her seferinde **sayıyı kaynaktan doğrulama** alışkanlığı.
5. **Bizim yaklaşımımız:** KolayTercih'in yapay zekâsı serbest cevap üretmez, **önceden kurulan aday havuzunun dışına çıkamaz**; havuz gerçek yerleştirme verisinden gelir. (`/meraklisina` şemasıyla **birebir tutarlı** olmalı — yazar `src/features/pazarlama/components/huni-semasi.tsx` içindeki `SEMA` sabitini okuyup uyumlu yazsın; çelişirse `yapay-zeka-muhendisi`'ne sorulur.)
- **Şema:** `Soruyu kime soracağım?` → sayı mı yorum mu → sayı: veri kaynağı / yorum: model → model dalında "sayı verdiyse doğrula" geri besleme oku → `/meraklisina`'ya çıkış.
- **Tablo kolonları:** soru tipi · örnek soru · sohbet botu ne yapar · nereden doğrulanır
- **Kaynak:** Kendi testimiz (tarih + model adı) [D olacak]; `/meraklisina` sayfası ve huni şeması [D].
- **İç link:** `tercih-robotu-nedir-yok-atlas-nasil-kullanilir`, `/meraklisina`, `taban-puan-mi-siralama-mi`, `/bolumler`
- **Not:** geo-raporu T22'nin içerik karşılığı. Kurucunun konumlandırmasıyla ("yapay zekâ ile insan arasında") birebir örtüşüyor; **marka açısından 20 konunun en değerlisi olabilir.** Rakip adı verilmez, kıyaslama yapılmaz — yalnızca araç türü anlatılır.
---
#### 20. `onlisansta-en-cok-yerlesilen-programlar` — **öncelik 20** · zorluk **M** · niyet **E + H**
- **Başlık:** Önlisansta En Çok Nereye Yerleşiliyor? 2026'nın Tablosu
- **Hedef sorgular:** "en çok tercih edilen önlisans bölümleri", "2 yıllık bölümler hangileri", "meslek yüksekokulu bölümleri", "hangi önlisans bölümü iyi"
- **İlk paragraf cevabı:** 2026'da önlisans programlarına 354.627 öğrenci yerleşti ve en çok yerleşilen program Bilgisayar Programcılığı oldu (333 ayrı programda 24.995 yerleşen); onu İlk ve Acil Yardım (235 programda 7.016), Muhasebe ve Vergi Uygulamaları (224/6.866), Lojistik (119/6.679) ve Elektrik (133/6.371) izledi — yani önlisans, medyada neredeyse hiç konuşulmadığı hâlde her yıl yerleşenlerin en büyük bloklarından birini oluşturuyor.
- **5 maddelik iskelet:**
1. Cevap + ölçek: 9.254 önlisans programı, 354.627 yerleşen [D]. "Önlisans görünmez" tezi.
2. **En çok yerleşilen 15 önlisans programı** tablosu (program sayısı, kontenjan, yerleşen, ortalama taban sırası).
3. **Önlisansta taban sıralaması nasıl okunur:** TYT tek oturum, sıralama aralığı çok geniş (ör. Bilgisayar Programcılığı ortalama ~900 binli sıralar [D]) — bu rakamlar lisanstakiyle aynı anlamda okunmaz.
4. **Devam yolları:** DGS (→ #12), dikey geçiş yapmadan çalışma, ikinci program. İstihdam vaadi **yok** → `bolumun-is-imkanini-nasil-arastirirsin` yöntemine köprü.
5. Karar: "lisans tutmazsa önlisans" mı, yoksa bilinçli önlisans mı → `onlisans-mi-lisans-mi`.
- **Şema:** `Önlisans düşünüyorum` → bilinçli tercih mi, bant sonucu mu → program ailesi seçimi → "DGS bağlantısı var mı" kontrolü → iki çıkış (DGS yolu / doğrudan çalışma).
- **Tablo kolonları:** program · program sayısı · 2026 kontenjan · 2026 yerleşen · doluluk · ortalama taban sırası
- **DB sorgusu:** #12'deki önlisans sorgusunun aynısı (`HAVING n>=40 ORDER BY y DESC LIMIT 15`) + `AVG(sira2026)` kolonu. **#12 ile aynı rakamlar kullanılacak — editör iki yazıda tutarlılığı kontrol etsin.**
- **İç link:** #12, `onlisans-mi-lisans-mi`, `bolumun-is-imkanini-nasil-arastirirsin`, `bos-kontenjanlar-ne-anlatiyor`, `/bolumler`
---
## 2.1 Özet tablo — 20 konu tek bakışta
| # | Slug | Niyet | Zorluk | Ana veri / kaynak | Bağımlılık |
|---|---|---|---|---|---|
| 1 | `taban-siralamalari-alti-yilda-nasil-degisti` | E+H | L | `programs` sira2021/2026 | — (kanonik) |
| 2 | `kac-net-ile-hangi-bolum` | H+E | L | `netler` 2025 — **"en son yerleşen kişinin netleri"**, ortalama değil | YÖK Atlas teyidi ✅ yapıldı · **YAZILDI** |
| 3 | `ayni-bolum-farkli-universite-siralama-farki` | E+H | M | `programs` il=İSTANBUL | — |
| 4 | `ogretmenlik-bolumlerine-talep-nasil-degisti` | H+V | M | `programs` trend + kontenjan | #1 |
| 5 | `hangi-bolumlerin-kontenjani-azaldi` | H+E | M | `programs` kontenjan 25→26 | #1 · YÖK duyurusu [doğrulanmalı] |
| 6 | `siralama-bandina-gore-kac-secenek-var` | E+H | M | `programs` sira2026 bantları | Kanibalizasyon kontrolü |
| 7 | `puan-turu-nasil-secilir` | H | M | `programs` tur kırılımı | ÖSYM kılavuz tanımları |
| 8 | `on-bir-sinifta-tercih-hazirligi` | H+V | M | — (yalnız iç alıntı) | #6, #7 |
| 9 | `dil-puaniyla-hangi-bolumler-var` | H+E | S | `programs` tur='DİL' | — |
| 10 | `psikoloji-okumak-2026-tablosu` | H+E | M | `programs` isim LIKE 'Psikoloji%' | #1, #3 · şablon |
| 11 | `bolumumu-sevmedim-hangi-kapilar-var` | B | M (kısa) | — | 5 mevcut yazı · uzunluk sınırı |
| 12 | `onlisanstan-lisansa-dgs-yol-haritasi` | B+E | M | `programs` onlisans=1 | ÖSYM DGS kılavuzu [doğrulanmalı] |
| 13 | `birinci-sinifta-ders-secimi-agno-ve-butunleme` | B | M | — | Üniversite yönetmelikleri |
| 14 | `kyk-disinda-burs-ve-destek-haritasi` | B+V | M | — | Kurum adı listesi yayımlanmaz |
| 15 | `veliler-icin-taban-siralama-okuma-kilavuzu` | V | M | #1/#3 alıntısı | #1, #3 |
| 16 | `cocugum-bir-yil-daha-istiyor-veli-rehberi` | V | M | — | ÖSYM kılavuz OBP maddesi |
| 17 | `rehber-ogretmenler-icin-veri-kaynaklari` | V | M | Üç birincil kaynak | Erişim tarihi zorunlu |
| 18 | `kendi-sehrinde-okumak-il-il-universite-haritasi` | V+H | L | `programs` il kırılımı | T7 · `il` temizliği |
| 19 | `yapay-zekaya-tercih-sordum-guvenilir-mi` | E+H | M | Kendi testimiz + `/meraklisina` | Huni şemasıyla senkron |
| 20 | `onlisansta-en-cok-yerlesilen-programlar` | E+H | M | `programs` onlisans=1 | #12 ile aynı rakam |
**Dağılım kontrolü:** evergreen 10 · 2027'ye hazırlanan 11 · yeni yerleşmiş 1. sınıf 4 · veli/rehber öğretmen 5 (istenen asgari 3 karşılandı). Zorluk: 1 S, 15 M, 4 L.
---
## 3. Şimdi yazılmaz (kaynağı doğrulanamıyor ya da karar bekliyor)
Bu konular **ana 20'ye karıştırılmadı**; kaynak açılınca ya da karar gelince ayrıca planlanır.
| Konu | Neden şimdi değil | Ne açılırsa yazılır |
|---|---|---|
| 2027 YKS/DGS/MSÜ **tarih tablosu** içeren her yazı | ÖSYM 2027 sınav takvimi 22 Eylül itibarıyla yayımlanmamış [A] | ÖSYM takvim duyurusu (2026'nınki 14.11.2025'te çıkmıştı [A]) |
| KYK burs/kredi ve **ek yurt başvuru tarihleri** odaklı yazı | GSB 2026-27 dönemini duyurmamış [A]; bu gece yazılan `kyk-burs-mu-kredi-mi` zaten tarihsiz karar yazısı | GSB/KYGM resmî duyurusu |
| AÖF / ikinci üniversite yazısı | CEO 21 Eylül'de reddetti (OBP istisnası teyitsiz) — karar değişmedi | ÖSYM/YÖK mevzuatında istisnanın açık metni |
| **Vakıf üniversitelerini adıyla** doluluk sıralaması | 05-seo-plan §3 #10: **[BİLAL]** kararı bekliyor (itibar/hukuk) | Bilal'in tek cümlelik onayı |
| Vakıf **burs etiketi** kırılımına dayanan derin analizler | 3.821 vakıf lisans programında isimde burs etiketi yok [D]; kaynak sorusu açık (veri-muhendisi) | Etiket kaynağı doğrulanınca |
| "Aynı üniversitede aynı bölümün iki satırı neden var?" | Yukarıdaki veri sorusuna bağlı; şimdi yazılırsa yanlış açıklama riski var | Aynı |
| **Harç/öğrenim ücreti rakamı** içeren her yazı | Rakam yalnızca Resmî Gazete'den; RG sayısı ve URL teyit edilmedi | RG kararının sayısı + URL |
| Öğretmen **atama/KPSS** kontenjanı içeren yazı | Verimiz yok, MEB ayrı kaynak; vaat riski yüksek | MEB atama istatistikleri (ve o zaman bile ayrı yazı) |
| Maarif modelinin YKS'ye etkisi (tarihli iddia) | MEB birincil kaynağı açılmadı [A] | MEB genelgesi/duyurusu |
| **2026 netleri** (herhangi bir 2026 net rakamı) | `netler` tablosu **2025'te bitiyor** [D]; YÖK Atlas canlı servisinde de en yeni yıl 2025 (22 Eyl 2026 teyidi [D]) | 2026 net verisi YÖK Atlas'ta yayımlanıp ingest edilince (#2 güncellenir; `netler` yıl etiketi kuralı §0'da) |
| Üniversite–üniversite kıyas yazıları (İÜ vs Marmara vb.) | Konsept hazır (05-seo-plan §3 #6) ama **öznel "daha iyi" riski** yüksek; önce #3 yayımlanıp ton oturmalı | #3 yayımlandıktan sonra |
---
## 4. Teknik bulgular (05-seo-plan §6'nın devamı; CTO iş paketine çevrilebilir)
Yeni numaralar T33'ten başlıyor; T1–T32 hâlâ geçerli ve tekrar edilmedi.
| # | Bulgu | Kanıt | Öneri | Önem |
|---|---|---|---|---|
| **T33** | **20 yeni yazı `/rehber` listesini kullanılamaz hâle getirir.** Bugün 32 yazı var; bu plan tamamlanırsa 52+. `rehber-makale.tsx:47` hâlâ "Diğer rehber yazıları" için tarihe göre `.slice(0,4)` yapıyor ve `/rehber` düz bir duvar. | 05-seo-plan T5 [D] · `ls content/rehber` = 32 dosya [D] | T5 (frontmatter `kume:` + `ilgili:`, `/rehber`'de küme başlıkları) **P1'den P0'a**. Bu gece yazılan yazılar teslim edilirken alan eklenebilecek şekilde CTO şartnamesi hazır olsun; alan eklenince yazarlar tek satır frontmatter ekler. | **P0** |
| **T34** | **`programs.il` alanı temiz değil.** 91 farklı `il` değeri var; içinde KKTC ilçeleri (LEFKOŞA, GİRNE, GÜZELYURT, LEFKE, GAZİMAĞUSA), yurt dışı şehirler (BAKÜ-AZERBAYCAN, BİŞKEK-KIRGIZİSTAN, TÜRKİSTAN-KAZAKİSTAN) ve **boş `il` değerli 110 program satırı** (9 üniversite) bulunuyor. | `SELECT il, COUNT(DISTINCT universite), COUNT(*) FROM programs GROUP BY il` [D] | `veri-muhendisi`: boş `il`'lerin kaynağı; `il` yanında `ulke`/`bolge` ayrımı. T7 (`/il/[slug]`, 81 il) bu temizlik olmadan yapılmasın — aksi hâlde `/il/bakü-azerbaycan` gibi sayfalar üretilir. #18 yazısının da ön koşulu. | **P1** |
| **T35** *(22 Eyl düzeltildi)* | **`netler` tablosu hiçbir ~~sayfada ve~~ yazıda kullanılmıyordu.** Katalogda kullanılıyor (`src/app/api/netler/route.ts`, `program-netleri.tsx` modal, `universite-program-tablosu.tsx:114`, `bolum-program-listesi.tsx:262`, `liste/components/program-tablosu.tsx:387` [D: `18-yazar-kac-net.md` §5.2]); eksik olan **sunucu HTML'i** ve **yazı** kullanımıydı. 62.975 satır, 25.166 program, 2023–2025; 2025 yılında 20.821 satırın tamamında TYT matematik neti dolu. **Tablo "en son yerleşen kişinin netleri"dir, ortalama değil** (§0 kuralı). geo-raporu T11 bunu "rakiplerde olmayan özgün veri" diye işaretliyor, hâlâ açık. | `SELECT yil, COUNT(*), SUM(tytMatNet IS NOT NULL) FROM netler GROUP BY yil` [D] · `grep -rn "netler" src/` → yalnız modal | (a) #2 yazısı bu veriyi ilk kez kamuya açıyor — yayın öncesi 3–5 satır YÖK Atlas'tan gözle doğrulansın. (b) T11 (bölüm sayfasında sunucu HTML'i olarak net tablosu) #2 yayımlandıktan sonra doğrudan trafik kazanacak: yazı → bölüm sayfası köprüsü kurulabilir. | **P1** |
| **T36** | **2026 net verisi yok.** `netler` en son 2025; katalog `sira2026`/`puan2026` ile 2026'ya geçmiş durumda. Bu uyumsuzluk bölüm sayfalarında "2026 tabanı + 2025 netleri" gibi karışık bir tablo doğurur. | `veri_meta.refresh_2026_tarih` [D] vs `netler` max(yil)=2025 [D] · YÖK Atlas canlı servisi `sortBy=yil DESC` → en yeni kayıt 2025, 22 Eyl 2026 [D: `18-yazar-kac-net.md` §3] | **Cevap alındı: YÖK Atlas 2026 netlerini yayımlamamış**, ingest gecikmesi değil. O hâlde kalıcı kural: hem katalog sayfasında hem her yazıda **her net rakamının yanında yıl etiketi zorunlu** (§0), ve 2026 taban sırasıyla 2025 neti aynı cümlede yılsız yan yana yazılmaz. `veri-muhendisi`'ne kalan tek iş: canlı servis 63.063 satır, bizde 62.975 — **88 satırlık kapsama farkı** (%0,14) nereden [D: aynı rapor §5.4]. | P1 |
| **T37** | **Yeni yazılar için IndexNow hâlâ yok** (T2 açık). 20 yazı toplu yayımlanırsa Bing/Copilot/ChatGPT tarafında haftalar kaybedilir; Search Console'a elle 20 URL girmek de pratik değil. | 05-seo-plan T2 [D] | T2'nin önceliği bu plan onaylanırsa yükselir: script `content/rehber` altındaki **değişen** dosyalardan slug türetsin (`git diff --name-only`), yayın sonrası tek komutla gönderilsin. | P1 |
| **T38** | **Katalog → rehber yönü hâlâ tek yönlü** (T8 açık). Bu plandaki 8 yazı (#1, #2, #3, #5, #9, #10, #18, #20) doğrudan `/bolum/*` sayfalarını besliyor; ters link olmadığı için katalog sayfasına inen organik ziyaretçi yazıyı hiç görmüyor. | `bolum-icerik.tsx:288`, `universite-icerik.tsx:365` [D: 05-seo-plan T8] | T5'in `ilgili:`/`bolumler:` frontmatter alanı iki yönlü kullanılsın. Bu plan T5'i ekonomik olarak haklı çıkarıyor: 52 yazı × ortalama 3 bölüm = ~150 katalog→rehber bağlantısı. | P2 |
---
## 5. Yazar dağıtımı önerisi (orkestratöre)
Paralel çalıştırılacaksa dosya çakışması yok (her yazar yalnız kendi `content/rehber/<slug>.md` dosyasını yazar, merkezi kayıt dosyası yok [D: `src/lib/rehber.ts` klasör tarıyor]). Sıra önerisi:
1. **Önce tek başına #1** yazılsın (kanonik trend rakamları). Bitmeden #4, #5, #10 başlamasın.
2. **#1 biterken paralel başlatılabilecekler** (birbirinden bağımsız): #2, #3, #6, #9, #11, #13, #14, #16, #17, #19.
3. **#1 bitince:** #4, #5, #10, #15.
4. **#12 ve #20 aynı yazara** verilsin (aynı sorgu, tutarlılık kendiliğinden gelir) ya da art arda.
5. **#18 en sona** — T34 (il temizliği) sorusuna veri-muhendisi cevap verdikten sonra.
6. **#8'in girdisi #6 ve #7**; ikisi bitmeden yazılmasın.
Her yazar bitirince: dosyayı bırakır, **commit atmaz**, raporunda (a) kullandığı sorgu metinlerini, (b) açamadığı kaynakları, (c) yazıdan çıkardığı doğrulanamayan cümleleri listeler. `rehber-editoru` en sonda **tek kopya** çalışıp §1 çakışma tablosunu denetler.
---
## 6. Bilal'den istenen (en fazla 3)
1. **Karar:** Vakıf üniversitelerinin **adıyla** doluluk/boşluk oranı yayımlanabilir mi (21 Eylül planından devreden soru)? Cevap "hayır" ise o kesit kalıcı olarak yalnız bölüm bazında kalır — **tek cümle, 1 dk.**
2. **Onay:** #2 (`kac-net-ile-hangi-bolum`) yazısı bugüne kadar hiç yayımlamadığımız **program bazlı net verisini** kamuya açıyor; bu veriyi yazı ve ileride bölüm sayfası olarak yayımlamakta sakınca var mı — **tek cümle, 1 dk.**
3. **Search Console'dan iki rakam** (21 Eylül'den devreden, hâlâ alınmadı): mülk türü (alan adı mı, URL öneki mi) ve "Yumuşak 404" sayısı — T1'in taban çizgisi bu olmadan kurulamıyor — **5 dk.**
---
## Kaynaklar
**İç (tamamı [D], bu gece okundu):** `data/yokatlas.db` — `programs` (21.493 satır, 18.251'inde `sira2026`, 322 üniversite, 1.744 farklı program adı, 9.254 önlisans), `netler` (62.975 satır, 25.166 program, 2023–2025), `veri_meta` (`refresh_2026_tarih = 2026-09-21T17:21:23Z`) · `content/rehber/` (32 dosya) · `src/lib/rehber.ts` (frontmatter ve mermaid ayrıştırma) · `src/lib/seo.tsx:24` (`KATALOG_VERI_TARIHI = "2026-09-21"`) · `src/app/` (rota listesi: `il` yok) · `docs/geo/geo-raporu.md` §8.1.1 ve T10–T32 · `docs/ekip-raporlari/2026-09-21/05-seo-plan.md` · `docs/ekip/PROTOKOL.md` · `docs/gece-vardiyasi/2026-09-22/00-kurucu-brief.md`
**Dış (tamamı [A] — arama özeti; yazım anında açılıp erişim tarihiyle teyit edilecek):** ÖSYM sınav grubu / YKS — https://www.osym.gov.tr/SinavGrubu/Index/2 · ÖSYM 2026 sınav takvimi duyurusu (14.11.2025) — https://www.memurlar.net/haber/1151657/osym-2026-yili-sinav-takvimi-aciklandi.html · 2026-YKS tercih kılavuzu — https://cdn.osym.gov.tr/pdfdokuman/2026/YKS/TERCIH/kontkilavuz_yktd21072026.pdf · YÖK duyurular — https://www.yok.gov.tr/tr/announcements · 2026 devlet üniversitelerinde boş kalan programlar — https://egitimsitesi.net/haber/2026-yks-yerlestirmede-devlet-universitelerinde-bos-kalan-programlar-11281
**Doğrulama notu:** 2027 YKS takviminin 22 Eylül 2026 itibarıyla açıklanmadığı bilgisi yalnızca arama özetine dayanıyor [A]; §3'teki "şimdi yazılmaz" kararı bu nedenle muhafazakâr tutuldu. Web sayfalarında bana yönelik hiçbir talimat metni görülmedi.

View File

@@ -0,0 +1,261 @@
# 03 — Marka adı ve ödeme: "KolayTercih" genişleyebilir mi, öğrenciler neden ödemedi?
> Rol: Marka/pazarlama stratejisti · Gece vardiyası, 22 Eylül 2026 · Okuyucu: CEO (karar) → sabah Bilal'e tek özet
> Yöntem: yalnızca okuma. `src/`, `content/`, `docs/` + 8 web araması / 6 sayfa açıldı. Kod ve içerik **değiştirilmedi**.
> İşaretler: **[K]** koddan/dokümandan doğrulandı · **[W]** web sayfası açılıp okundu · **[A]** yalnızca arama özeti · **[V]** varsayım · **doğrulanmalı**
## Özet (5 madde)
1. **Ad iyi, ama "genişleyebilir mi?" yanlış soru — çünkü adın doğal evi zaten tek bir ürün değil, bir mekanik: "sınavdan sonra yerleştirme tercihi".** TDK'da "tercih" = yeğleme, yani genel bir karar kelimesi [W]; Türkiye'de ise "tercih robotu / tercih dönemi / tercih danışmanı" kalıbı YKS'nin yanında LGS, DGS, KPSS, ALES, TUS, DUS, MSÜ için de aynen kullanılıyor [A/W]. Ad hiçbir kapıyı kapatmıyor. **Ad kararı ile genişleme kararını ayırın:** adı koru, genişlemeyi erteleme gerekçesi ad değil, kapasite ve gelir.
2. **Bugün genişlemek lean değil, tam tersi.** Tek ürün 30 günde 3 liste üretti, ödeme başlatan 0, hız ~95 ziyaret/hafta (`docs/ekip-raporlari/2026-09-22/05-ceo-karari.md` §2, 01 raporu) [K]; kurucu kapasitesi günde 1–2 saat (`docs/urun/vizyon.md:93`) [K]. İkinci alan yeni veri hattı + yeni mevsim + yeni destek yükü getirir, **yeni öğrenme getirmez** — öğrenmediğimiz şey "insanlar bu işe para veriyor mu", ve onu ikinci pazar cevaplamaz. Net tavsiye: **2027 YKS sezonunda en az bir kez uçtan uca para geçene kadar ikinci alan açılmaz.**
3. **"Öğrenciler ödemedi" cümlesi bugün kanıtlanamaz — kasa kırıktı.** 7 Ağu–12 Eyl arası ~100 siparişin **hiçbiri** iyzico token'ı alamadı, yani ödeme formu bir kez bile açılmadı (`docs/ekip/KARARLAR.md`, 2026-09-21 gece kaydı) [K]. 21 Eylül 17:00'den beri 7/7 sipariş token alıyor ama **uçtan uca tamamlanmış tek ödeme yok** [K]. Elimizdeki veri "Türk kullanıcısı ödemiyor"u değil, "ödeyemedi"yi gösteriyor. Bu ayrım sabah Bilal'e böyle sunulmalı.
4. **Ödemeye giden yolda 6 kapı var ve ödeyecek kişi o yolun hiçbir yerinde yok.** Sıralama → 3 adımlı sihirbaz → giriş → LLM üretimi → 24 satırın **3'ü** açık (`src/lib/rapor-maske.ts:12`) → `/paket` 299 TL [K]. Metinlerin tamamı öğrenciye "sen" diye sesleniyor; tüm `src/` içinde "veli" kelimesi **yalnız iki yerde** geçiyor ve ikisi de aynı özellik satırı: "Veliyle paylaşılabilir PDF rapor" (`src/app/page.tsx:197`, `src/features/odeme/components/paket-satinal.tsx:36`) [K]. Veliye yazılmış tek yüzey bir rehber yazısı (`content/rehber/veliler-icin-tercih-rehberi.md`) ve onun altındaki CTA öğrencinin CTA'sı — veliden "sıralamanı gir" isteniyor (`src/features/rehber/components/rehber-makale.tsx:115` → `CtaSiraForm`) [K]. **Ödeyecek kişi için sitede tek bir düğme yok.**
5. **Satış anında kurumsal kanıtın neredeyse tamamı eksik.** İade politikası iyi ve net (`src/app/kosullar/page.tsx:61-83`, 14 gün, koşulsuz) [K], iyzico bandı var [K] — ama satıcı kimliği (unvan/adres/vergi no/telefon) sitenin hiçbir yerinde yok (grep = 0) [K], fatura/makbuz kelimesi hiç geçmiyor (grep = 0) [K], **ödeme sonrası alıcıya giden tek bir e-posta yok** (`src/lib/eposta.ts` yalnız magic-link + kredi hatırlatma) [K], sosyal kanıt şeridi kodda var ama 25 liste eşiğinin altında hiç çizilmiyor (`src/lib/sosyal-kanit-sabitler.ts:11`) ve zaten yalnız ana sayfadadır, `/paket`'te yoktur (`src/app/page.tsx:536`) [K]. Taksit kapalı (`src/lib/iyzico.ts:201` `enabledInstallments: [1]`) [K] — oysa Türkiye'de online kart işleminin önemli bölümü taksitli [A].
---
# SORU 1 — "KolayTercih" adı üniversite tercihinin dışına çıkabilir mi?
## 1.1 Adın anlam alanı
| Katman | Bulgu | Kaynak |
|---|---|---|
| Sözlük | TDK Güncel Türkçe Sözlük: **tercih (a., Ar. tercīḥ) = yeğleme**. Tek anlam, eğitimle ilgisi yok; örnek cümle Çetin Altan'dan, yemek seçmekle ilgili | [W] sozluk.gov.tr/gts?ara=tercih |
| Günlük dil | "tercih etmek" = iki şey arasında seçim yapmak; genel kullanım | [W] ntv.com.tr/ne-demek/tercih-ne-demek |
| Türkiye'de sınav dili | "tercih robotu" kalıbı **YKS, LGS, DGS, KPSS, TUS, DUS, MSÜ, ALES** için aynen kullanılıyor; MEB'in kendi ürününün adı da "LGS Tercih Robotu" | [W] meslegimhayatim.meb.gov.tr/tercih-donemi/lgs-tercih-robotu; [A] arama sonuçları |
| Bizim kullanımımız | Ürün adı sezona kilitli: paket etiketimiz **"Tercih Dönemi Paketi"** (`src/lib/credits.ts:7`) — sezon dışında ürünün adı bitmiş bir dönemi işaret ediyor | [K] |
**Okuma.** "Tercih" Türkçede YKS'ye ait bir kelime değil; ama Türkiye'de **ücretli bir arama niyeti** olarak neredeyse tamamen "sınav sonrası yerleştirme tercihi"ne demirlemiş durumda. Yani ad iki yönde çalışıyor:
- **Geniş yön (dil):** "tercih" = karar. Ad, "karar verdiren araç" konumunu taşır. Teorik olarak tercih dışı karar ürünlerine de uzanır.
- **Dar yön (pazar):** insanlar "tercih" yazdığında sınav-yerleştirme arıyor. Bu dar yön bizim lehimize — ad bedava niyet taşıyor. Genişlerken kaybedilecek şey bu.
**Sonuç:** ad, "sınavdan sonra yerleştirme tercihi" ailesinin tamamına **bedava** genişler. Bu ailenin dışına (kariyer, özel okul, ehliyet, genel karar) ad taşır ama **ürün ve güven taşımaz** — aşağıdaki tablo bunu gösteriyor.
## 1.2 Bitişik alanlar — aynı kullanıcı / mevsim / veri / güven?
| Alan | Aynı kullanıcı? | Aynı mevsim? | Aynı veri? | Aynı güven? | Hüküm |
|---|---|---|---|---|---|
| **DGS / KPSS / ALES tercihleri** | Hayır (üniversiteli/mezun) ama aynı yaş bandı | **Hayır — ve bu iyi:** Ağustos–Eylül, YKS'nin ölü ayı (`docs/urun/vizyon.md:85`) [K] | **Neredeyse aynı:** ÖSYM kılavuzu + YÖK Atlas mantığı, aynı "kontenjan/taban sıralaması" şeması | **Aynı** (havuz kısıtı, garanti yok) | **En doğal genişleme.** Vizyon zaten yazmış (`vizyon.md:46`) [K] |
| **LGS / lise tercihi** | Hayır (8. sınıf + veli ağırlıklı) | Haziran–Temmuz, çakışıyor | Hayır — MEB yerleştirme verisi, ayrı hat | Aynı ama **rakip devlet** | **Riskli.** MEB 2026'da kendi **yapay zekâ destekli** LGS tercih robotunu çıkardı; ücretsiz, resmî [W]. Bedava + resmî bir rakibe karşı ücretli satmak zor |
| **Yurt / burs / yıllık maliyet kararı** | **Evet** (aynı öğrenci + veli) | **Evet** (tercih anı) | Hayır (KYK, vakıf ücretleri — bizde yok) | Aynı | **Ürün değil, içerik genişlemesi.** Zaten var: `content/rehber/yurt-burs-ve-yillik-maliyet.md`, `kyk-burs-mu-kredi-mi.md` [K] |
| **Meslek / kariyer kararı** | Evet ama farklı anda | Yıl boyu (sezonsuz — cazip) | **Hayır, veri yok** (iş piyasası, maaş verisi elimizde yok) | **Farklı** — "veriye dayanıyoruz" iddiamız burada boşa düşer | **Hayır.** Bugünkü tek farklılaştırıcımız "havuz dışına çıkamaz" kuralı (`src/app/page.tsx:127`) [K]; kariyerde havuz yok |
| **Özel okul seçimi / ehliyet / genel karar ürünleri** | Hayır | Hayır | Hayır | Hayır | **Ad taşır, ürün taşımaz.** Marka denemesi değil, yeni şirket |
## 1.3 Genişleme ne zaman? (lean cevap)
**Bugün yanlış.** Gerekçe kanıtla:
- Tek ürünün cevaplamadığı soru "pazar var mı?" değil, **"bu üründen para geçiyor mu?"** — 30 günde ödeme başlatan 0, uçtan uca ödeme 0 [K]. İkinci alan bu soruyu cevaplamaz, **iki katına çıkarır**.
- Genişlemenin marjinal maliyeti kod değil, **kurucu dikkati**: veri hattı + yıllık güncelleme + kılavuz takibi + destek + ayrı sezon takvimi. Günde 1–2 saatlik kapasitede (`vizyon.md:93`) bu, mevcut ürünün bakımını yer.
- Bileşik getirisi olan tek genişleme **DGS/KPSS**: aynı veri şeması, **farklı mevsim** — yani boş kalan Ağustos–Eylül'ü doldurur ve mevcut altyapıyı yeniden kullanır. Yine de sıra ikinci.
**Tavsiye — tek cümlelik tetik [BİLAL onayı gerekmez, CEO yazabilir]:**
> "2027 YKS sezonunda **en az 100 tamamlanmış ödeme** görülene kadar ikinci alan açılmaz. Görülürse sıradaki alan DGS/KPSS'tir (aynı veri, farklı mevsim), LGS değildir (bedava + resmî rakip)."
Sayı seçimi gerekçesi: bugünkü paket fiyatıyla 100 sipariş ≈ 29.900 TL [K, `credits.ts:7`] — "yan proje anlamlı oldu" eşiğinin altında ama "tesadüf değil" eşiğinin üstünde. Sayıyı Bilal değiştirebilir; önemli olan tetiğin **adet** olması, his olmaması.
## 1.4 Alan adı ve kanal riski (yalnızca liste — satın alma yok)
| Ne | Neden | Not |
|---|---|---|
| `kolaytercih.com.tr` | Kurumsal görünüm; Türkiye'de `.com.tr` **marka tescil belgesi/başvurusu** ister [A] | Yani asıl kapı alan adı değil, **marka tescili**. `[BİLAL]` |
| `kolaytercih.net`, `.org`, `.app`, `.co` | Savunma; taklit siteye karşı | Ucuz, geri dönüşsüz risk yok |
| `kolaytercih.ai` | Konum "yapay zekâ ile insan arasında" ise [K, `00-kurucu-brief.md:11`] doğal | İsteğe bağlı |
| Kullanıcı adları: `@kolaytercih` — Instagram, TikTok, YouTube, X | Dağıtım kanalı; öğrenci kitlesi burada | **Ben açmıyorum** (protokol md.5). Bilal'in 10 dakikası |
| `kolaytercih` yazım varyantları (`kolay-tercih`, `kolaytercih2027`) | Sezonluk taklit sayfa riski | Düşük öncelik |
**Marka tescili uyarısı:** TÜRKPATENT'te "kolaytercih" ya da benzerinin tescilli olup olmadığını **doğrulamadım — doğrulanmalı**. Bu, ad kararından önce bilinmesi gereken tek gerçek engel.
## 1.5 Ad riski: "kolay" ciddiyet kaybettirir mi?
**Kanıtlar (kendi kodumuzdan):**
| Bulgu | Dosya:satır | Yorum |
|---|---|---|
| Logo tipografisi "Kolay"ı **hafif**, "Tercih"i **kalın** yazıyor | `src/components/site-header.tsx:22-27`; aynısı `src/app/opengraph-image.tsx:53`, `src/lib/og-sayfa.tsx:228` | Tasarım, kelimenin ağırlığını zaten "Tercih"e kaydırmış — yani içeriden bir tedirginlik var ve doğru çözülmüş [K] |
| Ürün içinde öncelik çipi: **"Kolay yerleşme"** | `src/features/sihirbaz/sihirbaz-sabitler.ts:17` | "Kolay" kelimesi ürün içinde *düşük hedef* anlamına geliyor; markanın "kolay"ı ile çakışıyor [K] |
| Çip bir kez zaten geri çekilmiş: **"İş garantisi" → "İş bulma kolaylığı"** | `sihirbaz-sabitler.ts:128-133` | Vaat kelimesinden kaçınma refleksimiz var; "kolay" bu refleksin sınırında [K] |
| Editoryal çizgimiz "kolay"ın tersini söylüyor: "Yerleşme garantisi vermiyoruz — çünkü kimse veremez", "bu bir tahmin aracıdır" | `src/app/page.tsx:383-392`; `src/features/pazarlama/components/meraklisina-icerik.tsx:138+` | Ad "zahmetsiz", ürün "dürüst ve zahmetli" diyor [K] |
| Footer ürünü **"YKS Tercih Robotu 2026"** diye adlandırıyor | `src/components/site-footer.tsx:49` | `vizyon.md:22`'nin açıkça reddettiği kategori; bu, addan daha büyük bir konum çelişkisi [K] |
**Hüküm:** "Kolay" ciddiyet kaybettirmiyor — **çünkü ürün kolaylığı satmıyor, kolaylaştırıcılığı satıyor** ve kurucunun kendi çerçevesi de bu ("yapay zekâ ile insan arasında kolaylaştırıcı", `00-kurucu-brief.md:11`). Risk kelimede değil, **sloganın boş olmasında**: bugün adın yanında ne yaptığımızı söyleyen kalıcı bir alt satır yok (dünkü envanter §1.1: hero'da alt başlık **yok**). "Kolay" tek başına durduğunda "yüzeysel" okunur; yanında "gerçek YÖK Atlas verisiyle" durduğunda "karmaşığı sadeleştiren" okunur.
**Emsal (dışarıdan, [W]):** "Kolay Randevu" markası yurt dışına açılırken adını **SalonAppy** yaptı [W egirisim.com]. "Kolay İK" ise Türkiye B2B'de "Kolay" ile büyüdü [W kolayik.com]. Okuma: **"Kolay X" Türkçe pazarda taşır, ihracatta kırılır.** KolayTercih'in ufkunda ihracat yok (veri Türkiye'ye özgü) → ad bir tavan yaratmıyor.
## 1.6 Ekibin "kolaytercih güzel bir isim" görüşü: doğrulandı mı?
**Doğrulandı, ama gerekçesi düzeltildi.** Ad güzel olduğu için değil, **üç şeyi bedava taşıdığı** için iyi: (a) arama niyetiyle birebir örtüşüyor, (b) sınav-yerleştirme ailesinin tamamına genişler, (c) Türkçe telaffuzu ve yazımı tek. Çürütülen kısım: "ad bizi üniversiteye kilitliyor" korkusu **yersiz**; kilit adda değil, **veride ve mevsimde**.
---
# SORU 2 — Öğrenciler neden hiç ödeme yapmadı? Türk kullanıcısı neye para öder?
## 2.1 Önce teşhis sırası: üç katman, yanlış sırada tartışılıyor
| Katman | Bulgu | Kaynak | Bu katman çözülmeden bir sonrakini konuşmak anlamsız |
|---|---|---|---|
| **1. Mekanik** | ~100 siparişin **hiçbiri** iyzico token'ı alamadı (7 Ağu–12 Eyl). Ödeme formu bir kez bile açılmadı. 21 Eyl 17:00'den sonra 7/7 token alıyor; **uçtan uca tamamlanmış ödeme hâlâ 0** | `docs/ekip/KARARLAR.md`, 2026-09-21 gece kaydı [K] | Evet |
| **2. Huni** | Ödeme kapısına varmak için 6 kapı: sıralama → 3 adımlı sihirbaz → giriş → LLM üretimi → 3/24 satır → `/paket`. 30 günde liste üretimi **3** | `src/lib/rapor-maske.ts:12`, `05-ceo-karari.md` §2 [K] | Evet |
| **3. İkna** | Satış anında kurumsal kanıt yok (aşağıdaki envanter) | bu rapor §2.3 [K] | — |
**Bu yüzden sabahki cümle şu olmalı:** *"Öğrenciler ödemedi" henüz bir pazar bulgusu değil; 30 gün boyunca ödeme ekranı hiç açılmadı. Önce bir kez gerçekten satabildiğimizi görmemiz lazım.*
## 2.2 Türkiye'de gerçekten para kazanan tüketici kategorileri — rakamlarla
| Kategori | Fiyat bandı | Ödeme anı | Ödeyen | Kaynak |
|---|---|---|---|---|
| **YKS tercih danışmanlığı (insan)** | **1.000–3.000 TL**, örnek işler 1.250–3.000 TL | Tercih döneminde, hizmetten **önce** | Veli (çoğunlukla) [V] | [W] armut.com/fiyatlari/yks-tercih-danismani_93536 |
| DGS tercih danışmanlığı (paket) | Liste 7.000 TL, indirimli **3.500 TL** (Zoom'da birebir) | Sezon başında | Öğrenci/veli | [A] mbaakademi.com |
| MEB rehber öğretmenine ödenen tercih danışmanlığı ek dersi | 45 saat × 219 TL = **9.855 TL** (YKS); LGS'de 7.360 TL | — | Devlet | [A] ogretmenlericin.com, mebpersonel.com — *doğrulanmalı* |
| **Sınav hazırlık uygulaması (Kunduz)** | Soru Çözüm Paketi **726,99–1.299,99 TL/ay**; dönemlik 12–13 ay taahhüt; **12 taksite varan ödeme** | **Sezon başlamadan** ("Temmuz'da başla" indirimi) | Veli [V] | [W] alisanci.com/kunduz-paket-fiyatlari.html — *resmî sayfadan doğrulanmalı* |
| Aile başına eğitim harcaması ölçeği | Öğrenci başına toplam eğitim harcaması 2024'te **100.307 TL** (2023: 49.045 TL); eğitim hizmetleri yıllık enflasyonu Ağu 2026'da **%53,44** | Yıl boyu | Veli | [A] TÜİK bülten özeti / haber derlemeleri — *TÜİK sayfası JS ile açıldığı için birebir doğrulanamadı, doğrulanmalı* |
| **Ücretsiz ikame (en önemli rakip)** | **0 TL** — MEB 81 ilde **19.566 Üniversite Tercih Danışmanlığı Birimi** kurdu (rehber öğretmenler, RAM'lar, halk eğitim merkezleri) | Tercih döneminde | — | [W] meb.gov.tr/haber/37835 (Tem 2025; 2026 için *doğrulanmalı*) |
| **Ücretsiz ikame 2** | MEB'in kendi **LGS Tercih Robotu** — "öğrenci, öğretmen ve velilerimizin hizmetine sunulmuştur" | — | — | [W] meslegimhayatim.meb.gov.tr |
### Bu tablodan çıkan üç sonuç
1. **Eğitimde para var ve ödeyen veli.** Aile, ayda 700–1.300 TL'yi soru çözüm uygulamasına, 1.000–3.000 TL'yi tek seferlik danışmana verebiliyor. **299 TL bu ölçekte küçük bir para** — yani fiyat itirazı muhtemelen birincil sorun değil.
2. **Bizim fiyatımız "arafta".** 0 TL (MEB birimi + ücretsiz robotlar) ile 1.000 TL (insan danışman) arasında 299 TL, "ucuz olduğu için değersiz" ve "bedavası varken neden" itirazlarının ikisini birden yiyor. Bugünkü ana sayfa kıyasımız da tam olarak bu üç sütunu gösteriyor: Ücretsiz / 1.000–3.000 TL / 299 TL (`src/app/page.tsx:180-185`) [K]. Bu tablo dürüst ama **ortadaki sütunu seçtirmiyor**.
3. **Ödeme anı bizde en geçte, piyasada en erken.** Kunduz sezondan önce satıyor ("Temmuz'da başla" indirimi) [W], danışman hizmetten önce alıyor [W]. Biz ise ürün teslim edildikten *sonra*, 24 satırın 21'ini kilitleyip satıyoruz. Bu, "önce gör sonra öde" dürüstlüğü açısından iyi; **nakit tahsilatı açısından en zor an.**
## 2.3 Türk kullanıcısının ödeme koşulları — bizde ne var, ne yok (envanter, dosya:satır)
| Koşul | Piyasa normu | Bizde bugün | Kanıt |
|---|---|---|---|
| Tek seferlik mi abonelik mi | İkisi de var; eğitimde taahhütlü dönemlik yaygın [W Kunduz] | **Tek seferlik 299 TL + 129 TL top-up.** Net ve iyi; "Abonelik yok" rozeti var | `src/lib/credits.ts:6-9`, `src/app/paket/page.tsx:43` [K] |
| **Taksit** | En çok 6 ve 9–12 taksit tercih ediliyor [A BKM]; Kunduz "12 taksite varan" diyor [W] | **KAPALI** — `enabledInstallments: [1]` | `src/lib/iyzico.ts:201` [K] |
| Havale/EFT, kapıda ödeme | Düşük tutarda kart baskın; internetten kartlı işlem 2025'te 7.301 milyar TL [A BKM] | Yalnız kart (iyzico checkout) | `src/lib/iyzico.ts:197-201` [K] |
| **Sonuç garantisi beklentisi** | Rakipler "yerleşme olasılığı" diyor (dünkü rakip analizi) | **Bilinçli olarak vermiyoruz** ve bunu açıkça yazıyoruz — doğru karar, ama satış anında *dezavantaj olarak* duruyor | `src/app/page.tsx:383-392`, `src/app/kosullar/page.tsx:41-42` [K] |
| **Sosyal kanıt ("kaç kişi kullandı")** | Standart | Kod **var**, ama 25 liste eşiğinin altında hiç çizilmiyor; ayrıca yalnız ana sayfada, `/paket`'te **yok** | `src/lib/sosyal-kanit-sabitler.ts:11`, `src/app/page.tsx:536` [K] · prod'daki `reports` sayısı **doğrulanmalı** |
| **Kurumsal görünüm / satıcı kimliği** | Mesafeli satışta beklenen: unvan, adres, vergi no, telefon | **Hiç yok** (unvan/vergi/MERSİS/adres grep = 0); `/hakkinda` 21 Eyl'de ertelendi | `src/app/kosullar/page.tsx`, `src/app/iletisim/page.tsx` grep [K]; `docs/ekip/KARARLAR.md` 2026-09-21 [K] |
| **Fatura / makbuz** | Beklenen | Kelime sitede **hiç geçmiyor**; ödeme sonrası alıcıya **e-posta gönderilmiyor** (yalnız destek kutusuna iade bildirimi) | `src/lib/eposta.ts` (yalnız 2 şablon: `:127`, `:173`), `src/lib/odeme.ts:78-82` [K] |
| İade güvencesi | Güven artırıcı | **Var ve iyi:** 14 gün koşulsuz + teknik sorunda kullanımdan bağımsız iade; `/paket`'ten linkli | `src/app/kosullar/page.tsx:61-83`, `src/features/odeme/components/paket-satinal.tsx:88-95` [K] |
| Ödeme güvenlik işareti | Beklenen | **Var:** iyzico bandı + "Kart bilgilerin bize hiç ulaşmaz" | `paket-satinal.tsx:82-96` [K] |
| İletişim kanalı | Telefon/WhatsApp beklenir | Yalnız e-posta (`destek@kolaytercih.com`) | `src/app/iletisim/page.tsx:26-33` [K] |
| Denemeden ödeme | "Önce gör" | **Var ve dürüst:** 5 deneme kredisi, 24 satırın 3'ü açık, kredi kartı istenmiyor | `src/lib/credits.ts:11,14`, `src/lib/rapor-maske.ts:12` [K] |
## 2.4 Ödeyen kim olmalı? — envanter ve tavsiye
**Bugün metinler kime sesleniyor: %100 öğrenciye.**
| Yüzey | Kime | Kanıt |
|---|---|---|
| Hero H1 | Öğrenci ("Dört yıllık **geleceğini**… seçme") | `src/features/pazarlama/components/hero-baslik.tsx:24-28` [K] |
| Tüm CTA'lar | Öğrenci ("**Sıralamanı** gir", "Yapay Zeka **listemi** kur") | `hero-form.tsx:177,194`; `cta-sira-form.tsx:254,427` [K] |
| `/paket` H1 + alt metin | Öğrenci ("İnsan danışmanın işini, çok daha düşük fiyata") | `src/app/paket/page.tsx:44-51` [K] |
| Paket özellik listesi | **Tek veli değinmesi:** "Veliyle paylaşılabilir PDF rapor" | `src/app/page.tsx:197`, `paket-satinal.tsx:36` [K] |
| Veli rehber yazısı | Veliye yazılmış; **CTA'sı öğrencinin** ("Sıralamanı gir") → veli için ölü uç | `content/rehber/veliler-icin-tercih-rehberi.md` + `rehber-makale.tsx:115` [K] |
| E-postalar | Öğrenci ("Listen seni bekliyor") | `src/lib/eposta.ts:175-209` [K] |
**Tavsiye:** **Kullanan öğrenci, ödeyen veli** — vizyon zaten böyle diyor ("sürece para veren kişi çoğu zaman veli", `docs/urun/vizyon.md:36`) [K] ama **ürün bunu hiç uygulamamış**. 18 yaşındaki öğrencinin çoğunda kendi kartı ya yok ya limitsiz; 299 TL'lik kararı veren kişi mutfaktaki kişi. Piyasa da bunu doğruluyor: Kunduz'un 12 taksitli 13 aylık paketini bir lise öğrencisi almıyor [W].
Ama **öğrenciyi ödeyen yapmaya çalışmak yerine, öğrenciyi satıcı yapmak** daha lean: öğrenci ürünü ücretsiz kurar, veliye o gösterir. Bu, mevcut "Veliyle paylaşılabilir PDF" vaadinin zaten ima ettiği şey — sadece düğmesi yok.
## 2.5 Rakip söylemi (yeni, [W])
- **MEB, LGS için yapay zekâ destekli tercih robotunu 2026'da devreye aldı** ve "öğrenci, öğretmen ve **velilerimizin** hizmetine sunulmuştur" diyor [W meslegimhayatim.meb.gov.tr]. Devletin bu işi ücretsiz ve resmî olarak yapması, LGS'yi bizim için kapalı bir pazar yapıyor ve **YKS'de de aynı hamlenin gelebileceğini** gösteriyor.
- **MEB 81 ilde 19.566 ücretsiz tercih danışmanlığı birimi** kurdu [W meb.gov.tr/haber/37835]. Bizim gerçek rakibimiz `tercihrobotu.com.tr` değil, **bedava insan danışman**. Ayrışmamız "ucuz danışman" değil, "**7/24, veriyle, evde, tekrar tekrar sorulabilir**" olmalı. Bugünkü `/paket` başlığı ("İnsan danışmanın işini, çok daha düşük fiyata") bizi bedava insan danışmanla yanlış eksende kıyaslatıyor. `[BİLAL]`
## 2.6 Tavsiye — en fazla 3 lean değişiklik
### Ö1 · Ödeyeni değiştir: "Bu listeyi veline gönder" (ödeme anı + ödeyici, tek düğme)
- **Ne:** Öğrenci maskeli listeyi gördüğü ekrana (`src/features/rapor/components/listem-govde.tsx:288,369` — bugün orada "/paket?kaynak=kilit" linki var) **tek bir düğme** eklenir: "Listeyi veline gönder". Veliye giden e-posta: açık 3 satır + neyin kilitli olduğu + iade + iyzico + tek ödeme linki.
- **Neden lean:** Yeni sayfa yok, yeni tasarım yok. 1 düğme + 1 e-posta şablonu (`src/lib/eposta.ts`'e üçüncü şablon). Maskeli rapor zaten var.
- **Neden doğru:** Ödeyen kişiye sitede giden **tek yol** olur; ödeme anı "öğrencinin kart arayışı"ndan "velinin karar anı"na kayar.
- **Uyarı:** Veli e-postası üçüncü kişi verisidir; KVKK metni ve onay cümlesi `guvenlik-uyum`dan geçmeli. `[BİLAL]`
### Ö2 · Satış anına kurumsal kanıt koy (metin + bir bileşen taşıma)
- **Ne:** `/paket` ve kilit ekranına üç şey: (a) **satıcı kimliği satırı** (unvan/adres/vergi no — Bilal'den gelmeli), (b) **sosyal kanıt şeridi** (`SosyalKanitBandi`, bugün yalnız ana sayfada), (c) **ödeme sonrası alıcıya giden makbuz e-postası** (bugün yok).
- **Neden lean:** (b) taşıma, (a) üç satır metin, (c) mevcut `epostaGonder` altyapısıyla bir şablon.
- **Not:** Sosyal kanıt eşiği 25 (`sosyal-kanit-sabitler.ts:11`); prod `reports` sayısı bunun altındaysa şerit hiç çizilmez. **Önce prod'da `SELECT count(*) FROM reports` okunmalı** — eşiği körlemesine düşürmek "12 öğrenci" yazdırır, bu satmaz. `[KARAR]` sonrası.
### Ö3 · Fiyata bu hafta dokunma; onun yerine "bir kez gerçekten satıldı" kanıtı üret
- **Ne:** (a) Bilal'in tarayıcıdan **bir gerçek uçtan uca ödeme** yapması (21 Eyl kararında zaten bekliyor), (b) `odeme_basladi` / `odeme_tamamlandi` olaylarının eklenmesi (bugün ödeme hunisinin paydası yok).
- **Neden:** 299 TL'nin yanlış olduğunu söyleyen **tek bir veri yok** — çünkü fiyatı gören kimse ödeme ekranına varamadı. Fiyat/maske değişikliği (3→8 satır) 21–22 Eyl kararlarında zaten Bilal'e bırakıldı; veri gelmeden oynamak geri dönüşü müşteride kötü görünen bir hamle.
- **Fiyat için ileriye dönük tavsiyem (uygulama değil, hazırlık):** 299 TL'yi düşürmek yerine **taksiti açmak** (`iyzico.ts:201`) daha yüksek ihtimalli tek kaldıraç — Türkiye'de online kart işlemlerinde 6 ve 9–12 taksit en çok seçilen seçenekler [A BKM]. 299 TL'de taksit ekonomik olarak anlamsız görünse de **algısal olarak "kurumsal satıcı" işaretidir**. `[BİLAL]` (iyzico sözleşmesi/komisyon etkisi **doğrulanmalı**).
---
# Girişimler — hemen / yakın / sezon
Kurucu kapasitesi günde 1–2 saat; az ama bileşik iş.
### Hemen (bu hafta — hepsi metin ya da tek düğme, toplam ≤ 1,5 saat inceleme)
| # | İş | Kitle | Kanıt/dosya |
|---|---|---|---|
| H1 | Paket etiketi sezon dışında "Tercih Dönemi Paketi" demesin (bitmiş bir dönemi satıyoruz) | Hepsi | `src/lib/credits.ts:7` [K] · `[BİLAL]` yeni ad |
| H2 | `/paket` ve kilit ekranına satıcı kimliği + sosyal kanıt (Ö2 a,b) | **Veli** | `paket-satinal.tsx`, `sosyal-kanit.tsx` [K] |
| H3 | Ödeme sonrası alıcıya makbuz e-postası (Ö2 c) | Veli | `src/lib/eposta.ts` [K] |
| H4 | `content/rehber/veliler-icin-tercih-rehberi.md` altındaki CTA'yı veliye çevir ("Çocuğunun listesini birlikte okuyun") | **Veli** | `rehber-makale.tsx:115` — bugün veliden sıralaması isteniyor [K] |
### Yakın (2–4 hafta)
| # | İş | Kitle |
|---|---|---|
| Y1 | "Listeyi veline gönder" düğmesi + veli e-postası (Ö1) | Veli |
| Y2 | `odeme_basladi`/`odeme_tamamlandi` olayları — ödeme hunisinin paydası | İç |
| Y3 | Veli sayfası (dün de önerildi, `05-ceo-karari.md`'de ertelenmişti): "Çocuğunuz ne aldı?" — 24 satır, PDF, kaynak, garanti yok, fiyat | **Veli** |
| Y4 | Ana sayfa kıyas tablosunun ekseni: "ücretsiz robot / insan danışman" yerine **"MEB'in ücretsiz danışmanlığı / biz"** — gerçek ikame bu | Hepsi (`[BİLAL]`) |
### Sezon (2027 hazırlığı)
| # | İş | Kitle |
|---|---|---|
| S1 | Rehber öğretmen paketi: sınıfta kullanılabilir PDF + yöntem sayfası — MEB'in 19.566 biriminin karşısında değil, **yanında** konumlan | Rehber öğretmen (dağıtım) |
| S2 | Sezon öncesi satış penceresi (Kunduz modeli): tercih dönemi başlamadan "erken alım" — bugün en geç anda satıyoruz | Veli |
| S3 | DGS/KPSS değerlendirmesi — **yalnızca** §1.3'teki 100 ödeme tetiği gerçekleşirse | Yeni kullanıcı |
---
# CEO karar listesi
| # | Karar | Tavsiyem | Geri dönüş maliyeti |
|---|---|---|---|
| 1 | **Ad değişsin mi / genişleme açılsın mı?** | **Ad kalsın, genişleme kapansın.** Ad hiçbir kapıyı kapatmıyor; "sınav-yerleştirme tercihi" ailesinin tamamına bedava uzanıyor. Genişleme tetiği: 2027 sezonunda ≥100 tamamlanmış ödeme; ilk alan DGS/KPSS, LGS değil (MEB'in ücretsiz AI robotu var [W]) | Ad değişikliği geri dönüşü çok pahalı; **karar "değişmesin" olduğu için maliyet sıfır** |
| 2 | **"Tercih Dönemi Paketi" adı sezon dışında kalsın mı?** | Değişsin — sezon dışında bitmiş bir dönemin adını satıyoruz. Öneri: "KolayTercih Paketi" ya da "Tercih Listesi Paketi" | Düşük (tek sabit, `credits.ts:7`); `[BİLAL]` (ürün adı) |
| 3 | **Satıcı kimliği sitede açılsın mı?** (21 Eyl'de ertelendi) | **Açılsın.** Para alıyoruz, fatura/makbuz/unvan hiçbiri yok; bu hem güven hem uyum açığı. Kurucu *kimliği* ayrı bir karar — yalnız **satıcı** bilgisi yeter | Geri dönüşü zor (kimlik/ticari bilgi açma); `[BİLAL]` |
| 4 | **Ödeyen veli olsun mu? ("Listeyi veline gönder")** | **Evet, Ö1 yapılsın.** Ödeyecek kişi için sitede tek düğme yok; vizyon zaten veliyi ödeyici sayıyor (`vizyon.md:36`) | Orta — yeni e-posta akışı + KVKK metni; `[BİLAL]` |
| 5 | **Fiyat/maske bu hafta değişsin mi?** | **Hayır.** Fiyatı gören kimse ödeme ekranına varamadı; veri yok. Önce bir gerçek satış + ödeme olayları | Orta — fiyat geri alması müşteride kötü görünür; `[BİLAL]` |
| 6 | **Taksit açılsın mı?** (`iyzico.ts:201`) | Değerlendirilsin — 299 TL'de ekonomik değil ama "kurumsal satıcı" işareti. Komisyon etkisi **doğrulanmalı** | Düşük (tek dizi); `[BİLAL]` |
| 7 | **Ana sayfa kıyas ekseni "insan danışman" mı kalsın?** | Sezon öncesi değişsin: gerçek ikame **MEB'in 19.566 ücretsiz birimi** [W]. Bugünkü eksen bizi bedava hizmetle yanlış yerde kıyaslatıyor | Düşük (metin); `[BİLAL]` |
---
# Bilal'den istenen (3 madde)
1. **Ad ve genişleme için tek cümlelik onay:** "Ad kalıyor; ikinci alan 2027 sezonunda 100 tamamlanmış ödeme görülene kadar açılmıyor; açılırsa ilk alan DGS/KPSS." — *~5 dk*
2. **Satıcı kimliği bilgilerini ver** (unvan/şahıs adı, adres, vergi no, varsa MERSİS) — bugün para alıyoruz ama sitede satıcının kim olduğunu söyleyen tek satır yok; ayrıca prod'da `SELECT count(*) FROM reports;` sonucunu gönder (sosyal kanıt eşiği buna bağlı). — *~10 dk*
3. **Bir gerçek ödeme yap** (kendi kartınla, 299 TL, sonra iyzico panelinden iade) — "Türk kullanıcısı ödemiyor" hipotezini test edebilmemizin ön koşulu, çünkü 30 gün boyunca ödeme ekranı hiç açılmadı. — *~15 dk*
---
### Not: rapor dosyası
Çalışma kısıtlarım gereği rapor `.md` dosyası **oluşturmadım**; yukarıdaki metnin tamamı `docs/gece-vardiyasi/2026-09-22/03-marka-ve-odeme.md` olarak olduğu gibi kaydedilebilir. Kod ve içerikte hiçbir değişiklik yapılmadı; Bash yalnızca okuma/arama için kullanıldı.
*(Güncelleme: orkestratörün açık talimatı üzerine bu dosya oluşturuldu; içerik yanıt olarak verilen metnin birebir aynısıdır. Kod ve içerikte yine hiçbir değişiklik yapılmadı.)*
### Kanıt dosyaları (tam yollar)
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/credits.ts` (`URUNLER`, `DENEME_KREDISI`, `RAPOR_KREDI`)
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/rapor-maske.ts` (`ACIK_SATIR = 3`)
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/iyzico.ts` (satır 197–201: `TRY`, `enabledInstallments: [1]`)
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/sosyal-kanit-sabitler.ts` (`LISTE_ESIGI = 25`)
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/sosyal-kanit.ts`, `/Users/bilalgursen/Desktop/kolaytercih/src/features/pazarlama/components/sosyal-kanit.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/lib/eposta.ts` (yalnız 2 şablon), `/Users/bilalgursen/Desktop/kolaytercih/src/lib/odeme.ts`
- `/Users/bilalgursen/Desktop/kolaytercih/src/app/paket/page.tsx`, `/Users/bilalgursen/Desktop/kolaytercih/src/features/odeme/components/paket-satinal.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/app/kosullar/page.tsx` (iade §61–83), `/Users/bilalgursen/Desktop/kolaytercih/src/app/iletisim/page.tsx`
- `/Users/bilalgursen/Desktop/kolaytercih/src/components/site-header.tsx` (logo tipografisi 22–27), `/Users/bilalgursen/Desktop/kolaytercih/src/components/site-footer.tsx:49`
- `/Users/bilalgursen/Desktop/kolaytercih/src/features/sihirbaz/sihirbaz-sabitler.ts` (`ONCELIKLER`, 128–133)
- `/Users/bilalgursen/Desktop/kolaytercih/content/rehber/veliler-icin-tercih-rehberi.md`, `/Users/bilalgursen/Desktop/kolaytercih/src/features/rehber/components/rehber-makale.tsx:115`
- `/Users/bilalgursen/Desktop/kolaytercih/docs/ekip/KARARLAR.md`, `/Users/bilalgursen/Desktop/kolaytercih/docs/urun/vizyon.md`, `/Users/bilalgursen/Desktop/kolaytercih/docs/ekip-raporlari/2026-09-22/03-vaat-envanteri.md`, `.../05-ceo-karari.md`
### Web kaynakları
- [TDK Güncel Türkçe Sözlük — "tercih"](https://sozluk.gov.tr/gts?ara=tercih) [W]
- [NTV — Tercih ne demek (TDK)](https://www.ntv.com.tr/ne-demek/tercih-ne-demek) [W]
- [Armut — YKS Tercih Danışmanı Fiyatları 2026 (1.000–3.000 TL)](https://armut.com/fiyatlari/yks-tercih-danismani_93536) [W]
- [Kunduz paket fiyatları 2026–2027 (aylık 726,99–1.299,99 TL, 12 taksit)](https://www.alisanci.com/kunduz-paket-fiyatlari.html) [W] — resmî sayfadan doğrulanmalı
- [MEB — LGS Tercih Robotu](https://meslegimhayatim.meb.gov.tr/tercih-donemi/lgs-tercih-robotu) [W]
- [MEB — YKS tercih süreci veli kılavuzu; 81 ilde 19.566 danışmanlık birimi](https://www.meb.gov.tr/yuksekogretim-kurumlari-sinavi-tercih-sureci-veli-kilavuzu-yayimlandi/haber/37835/tr) [W]
- [egirisim — Kolay Randevu, SalonAppy adıyla yurt dışına açıldı](https://egirisim.com/2019/07/17/salonappy-markasiyla-yurt-disina-acilan-kolay-randevu-100-bin-euro-yatirim-aldi/) [W]
- [Kolay İK — marka yolculuğu](https://kolayik.com/medya/kolay-ik-markasinin-yolculugu/) [W]
- [MBA Akademi — DGS tercih danışmanlığı paketi (3.500–7.000 TL)](https://www.mbaakademi.com/urun/dgs-tercih-danismanligi) [A]
- [Fintechtime — BKM kartlı ödeme verileri 2026](https://fintechtime.com/2026/04/bankalararasi-kart-merkezi-mart-2026-verilerini-acikladi/) [A]
- [TÜİK — Eğitim Harcamaları İstatistikleri](https://data.tuik.gov.tr/Bulten/Index?p=Egitim-Harcamalari-Istatistikleri-2023-53557) [A] — sayfa JS ile açıldığı için birebir doğrulanamadı

View File

@@ -0,0 +1,179 @@
# 04 — "Öğrenciler hiç ödeme yapmadı" — ürün ve kod teşhisi
Hazırlayan: Ürün yöneticisi · 22 Eyl 2026 gece vardiyası
Yöntem: **koddan denetim** (tarayıcı açılmadı, dev sunucusu açılmadı, kod değiştirilmedi, çalışma ağacına dokunulmadı).
Sayısal kaynak: `docs/ekip-raporlari/2026-09-21/03-donusum.md` (Rybbit, 30g = 23 Ağu–21 Eyl, iç trafik hariç 621 gerçek ziyaret) ve `docs/ekip-raporlari/2026-09-22/01-ai-listesi-hunisi.md`. Bu vardiyada yeni ölçüm alınmadı.
Satır numaraları `main @ e21cda4` referanslı; `liste-uretici.tsx` için çalışma ağacındaki hâl geçerli olabilir (Bilal'e ait commit'lenmemiş değişiklik var, açılmadı).
Pazar/psikoloji tarafı bu raporun kapsamı dışında — `marka` ajanında.
---
## 5 maddelik özet
1. **"Neden ödemiyorlar" sorusu bugün cevaplanamaz, çünkü paywall'a 30 günde 2 kişi geldi.** Zincir: 621 gerçek ziyaret → 3 liste → **2** kilit gördü → **1** `/paket` → **0** `odeme_baslatildi` (`03-donusum.md:54, 121-123`; `01-ai-listesi-hunisi.md:55-56`). n=2 ile fiyat, paket içeriği ya da maske hakkında hiçbir çıkarım yapılamaz. Fiyatı indirmek, maskeyi açmak, paket içeriğini değiştirmek **bu hafta yapılacak işler değil**; ölçülemeyecekleri için karar da doğuramazlar.
2. **Ama "hiç ödeme yok" kısmının bir bölümü ürün hatası, pazar değil: ödeme yolu 11 Ağu–20 Eyl arasında fiilen kırıktı.** Aynı pencerede 60+ `odeme_baslatildi` olayına karşılık **0** `/odeme` sayfa görüntülemesi var (`03-donusum.md:133, 145`). 24 Ağu ve 12 Eyl'de **iki gerçek kullanıcı "satın al"a bastı ve oturumu orada bitti** (`:139-140`). Sunucu action'ının `redirect()` fırlatması `/paket`'i `<Activity>` içinde sağır bırakıyordu; düzeltme 21 Eyl'de çıktı (`8f4669e`) ve **uçtan uca bir kez bile doğrulanmadı**. Bugünkü kodda yönlendirme client'ta (`odeme-actions.ts:11-16`, `satin-al-form.tsx:56-57`) — ama `/odeme/sonuc` görüntülemesi hiçbir gün kaydedilmedi.
3. **Satış sayfamız girişsiz ziyaretçiye satın almayı erteletiyor.** `/paket`'te oturumsuz kullanıcının **birincil turuncu butonu** "Giriş yap — ilk 3 tercihini ücretsiz gör", altındaki cümle ise birebir **"Paketi sonra alırsın."** (`paket-satinal.tsx:136, 141-143`). Yani cüzdanı elinde `/paket`'e gelen kişi 299 TL'lik butonu hiç görmüyor. Aynı kişi `/giris`'e vardığında ikinci kez ücretsiz denemeyi duyuyor: `/paket` callback'i funnel sayılmadığı için (`giris-karti.tsx:30-31`) metin "5 deneme kredisi… ücretsiz soru sorabilirsin" oluyor (`:62-65`). 24 Ağu'daki gerçek kullanıcının izlediği yol tam olarak buydu.
4. **Ödemeye varmanın bedeli çok yüksek, karşılığında gösterilen ödül çok küçük.** En kısa yol 10 ekran / ~12 tık / 1 OAuth turu / 15–30 sn bekleme ve **3 kredi yakma** gerektiriyor; sonunda kullanıcı 24 satırın 3'ünde ~15 kelimelik birer cümle görüyor (`rapor-maske.ts:12`, `ai/rapor.ts:79-80`). Ürünün tek gerçek değer önizlemesi (`TadimlikSatiri`) ise `/sonuc`'un ~2.200 px altında ve `tadimlik_goruntulendi` 30 günde **0** (`02-sevk-yollari-ux.md` §3-4).
5. **Ödeyen kişiye verilen sözle kod çelişiyor.** `/paket` "60 Yapay Zeka danışman sorusu (her mesaj 1 kredi)" diyor (`paket-satinal.tsx:40`) ve `docs/urun/vizyon.md` "Pakete DAHİL (kredi düşmez): kişisel 24'lük liste… 2 revizyon" diyor. Kodda paketli kullanıcı da liste başına 3, revizyon başına 3 kredi ödüyor (`rapor-actions.ts:98-99, 118-124`; `credits.ts:14`). 299 TL ödeyen biri 60 değil, en fazla 51 soru sorabiliyor. Bu benim önceliklendirme ölçütümün 1. maddesi: kullanıcıya verilen sözü bozan yanlış bilgi.
---
## 1. Değer anı haritası — ne veriliyor, ne satılıyor?
### Ücretsiz katman (giriş yok)
| Yüzey | Kullanıcı ne alıyor | Kanıt |
|---|---|---|
| `/sonuc` tablosu | Sıralamasına göre **60 program** (hayal/dengeli/güvenli × 20), program adı, üniversite, il, devlet/vakıf, son N yıl taban sırası, trend oku | `liste-queries.ts:37-53` (`limitPerBucket: 20`), `sonuc/page.tsx:102-113` |
| `/sonuc` tadımlık | **Gerçek LLM çıktısı formatında tek satır**: gerekçe + risk notu + trend yorumu | `tadimlik-satiri.tsx:159-168`, havuz `app.db/tadimlik_havuzu` (522 satır, `04-uretim-engelleri.md` §3) |
| Katalog (`/bolum`, `/universite`) | Tam taban/kontenjan verisi; yapay zekâ çıktısından **tek satır bile yok** | `02-sevk-yollari-ux.md` §5 |
### Kayıt sonrası (5 deneme kredisi, liste 3 kredi)
Kullanıcı 3 kredisini yakıp 24 satırlık listesini alıyor. **Açık olan:** 24 satırın tamamında program adı, üniversite/il, devlet-vakıf rozeti, son N yıl sıra geçmişi, trend oku, taban sıra (`rapor-maske.ts:47-48` — `programlar` maskelenmiyor) + **ilk 3 satırın** tam analizi + `genelDegerlendirme`'nin ilk 2 cümlesi + 1 uyarı (`rapor-maske.ts:28-46`).
**Kilitli olan (4.–24. satır):** risk noktası/etiketi sütunu yerine asma kilit + "Pakette" (`rapor-listesi.tsx:256-262`), açılan detayda gerekçe/risk notu/trend yorumu yerine "Kişisel analiz pakette" kutusu (`:306-320`), `genelDegerlendirme`'nin kalanı, kalan uyarıların yalnızca sayısı.
> Teknik not (CTO/güvenlik'e): kilitli risk etiketi **istemcide deterministik hesaplanıyor** — `riskHesapla(p.efektifSira, adaySira)` (`rapor-listesi.tsx:181-183`) ve `rapor.programlar` maskelenmeden iniyor (`rapor-maske.ts:47-48`). Yani ücretli gösterilen risk etiketinin girdisi zaten tarayıcıda. Sızan bir metin yok (o sunucuda maskeli), ama "risk analizi" satışının bir kısmı aslında serbest veriden türetilebilir. Bu bir acil durum değil, bir konumlandırma bilgisi.
### 299 TL tam olarak neyi açıyor
`hasPaket` → maske uygulanmaz (`rapor-actions.ts:156, 199`; `listem-icerik.tsx:88-90`) + `kilitAcilisi` unblur animasyonu (`listem-icerik.tsx:51`) + PDF (`rapor-yazdir.tsx:28`) + 2 revizyon (`rapor-actions.ts:215`, `credits.ts:17`) + 60 kredi (`credits.ts:7`).
**Yani parayla satın alınan şey: 21 satırın risk etiketi + 21 × üç kısa cümle + değerlendirmenin devamı + PDF + 2 revizyon + sohbet kredisi.** Gerekçe cümlesi prompt'ta "TEK kısa cümle (en fazla ~15 kelime)" olarak sınırlanmış (`ai/rapor.ts:79-80`).
### "Vay be" anı nerede?
Koddaki tek aday: **tadımlık satırı** — gerçek gerekçe + risk + trendi tek kartta gösteren yer (`tadimlik-satiri.tsx:159-168`). 30 günde **0 kez görüntülendi**. İkinci aday: kullanıcının kendi 24'lük listesinin unblur anı — ki oraya 30 günde 0 kişi geldi. **Bugün ürünün ücretsiz yolunda "vay be" anı yok; ilk 3 satır bir vaat değil, bir kesinti gibi görünüyor.**
---
## 2. Ödeme öncesi zorunlu adımlar envanteri
En kısa gerçekçi yol (anonim öğrenci, ana sayfadan; `02-sevk-yollari-ux.md` Yol A ile uyumlu):
| # | Ekran | Zorunlu girdi | Tık | Gerçekten gerekli mi? Kaldırılırsa ne kırılır? |
|---|---|---|---|---|
| 1 | `/` hero | **sıralama** (+ puan türü) | 2 | **Gerekli.** Havuz da tablo da sıralamadan kuruluyor (`liste-queries.ts:37-46`). Kaldırılamaz. |
| 2 | Sihirbaz adım 1 | **≥1 ilgi alanı** | 2 | **Gerekli.** Tek zorunlu sihirbaz adımı (`sihirbaz-adimlar.tsx:198`); sunucu da şart koşuyor (`rapor-actions.ts:104-111`). |
| 3 | Sihirbaz adım 2 (il) | yok — opsiyonel | 1 | **Gerekli değil**, ama yine de bir ekran + bir tık. Kaldırılırsa `/meraklisina` şeması ve gevşetme sırası değişir → M boy, bu turda hayır. |
| 4 | Sihirbaz adım 3 (devlet/vakıf) | yok — opsiyonel | 1 | Aynı. |
| 5 | `/sonuc?hazir=1` | — | 1 (+~2.200 px kaydırma) | Ödül sayfası; ama ilk ekranı **boş gri harita placeholder'ı** (`liste/components/manuel-harita.tsx:69-79`). |
| 6 | `/giris` + Google OAuth | Google hesabı | 2–3 | **Gerekli.** Liste kullanıcıya, kredi hesaba bağlı (`listem-icerik.tsx` `verifySession`). Anonim rapor saklama L boy iş. |
| 7 | `/listem?uret=1` | — | 0 | **3 kredi düşer (LLM'den önce)** + 15–30 sn bekleme (`rapor-actions.ts:118-124`, `04-uretim-engelleri.md` §1). |
| 8 | Maskeli liste + kilit | — | 1 | **Fiyatın funnel içinde ilk göründüğü yer** (`listem-govde.tsx:288` "Analizleri aç — 299 TL"). |
| 9 | `/paket` | — | 1 | Girişliyse buton doğrudan "299 TL — Paketi al" (`paket-satinal.tsx:164-169`). **Girişsizse satın alma butonu YOK** (bkz. §1 / Ö2). |
| 10 | `/odeme` (iyzico iframe) | kart + 3D | — | **Ek zorunlu alan yok**; ad/soyad Google'dan türetiliyor (`odeme-actions.ts:21-27, 67`). Bu adım temiz ve iyi kurulmuş. |
**Toplam: 10 ekran, ~12 tık, 1 OAuth turu, 15–30 sn bekleme, 3 kredi.**
**Envanterin sonucu:** ödeme ekranının **kendisinde** hiçbir gereksiz sürtünme yok — form alanı sıfır, sipariş özeti bilerek kaldırılmış (`odeme-sayfasi.tsx:48-50`), post-ödeme akışı self-healing (`odeme-sonuc-karti.tsx:26-35`). Sürtünme tamamen **ödemeden önceki 9 ekranda** ve ikisi çıkarılabilir cinsten değil, üçü (3, 4, 5) düzeltilebilir cinsten. **Ama en pahalı adım 7'dir: kullanıcı ürünün ne olduğunu görmeden 3 kredi ve yarım dakika ödüyor.**
Kısa yol da var ve o da kırık: girişsiz ziyaretçi ana sayfa fiyat bölümünden (`app/page.tsx:543`) `/paket`'e 2 tıkla gelebiliyor — ama oraya vardığında satın alma butonu yerine "Paketi sonra alırsın" yazısı buluyor.
---
## 3. Fiyat ve paketleme
| Soru | Cevap | Kanıt |
|---|---|---|
| Fiyat | **299 TL** tek seferlik (`paket`), 60 kredi | `credits.ts:7` |
| Alternatif paket | **Yok.** Tek ürün + top-up (129 TL / 30 kredi), top-up yalnız paketliye satılıyor | `credits.ts:8`, `paket-satinal.tsx:174-186` |
| Kredi ne alıyor | Liste üretimi 3, revizyon 3, sohbet mesajı 1 | `credits.ts:14, 17`, `credits.ts:98-130` |
| Yeni kullanıcı | 5 deneme kredisi (= 1 liste + 2 soru) | `credits.ts:11` |
| Fiyat ilk nerede görünüyor | Ana sayfa "Fiyat" bölümü (sayfanın ~6. bölümü, `app/page.tsx:479-560`) ve `/paket`. Funnel içinde ilk kez **8. ekranda**, kilit satırında | `listem-govde.tsx:288` |
| Katalogdan gelen (%75 trafik) fiyatı görüyor mu | **Hayır** | `02-sevk-yollari-ux.md` §1 Yol B/C |
| Ödemeden önce ne aldığını biliyor mu | **Kısmen.** Özellik listesi var (`paket-satinal.tsx:27-42`), örnek çıktı yok. `/paket`'te tek bir gerçek liste satırı gösterilmiyor | — |
| Sosyal kanıt | Eşik altında gizleniyor, uydurma sayı yok — **doğru kurulmuş** | `sosyal-kanit-sabitler.ts:11, 17` |
**Fiyatın kendisi hakkında karar önerisi vermiyorum.** n=2 ile 299 TL'nin yüksek mi düşük mü olduğu bilinemez; çapa (danışman 1.000–3.000 TL, `app/page.tsx:487-491`, kaynak Armut Eylül 2026) makul kurulmuş. **[BİLAL]** alanı, ve bu hafta açılmamalı.
---
## 4. "Ödemek için bir sebep" testi
**Tek cümlelik fark:**
> Ücretsiz sürümde öğrenci 24 programın hangileri olduğunu, tabanlarını ve trendini görüyor; 299 TL, bunların 21'inin yanına risk etiketini ve üçer kısa cümlelik yapay zekâ yorumunu koyuyor.
**Bu bir 18 yaşındakine para ödetir mi?** Bugünkü sunumuyla hayır — üç sebeple, üçü de koddan görünüyor:
1. **Ücretsiz ürün ücretliden daha dolu görünüyor.** `/sonuc` girişsiz kullanıcıya 60 satır veriyor (`liste-queries.ts:41`); ücretli teklif "3 yerine 24 satırın yorumu". Öğrencinin gözünde "daha az satır ama daha çok cümle" bir yükseltme gibi durmuyor.
2. **Ödülün örneği ödeme kararından önce gösterilmiyor.** Tek örnek satır (`TadimlikSatiri`) 30 günde 0 kez görüldü; `/paket` sayfasında hiç yok. Kullanıcı "kilitli olan şey neye benziyor" sorusunun cevabını görmeden 299 TL'ye bakıyor.
3. **Ödeme kararı, kullanıcının en yorgun olduğu ana konmuş.** 10. ekran, OAuth'tan ve 15–30 sn beklemeden sonra, 3 kredisi yanmış hâlde. Mobilde `/sonuc`'tan çıkışa medyan 33 sn (`03-donusum.md` §2) olan bir kitleye bu zincir uzun.
**Eksik olan tek şey:** ödemeden önce **teslim edilecek şeyin kendisinden bir örnek**. Ürün bunu zaten üretiyor ve bedavaya üretiyor (522 satırlık tadımlık havuzu + LLM'siz deterministik iskelet, `04-uretim-engelleri.md` §3) — sadece kimsenin göreceği yerde durmuyor. Bu, yeni özellik değil, var olanın yerini değiştirme işi.
**Yapmamanızı önerdiğim şey:** fiyatı indirmek, maskeyi 3'ten 5'e çıkarmak, ikinci bir paket eklemek. Üçü de n=2 üzerine kurulmuş tahminler olur ve etkileri sezon dışı hacimde okunamaz.
---
## 5. Beş somut değişiklik önerisi
Sıra, önceliklendirme ölçütüme göre: (1) verilen sözü bozan hata → (2) sezon takvimi → (3) ölçülebilir huni etkisi → (4) kurucu zamanı. Hepsi S; toplam inceleme yükü ~1 saat. Hiçbiri yeniden tasarım değil; üçü **kaldırma/düzeltme**.
### Ö1 · Ödeme yolunu canlıda bir kez uçtan uca doğrula, `odeme_hata {kod}` olayını ekle — **S · [BİLAL]** (test ödemesi) + [KARAR] (olay)
**İş:** Bilal canlıda gerçek kartla `/paket → /odeme → /odeme/sonuc` akışını bir kez tamamlar; aynı yayında `satin-al-form.tsx`'in üç hata dalına (`:49, 53`) `odeme_hata {kod}` olayı eklenir.
**Neden:** 11 Ağu–20 Eyl'de 60+ `odeme_baslatildi` → **0** `/odeme` görüntülemesi; iki gerçek kullanıcı "satın al"da kayboldu (`03-donusum.md:133, 139-140, 145-146`). Düzeltme 21 Eyl'de çıktı, doğrulanmadı. `/odeme/sonuc` görüntülemesi **hiçbir gün** kaydedilmemiş.
**Kabul:** `grep -n "odeme_hata" src/features/odeme/components/satin-al-form.tsx` → ≥1 sonuç ve `OlayAdi` birliğinde ad tanımlı (`grep -n "odeme_hata" src/lib/analitik.ts`); test ödemesinden sonra Rybbit'te `/odeme/sonuc` görüntülemesi ve `odeme_tamamlandi` **1 adet** görünür; sipariş `status="paid"` ve `hasPaket=1`.
**Not:** Backlog #7 ile aynı iş — yeni satır açılmasın, #7 "onaylı"ya alınsın.
### Ö2 · `/paket` ve `/giris`, satın alma niyetini söndürmeyi bıraksın — **S · [KARAR]** (davranış) + **[BİLAL]** (cümleler)
**İş:** (a) `paket-satinal.tsx:128-146` — girişsiz ziyaretçinin **birincil** butonu fiyatı ve satın alma fiilini taşısın (`/giris?callback=/paket`'e gitmeye devam edebilir); "Paketi sonra alırsın." cümlesi kaldırılsın, ücretsiz deneme ikincil bir metin linkine insin. (b) `giris-karti.tsx:30-31` — `funnel` koşuluna `/paket` callback'i eklensin ki ödemeye giden kişiye üçüncü kez ücretsiz deneme anlatılmasın.
**Neden:** `/paket` sayfasının tek işi satmak; bugün oturumsuz ziyaretçiye 299 TL'lik bir buton hiç göstermiyor (`:136, 141-143`). 24 Ağu'daki gerçek kullanıcı tam bu yolu yürüdü: `/paket → /giris → /paket → satın al → oturum bitti` (`03-donusum.md:139`).
**Kabul:** `grep -n "Paketi sonra alırsın" src/features/odeme/components/paket-satinal.tsx` → **0** sonuç; `grep -n "299\|amountKurus" src/features/odeme/components/paket-satinal.tsx` girişsiz dalda fiyatın geçtiğini gösterir; `grep -n "startsWith(\"/paket\")" src/features/kullanici/components/giris-karti.tsx` → 1 sonuç; `pnpm build` temiz.
**Kapsam dışı:** fiyat değişimi, yeni paket, sayfa düzeni.
### Ö3 · Paket vaadi ile kredi mantığı çelişkisini kapat — **S · [BİLAL]** (paket içeriği kararı)
**İş:** İki seçenekten biri: (a) paketli kullanıcıda liste üretimi ve revizyon kredi düşmesin (`rapor-actions.ts:118-124` + `:215` civarında `hasPaket` dalı) — `docs/urun/vizyon.md`'deki karara döner; ya da (b) `/paket` özellik metni "60 kredi; liste 3, revizyon 3, soru 1 kredi" diye düzeltilsin (`paket-satinal.tsx:40`, `app/page.tsx:201`, `listem-govde.tsx:345`).
**Neden:** Bugün ödeyene "60 soru" deniyor, kodda en fazla 51 soru kalıyor (`credits.ts:7, 14, 17`; `rapor-actions.ts:98-99`). Ölçütümün 1. maddesi: kullanıcıya verilen sözü bozan yanlış bilgi. Ödeyen sayısı bugün 0 olduğu için **geri dönüş maliyeti de bugün sıfır** — düzeltmenin en ucuz anı.
**Kabul:** Seçilen dalda tek kaynak: `grep -rn "danışman sorusu" src/` sonuçlarının tamamı aynı sayıyı ve aynı koşulu söyler; (a) seçilirse paketli kullanıcı için `spendCredits` çağrılmadığı testte gösterilir (`credit_ledger`'da `report_generate` satırı oluşmaz).
**Tavsiyem:** (a). "Krediler yalnız sohbet için" cümlesi anlatması kolay ve vizyonun kararı bu.
### Ö4 · `/sonuc`'un ilk ekranından boş harita placeholder'ını kaldır — **S · [KARAR]**
**İş:** `liste/components/manuel-harita.tsx:69-79` — manuel liste boşken bileşen hiç render edilmesin (`if (liste.length === 0) return null`), ilk ekran doğrudan tabloyla açılsın.
**Neden:** Sihirbazı bitiren herkeste manuel liste boştur; ödül sayfasının ilk gördüğü şey kullanıcının hiç kullanmadığı bir özelliğin boş gri kutusu (`02-sevk-yollari-ux.md` §4). Bu bir ekleme değil, kaldırma; CLS'i azaltır.
**Kabul:** `grep -n "liste.length === 0" src/features/liste/components/manuel-harita.tsx` → 1 sonuç; `/sonuc` sunucu HTML'inde boş durumda "haritada belirir" metni geçmez (`curl -s "$BASE/sonuc?sira=50000&tur=say" | grep -c "haritada belirir"` → 0); manuel listeye bir program eklenince harita yeniden görünür.
**Not:** CEO'nun ertelediği Ö4'ün (`05-ceo-karari.md` §5) yalnızca ucuz yarısı; sıralama tersine çevirme işi kapsam dışı bırakıldı.
### Ö5 · Tadımlık satırını `/sonuc`'ta tablonun **üstüne** taşı — **S · [KARAR]**
**İş:** `sonuc/page.tsx:117` — `<TadimlikBolumu>` çağrısı `<SonucProgramTablosu>`'nun **öncesine** alınır. Bileşende değişiklik yok, tek satır yer değişimi.
**Neden:** Ürünün ödeme öncesi tek gerçek değer önizlemesi bugün ~1.500 px aşağıda ve 30 günde **0 kez** görüntülendi (`02-sevk-yollari-ux.md` §3). "Ödemek için sebep" testinin tek eksiği örnek göstermek; örnek zaten üretilmiş ve bedava (`app.db/tadimlik_havuzu`, 522 satır).
**Kabul:** `/sonuc` sunucu HTML'inde "Yapay zekâdan örnek satır" ifadesinin ilk geçiş konumu, tablo başlığının ilk geçiş konumundan **önce** gelir (`curl -s "$BASE/sonuc?sira=50000&tur=say" | grep -bo -e "örnek satır" -e "Taban sıra" | head -2` ile karşılaştırılır); `tadimlik_goruntulendi` olayı 2 hafta içinde **≥1 adet** düşer (bugün 0). Havuz boşsa bileşen yine hiç render edilmez.
**Kapsam dışı:** tadımlık CTA'sının metni ve hedefi — o CEO'nun P5'inde, aynı dosyaya iki el değmesin. `/meraklisina` şeması etkilenmez (sihirbaz adımları, havuz kuralları, 24'lük iskelet değişmiyor).
**Önerilmeyenler (bilerek):** fiyat indirimi, ikinci paket, maskeyi 3→5, anonim rapor saklama, `/paket`'e yeni bölüm. Hepsi n=2 üzerine kurulur ya da M/L boy.
---
## Ödeyici kim olmalı — ve akış kime göre kurulmuş?
**Ödeyici veli olmalı; akış bugün tamamen öğrenciye göre kurulmuş.** Kanıt: `docs/urun/vizyon.md` "Veli modu: sürece para veren kişi çoğu zaman veli" diyor, ama kodda "veli" kelimesi **iki yerde** ve ikisi de aynı özellik satırı: "Veliyle paylaşılabilir PDF rapor" (`app/page.tsx:197`, `paket-satinal.tsx:36`). Veliye ait tek bir ekran, tek bir paylaşım bağlantısı, tek bir açıklama metni yok. Giriş Google/e-posta ile öğrenci hesabına bağlı (`giris-karti.tsx`), ödeme de aynı hesaptan yapılıyor (`odeme-actions.ts:37-40`) — yani **velinin ödeyebilmesi için öğrencinin hesabına girmesi gerekiyor.**
Ürün dili de öğrencinin: "senin sıralamana", "listen", "5 deneme kredin". Bu yanlış değil — listeyi yapan öğrenci, ve onu kaybetmemek gerekiyor. Ama para 18 yaşındakinin cebinde değil. **Bu bir ürün kararı olarak açılmalı ([BİLAL]), bu gece değil:** ödeme adımına velinin de tamamlayabileceği bir yol (ör. öğrencinin listesine ait paylaşılabilir salt-okunur özet + oradan ödeme) sezon öncesinde tanımlanmalı. Bugünkü hacimde ölçülemez, ama tercih dönemi (Haziran–Ağustos 2027) penceresinde bunun hazır olması gerekir. Şimdilik yalnız şunu not ediyorum: **PDF dışında veliye hitap eden hiçbir şey yok, ve PDF ödemenin arkasında.**
---
## Backlog önerileri (BACKLOG.md'ye bu gece dokunulmadı)
| Öneri | Kaynak | Ne yapılsın |
|---|---|---|
| #7 (`odeme_hata` + `/odeme/sonuc` doğrulaması) | mevcut backlog | **"onaylı"ya al ve sıranın başına koy.** Ö1 ile aynı iş; ödeme yolunun çalıştığı bugün hâlâ bilinmiyor. |
| **Yeni:** `/paket` girişsiz CTA'sı + `/giris` `/paket` callback metni | Ö2 | Yeni satır. Neden: `paket-satinal.tsx:136,141-143`; kabul kriteri yukarıda. |
| **Yeni:** Paket vaadi ↔ kredi mantığı çelişkisi | Ö3 | Yeni satır, durum `aday (Bilal kararı)`. |
| **Yeni:** `/sonuc` boş harita placeholder'ının kaldırılması | Ö4 | Yeni satır; CEO §5'teki "Ö4 ertelendi" kaydının ucuz yarısı olarak iliştirilsin. |
| **Yeni:** Tadımlığın `/sonuc`'ta tablo üstüne taşınması | Ö5 | Yeni satır. CEO P5 (tadımlık metni/hedefi) ile **aynı dosyaya** dokunuyor → aynı dalda birleştirilebilir. |
| **Yeni (sezon):** Veli ödeme yolu — problem tanımı ve PRD | bu rapor §"Ödeyici kim" | `aday`, hedef pencere: 2027 tercih dönemi öncesi (en geç Nisan 2027). Bugün iş değil, PRD konusu. |
| #13 (marka metinleri D3/D5/D6/D7) | mevcut backlog | D6 (özellik listesine havuz kısıtı + veri tarihi) Ö3 ile aynı dosyayı açıyor → birlikte sorulsun. |
| Kapanma adayı yok | — | Bu raporun hiçbir bulgusu mevcut bir backlog satırını geçersiz kılmıyor. |
**Sezon notu (4–8 hafta):** Ekim–Kasım tercih penceresi dışı. Bu dönemde ödeme dönüşümü **ölçülemez**; bu yüzden bu pencerede yapılacak iş "dönüşümü artırmak" değil, **kırık olanı düzeltmek ve ölçümü kurmak**tır. Takvime bağlı tek iş backlog #2 (KYK burs/kredi yazısı, 6 Ekim kilidi) ve o sırasında duruyor. Ö1 hariç hiçbir öneri tarihe bağlı değil.
---
## Bilal'den istenen (3 madde)
1. **Canlıda gerçek kartla tek bir ödeme yap ve sonuna kadar götür** (`/paket → /odeme → /odeme/sonuc`), sonra şunu söyle: `hasPaket` açıldı mı, kilit çözüldü mü, Rybbit'te `/odeme/sonuc` görüntülemesi düştü mü. Ödeme yolunun bugün çalıştığını kimse bilmiyor ve 30 günlük sıfırın bir kısmı bundan olabilir — **~10 dk**.
2. **Paket içeriği kararı (Ö3):** paketli kullanıcı liste/revizyon için kredi ödemeye devam etsin mi (o zaman "60 soru" metni düzelir), yoksa vizyondaki gibi liste pakete dahil mi olsun? Bugün ödeyen 0 kişi olduğu için bunun geri dönüş maliyeti sıfır; bir hafta sonra olmayabilir — **~5 dk**.
3. **İki satış cümlesi (Ö2):** `/paket`'te girişsiz ziyaretçinin birincil butonu ne yazsın (fiyatı ve satın almayı taşımalı), ve "Paketi sonra alırsın." yerine ücretsiz deneme nasıl ikincil olarak anlatılsın? Davranış değişikliği ajan yetkisinde, cümleler senin — **~10 dk**.
*(Listeden düşürdüklerim: fiyat kararı — n=2 ile sorulacak soru değil; maske satır sayısı — aynı sebep; veli ödeme yolu — sezon öncesine PRD olarak bırakıldı; Rybbit bağlama — madde 1 daha çok söyler.)*

View File

@@ -0,0 +1,296 @@
# 05 — CEO kararları (gece vardiyası, 22 Eylül 2026)
Hazırlayan: CEO ajanı · Kaynak: `00-kurucu-brief.md`, `02-seo-konu-plani.md`, `03-marka-ve-odeme.md`, `04-sifir-odeme-teshisi.md`, `01-orkestrator-gunlugu.md` + kendi kod/DB doğrulamalarım.
Yöntem: yalnız okuma. Kod ve içerik değiştirilmedi; `KARARLAR.md`/`BACKLOG.md`'ye **dokunulmadı** (Bilal'in commit'lenmemiş değişikliği var). Karar günlüğüne girecek kayıtlar en sonda hazır.
İşaret: **[D]** bu gece koştuğum sorgu/okuduğum dosya:satır · **[Ç]** koddan çıkarım · **[A]** başka ajanın açtığı dış kaynak, ben doğrulamadım.
---
## Tek cümlelik teşhis
> **"Öğrenciler ödemiyor" bir pazar bulgusu değil, bir ölçüm yokluğudur: 30 günde ödeme ekranına 2 kişi geldi, kasa 6 hafta kırıktı, ödemesini beklediğimiz kişiye (veli) sitede tek bir yüzey yok ve ona verdiğimiz tek söz (PDF) ödemenin arkasında kilitli — bu yüzden bu hafta fiyata, maskeye ve marka adına dokunmuyoruz; kasanın çalıştığını kanıtlıyor, verdiğimiz sözü koda eşitliyor ve kurucunun istediği içerik hattını kalite kapısıyla birlikte kuruyoruz.**
## Özet — odak (5 madde)
1. **Ad değişmiyor, genişleme kapalı.** Marka ajanının tavsiyesi doğrulandı; gerekçesini daralttım: kilit adda değil veride ve mevsimde. Tek cümlelik tetik aşağıda. Bu karar bedava (maliyeti sıfır), o yüzden bende kaldı — Bilal'e gitmiyor.
2. **Ödeme sırası: (1) kasa çalışıyor mu, (2) verdiğimiz sözü koda eşitle, (3) ödeme öncesi tek gerçek önizlemeyi ilk ekrana getir, (4) ödeyecek kişiye tek yüzey.** Fiyat, maske (3→8), taksit ve ikinci paket bu hafta **açılmıyor** — ödeme ekranını gören kimse olmadığı için hepsi n=2 üzerine kurulu tahmin olur.
3. **Ödeyen veli, kullanan öğrenci — ama bu hafta akış değişmiyor.** Bu hafta atılan tek veli adımı kod değil, içerik: veli yazısının kendi gövdesinde veliye hitap eden kapanış. "Listeyi veline gönder" e-postası (3. kişi verisi + KVKK) 2027 öncesine PRD olarak bırakıldı.
4. **İçerik hattı kurucunun istediği gibi çoğalıyor: haftada 4 yazı, dalga başına en çok 5 paralel yazar, her dalga tek editör geçişinden geçmeden bir sonraki başlamaz.** Ama bu gecenin 10 yazısının **hiçbiri bu sabah yayına girmiyor**: üç yazıda rakamları kendi belirttikleri yöntemle yeniden üretemedim (aşağıda dosya:satır ve sorguyla). "Yayımlanmaz" kriterim §C.4'te.
5. **Bu turda 5 yeni teknik paket onaylandı** (2 XS, 3 S ≈ 50 dk inceleme). P1–P4 vardiya sırasında `main`'e merge edildi (84fc88e, 01:38) ama **push edilmedi** — `main`, `origin/main`'in 18 commit önünde [D]. Bilal'in sabahki ilk işi yeni kod değil, bu kuyruğun build + push'u.
---
## 1. İddiaların kod/DB doğrulaması
Her satırı bu gece ben açtım. "Doğru ama eksik" = iddia doğru, sonucu değiştiren bir şey atlanmış.
| # | İddia | Sahibi | Hüküm | Kanıt |
|---|---|---|---|---|
| 1 | Kasa 6 hafta kırıktı; uçtan uca tamamlanmış ödeme hâlâ 0 | Marka §2.1, Ürün §2 | **Doğru** (kaynak: 21 Eyl gece prod `orders` sorgusu, `KARARLAR.md`) — bu gece prod'a erişmedim, teyit Bilal'in testine bağlı | `docs/ekip/KARARLAR.md` 21 Eyl gece kaydı |
| 2 | `/paket` girişsiz ziyaretçiye 299 TL'lik buton göstermiyor, "Paketi sonra alırsın." diyor | Ürün Ö2 | **Doğru ama eksik** — eksik olan: bu metin **21 Eylül'de Bilal'in onayladığı kararın uygulaması**; önceki hâli "Giriş yap — sonra 299 TL'ye…" idi | `paket-satinal.tsx:128-146` [D]; `git show 95bc87e` [D]; `KARARLAR.md` 21 Eyl gece #6 |
| 3 | `/giris` ödemeye gelen kişiye üçüncü kez ücretsiz deneme anlatıyor | Ürün Ö2(b) | **Doğru ama eksik** — `funnel` koşuluna `/paket` eklemek **yetmez**: funnel dalı da "Seçimlerin hazır — listen üretilsin" diyor, ödeme niyetiyle gelene o da yanlış. Üçüncü dal gerekir | `giris-karti.tsx:28-31, 52-65` [D] |
| 4 | Paket "60 danışman sorusu" diyor, kodda en çok 51 kalıyor | Ürün Ö3 | **Doğru** | `paket-satinal.tsx:36-41` (`${URUNLER.paket.credits} Yapay Zeka danışman sorusu`), `credits.ts:7,14,17`, `rapor-actions.ts:118-124` ve `:244-249` — `spendCredits` **`hasPaket` dalı olmadan** çağrılıyor [D] |
| 5 | Çözüm (a): paketliden liste/revizyon kredisi alınmasın | Ürün Ö3 tavsiyesi | **Doğru ama tehlikeli — raporun kaçırdığı şey bu** | `spendCredits`'in ledger'daki UNIQUE `refId`'si, üretimin **tek idempotency çapası**; DUPLICATE dalı (`rapor-actions.ts:133-162`) ve iade mantığı ona bağlı. Çağrı atlanırsa paketli kullanıcı aynı `requestId` ile LLM üretimini tekrar tekrar tetikleyebilir ve Bilal'in şu an üzerinde çalıştığı "çifte kredi" düzeltmesi (backlog #1) paketlide hükümsüz kalır. Çözüm: çağrıyı kaldırma, `amount: hasPaket ? 0 : RAPOR_KREDI` yap — `gte(creditBalance, 0)` geçer, ledger satırı (delta 0) yazılır, DUPLICATE korunur. İade dalı da (`grantCredits`, `:172-176`) aynı koşulu almalı, yoksa paketliye bedava 3 kredi sızar [D + Ç] |
| 6 | Ödeyecek kişiye (veli) sitede tek düğme yok | Marka §2.4 | **Doğru — ve rapordan daha kötü** | `src/` içinde "veli" 2 yerde, ikisi de aynı özellik satırı (`app/page.tsx:197`, `paket-satinal.tsx:36`) [D]. Eksik olan: o tek vaat (**PDF**) tamamen ödemenin arkasında — `rapor-yazdir.tsx:28` `if (!user.hasPaket) redirect("/paket")` [D]. Yani veliye verdiğimiz tek sözü veli ödemeden göremiyor |
| 7 | Veli rehber yazısının CTA'sı öğrencinin CTA'sı | Marka §2.4 | **Doğru ve genel** | `rehber-makale.tsx:112-116` — `CtaSiraForm` **tüm** yazıların altına basılıyor, yazı başına seçim yok [D] |
| 8 | Satıcı kimliği / fatura / makbuz e-postası yok | Marka §2.3 | **Doğru** | unvan/vergi/MERSİS grep = 0 [D]; `eposta.ts`'te yalnız 2 şablon (`:127` magic link, `:173` kredi hatırlatma) [D] |
| 9 | Sosyal kanıt şeridi `/paket`'e taşınsın | Marka Ö2(b) | **Yanlış (bu tur)** | Eşik 25 liste (`sosyal-kanit-sabitler.ts:11`) [D], 30 günde üretilen liste 3 (`01-ai-listesi-hunisi` §5.1). Taşınsa da **hiç çizilmez**. Taşıma işi değil, ölçü işi |
| 10 | Taksit kapalı | Marka §2.3 | **Doğru** | `iyzico.ts:201` `enabledInstallments: [1]` [D] |
| 11 | Paket adı sezona kilitli ("Tercih Dönemi Paketi") | Marka §1.1 | **Doğru** | `credits.ts:7` [D] |
| 12 | Footer ürünü "YKS Tercih Robotu 2026" diyor | Marka §1.5 | **Doğru** (satır 49 değil **48**) | `site-footer.tsx:48` [D] |
| 13 | `/sonuc` ilk ekranı boş gri harita placeholder'ı | Ürün Ö4 | **Doğru** | `manuel-harita.tsx:69-79` [D] |
| 14 | Tadımlık tablonun ~1.500 px altında | Ürün Ö5 | **Doğru** | `sonuc/page.tsx:102-118` — sıra: `ManuelHarita` → `SonucProgramTablosu` → `TadimlikBolumu` [D] |
| 15 | 20 yazı `/rehber`'i kullanılamaz hâle getirir (T33, P0) | SEO T33 | **Doğru ama yanlış yeri işaret ediyor** | `/rehber` düz masonry, tarihe göre desc, kümeleme/sayfalama yok (`rehber-listesi.tsx:7-12`, `rehber.ts:250-253`) [D] — 52 kart çirkin ama kullanılabilir. Asıl kırılan yer **makale altı**: `getAllRehberler().filter(...).slice(0,4)` (`rehber-makale.tsx:45-47`) [D] → 52 yazının **hepsinde aynı 4 yeni yazı** görünür, iç link grafiği çöker. P0 olan yarısı bu, `/rehber` gruplaması P1 |
| 16 | SEO planının DB rakamları | SEO §2 | **Doğru — birebir** | Altı yıllık trend (İktisat 51/256.761→131.892, Tarih 64/276.363→120.510, Psikoloji 184/152.325→270.358, İlk. Mat. Öğrt. 76/83.225→218.963), kontenjan kısıntısı (İng. Dili −1.096, Görsel İletişim −1.084, Hukuk −1.072, Diş Hek. −792), önlisans 9.254/354.627, bantlar 64/3.361/8.201, `netler` 2025=20.821 — **hepsini koşturdum, hepsi tuttu** [D] |
| 17 | `netler` = "yerleşenlerin ortalama netleri" (SEO planı §2 ilk paragraf) | SEO #2 | **Yanlış** | YÖK Atlas verisi **son yerleşen kişinin** netleridir; bu gece yazılan `kac-net-ile-hangi-bolum.md:7` doğru çerçeveyi kullanmış. Planın cümlesi yayına **girmemeli** |
| 18 | ÖSYM 2027 takvimi açıklanmadı → takvim yazısı şimdi yazılmaz (SEO §3) ↔ orkestratör `yks-2027-takvimi`'ni yazdırdı | SEO §3 ↔ Orkestratör | **Çelişki çözüldü: yazı haklı** | Yazının tezi zaten "açıklanmadı"; her satır AÇIKLANDI/BEKLENTİ etiketli, 2027 sütununda tek bir uydurma tarih yok (`yks-2027-takvimi.md:7,47,51-60`) [D]. Ayrıca 2026 satırı (29 Tem–10 Ağu) koddaki sezon sabitleriyle çakışıyor (`site-top-banner.tsx:7-8`) — iç tutarlılık teyidi [D] |
### Raporların kaçırdığı, benim eklediklerim
1. **Ö3(a)'nın idempotency maliyeti** (üstte #5). Tek satırlık bir "kredi düşme" kaldırma işi değil; yanlış yapılırsa çifte LLM maliyeti + backlog #1'in delinmesi.
2. **`/giris`'in üçüncü dalı** (üstte #3). Ö2(b) önerildiği gibi uygulanırsa metin yine yanlış olur.
3. **Veliye verilen tek söz paywall'un arkasında** (üstte #6). "Veli sayfası yok"tan daha keskin bir cümle ve bedava düzeltilebilir bir konum hatası değil — gelir modeli kararı. Not ediyorum, bu hafta açmıyorum.
4. **Gündüz yazdığım P1 kabul kriteri hatalıydı.** "`grep -rn "Tercih dönemi bitmeden" src/` → 0" ölçüsü işe yaramaz: cümle JSX'te satır sonuna bölünmüş (`hero-focus-button.tsx:44-46, 63-66`). Doğru ölçü `grep -rn "bitmeden yerini al" src/`; onunla `main`=2 → `icerik/sezon-celiskisi`=0, yani **P1 kabul kriterini geçiyor** [D]. Kriter düzeltildi.
5. **P1 dalı kapsamını aştı ama kabul edilebilir yönde:** `src/lib/sezon.ts` (86 satır, tek kaynak sezon takvimi + `BANT_METNI`) eklenmiş, hero'ya kanonik sağ ok konmuş. Bant metni A/B iki seçenek olarak hazır (`4034f03` "[Bilal]" commit'i dalın tepesinde, cherry-pick edilmezse dal A ile tutarlı) [D]. Bu, markanın "4 sezon durumu için tek metin şeması" isteğinin altyapısı — onaylıyorum, ama kayda geçiyorum: **tek amaçlı paket kuralı esnetildi.**
6. **`/rehber` sayfa başlığı sezona kilitli:** "Tercih Rehberi 2026 — YKS Tercih Dönemi Yazıları" (`src/app/rehber/page.tsx:13-17`) [D]. Bu gece eklenen yazıların yarısı 1. sınıf/veli/2027 içeriği; başlık artık sayfanın içeriğini yanlış tarif ediyor.
7. **Ödeme yolu değişikliği bu hafta yasak bölge.** Bilal tek gerçek uçtan uca ödemeyi yapacak; o testten **önce** `iyzico.ts`, `odeme-actions.ts`, paket adı ve taksit parametresine el değmez — yoksa testin neyi ölçtüğü belirsizleşir. Bu, aşağıdaki üç ertelemenin ortak gerekçesi.
---
## 2. Kurucunun dört sorusuna cevap
### A · Marka adı ve genişleme
**Marka ajanının analizi doğrulandı, gerekçesi daraltıldı.** Doğrulananlar: paket adının sezona kilitli olması (`credits.ts:7`), footer'ın ürünü reddedilmiş kategoriyle adlandırması (`site-footer.tsx:48`), logo tipografisinin ağırlığı "Tercih"e kaydırmış olması (`site-header.tsx:22-27`), "Kolay yerleşme" çipinin ürün içinde *düşük hedef* anlamına gelmesi (`sihirbaz-sabitler.ts:17`) — hepsi [D]. Dış kaynaklar (TDK, MEB LGS robotu, Armut, Kunduz, 19.566 MEB birimi) **[A]** — ben açmadım, marka ajanı açtı; kararım bunların hiçbirine tek başına dayanmıyor.
**Çürüttüğüm tek yer:** marka raporu "ad kararı ile genişleme kararını ayırın" derken genişleme tetiğini yalnız ödeme adedine bağlıyor. Eksik: genişlemenin gerçek maliyeti kod değil **mevsim ve veri hattı**. DGS/KPSS'nin cazip görünmesinin sebebi "aynı veri" değil, **boş kalan Ağustos–Eylül**; ama o ay bugün zaten boş ve biz onu dolduramıyoruz. İkinci alan, birinci alanın cevaplayamadığı soruyu ikiye katlar.
> **[KARAR] — tek cümle:** Ad değişmiyor; KolayTercih üniversite tercihinin dışına ancak 2027 YKS sezonunda **100 tamamlanmış ödeme** görülürse ve ilk alan **DGS/KPSS** olarak açılır — LGS hiçbir koşulda açılmaz (MEB'in ücretsiz ve resmî yapay zekâ destekli LGS robotu var [A]).
Maliyeti sıfır bir karar (hiçbir şey değişmiyor), o yüzden Bilal'e gitmiyor. Bilal'e giden tek ad konusu marka **tescili**dir (para + hukuk) ve onu da bu hafta istemiyorum; önce bir engel kontrolü gerekiyor (aşağıda marka ajanına soru).
### B · Öğrenciler neden ödemedi — çelişki çözümü ve sıra
**İki rapor çelişmiyor, tek bir yerde çarpışıyor: `/paket` girişsiz CTA'sı.** Ürün yöneticisi "birincil buton fiyatı ve satın almayı taşısın, 'Paketi sonra alırsın.' kalksın" diyor (Ö2a). Ama bugünkü metin **21 Eylül'de Bilal'in onayladığı kararın ta kendisi** (`KARARLAR.md` 21 Eyl gece #6; `git show 95bc87e`). Gerekçesi olarak gösterilen 24 Ağustos'taki kullanıcı ise **o karardan önceki sürümü** gördü. Yani ortada yeni kanıt yok, bir günlük kararın verisi hiç okunmadı. **Hüküm: Ö2(a) reddedildi** (PROTOKOL: verilmiş karar yeni kanıt olmadan açılmaz). **Ö2'nin onaylanan yarısı:** "Paketi sonra alırsın." cümlesi kalkar — o cümle kararın metni değil, satın almayı aktif olarak erteleten bir alt satır; kaldırılması kararı bozmaz.
**Sıra (ve neden bu sıra):** ölçülemeyen bir hipotezi test etmeden önce, testin mümkün olduğunu kanıtlamak gerekir.
1. **Kasa çalışıyor mu?** Bilal'in tek uçtan uca ödemesi + `odeme_hata {kod}` olayı (G2). Bu olmadan aşağıdaki hiçbir sayı yorumlanamaz.
2. **Verdiğimiz sözü koda eşitle.** "60 soru" ↔ 51 soru (G3). Ölçütüm sırasında ilk madde: kullanıcıya verilen sözü bozan yanlış bilgi. Ödeyen 0 kişi olduğu için **geri dönüş maliyeti bugün sıfır, bir hafta sonra olmayabilir.**
3. **Ödeme öncesi tek gerçek önizlemeyi ilk ekrana getir** (G1). "Ödemek için sebep" testinin tek eksiği, teslim edilecek şeyin örneğini ödeme kararından önce göstermek; örnek zaten üretilmiş ve bedava (522 satırlık tadımlık havuzu).
4. **Ödeyecek kişiye tek yüzey.** Bu hafta yalnız içerik adımı (aşağıda).
**Fiyat ve maske kararı — erteleme gerekçesi:** 299 TL'nin yanlış olduğunu söyleyen **tek bir veri yok**, çünkü fiyatı gören hiç kimse ödeme ekranına varamadı (30 günde `odeme_baslatildi` → `/odeme` görüntülemesi = 0). Maskeyi 3'ten 8'e çıkarmak ya da fiyatı indirmek, geri alındığında müşteride kötü görünen hamlelerdir; veri yokken yapılırsa geri alma ihtimali yüksektir. İkisi de **Bilal'in alanında ve bu hafta açılmıyor.**
**Ödeyen öğrenci mi, veli mi?**
> **Kullanan öğrenci, ödeyen veli.** Vizyon bunu zaten söylüyor (`vizyon.md:36`), ürün hiç uygulamamış: "veli" kelimesi kodda iki yerde ve veliye verdiğimiz tek söz (PDF) ödemenin arkasında kilitli (`rapor-yazdir.tsx:28`).
**Bu karar bu hafta akışı nasıl değiştirir? Neredeyse hiç — bilerek.** Veliye giden e-posta üçüncü kişi verisidir (KVKK metni + onay cümlesi + yeni şablon = M boy) ve sezon dışı hacimde etkisi okunamaz. Bu hafta atılan tek adım **kodsuz**: `content/rehber/veliler-icin-tercih-rehberi.md` gövdesine veli diliyle bir kapanış paragrafı + doğru bağlantı eklenir (bileşen CTA'sı yazı başına seçilebilir hâle gelene kadar ara çözüm). Kalıcı çözüm (`kume: veli` olan yazılarda farklı CTA) G4'ün üstüne, sonraki tura.
**Türkiye ölçeğinde büyüyen girişimlerden ders — bizim hacmimizde ne işe yarar?**
| Kaldıraç | Bizde işe yarar mı (95 ziyaret/hafta)? | Gerekçe |
|---|---|---|
| İçerik / organik yer tutma | **Evet — sezon dışı çalışan tek kaldıraç** | AI gösteriminde ilk 10'un 7'si rehber yazısı; 24 rehber, 864 katalog sayfasından fazla gösterim çekiyor (`geo-raporu` §8.1.1 [A/D]). Bileşik getirili, trafikten bağımsız birikir. **Kurucunun "yazı çoğalt" talimatı hacim gerçeğiyle uyumlu olan tek büyüme hamlesidir.** |
| Rehber öğretmen kanalı | **Evet** | MEB'in 81 ildeki 19.566 birimi [A] rakip değil dağıtım kanalı; rehberlik servisleri ve il MEM sayfaları bu tür sayfalara link verir. Maliyeti bir yazı (#17). |
| Sezon öncesi satış penceresi (Kunduz modeli) | Evet ama **2027 işi** | Bugün satacak sezon yok; hazırlığı Nisan 2027. |
| Fiyat testi / indirim | **Hayır** | n=2. |
| Taksit | **Hayır (bu hafta)** | 299 TL'de ekonomik değil; ayrıca ödeme yolu bir kez uçtan uca çalışmadan ödeme isteğine parametre eklenmez. |
| A/B testi | **Hayır** | Her kol 47 ziyaret/hafta. |
| Sosyal kanıt şeridi | **Hayır** | Eşik 25, elimizde 3 liste var; taşısak da çizilmez [D]. |
| Ücretli reklam | **Hayır** | Alt huni sızdırırken üste trafik pompalamak. |
### C · İçerik hattı
**(a) Bu gecenin 10 yazısı.** Dördü 20'lik planın konuları (#1 `taban-siralamalari-alti-yilda-nasil-degisti`, #2 `kac-net-ile-hangi-bolum`, #6 `siralama-bandlari-hangi-kapilar-acilir`, #19 `yapay-zekaya-tercih-sordum-guvenilir-mi`), üçü 21 Eylül planından (`universitede-ilk-hafta…`, `yks-2027-takvimi`, `ek-madde-1-puanim-yetiyor-mu`), ikisi yedek havuzdan (`bilgisayar-mi-yazilim-muhendisligi-mi`, `kktc-universiteleri-okunur-mu`), biri plan dışı yeni konu (`yeni-acilan-bolumler-nasil-degerlendirilir`).
**Hiçbiri bu sabah yayına girmiyor.** Gerekçe — üç yazıda rakamları, yazının kendi belirttiği yöntemle **bağımsız koşturduğumda tutturamadım**:
| Yazı | Yazıdaki rakam | Benim koşum (aynı filtre) | Hüküm |
|---|---|---|---|
| `bilgisayar-mi-yazilim-muhendisligi-mi.md:7,66` | "56 üniversitenin 54'ünde" | **57 / 55** (istisna sayısı 2 ✓) | Düzeltilecek. Program/kontenjan tablosu (303/133, 12.993, 11.285, 134/169) **birebir tuttu** [D] |
| `kktc-universiteleri-okunur-mu.md:81,212` | Lisans 13.162/7.923, önlisans 4.851/3.632 ve "toplamlarımız ÖSYM ile **birebir aynı**" | Bizim DB: **12.912/7.849** ve **4.637/3.537**; ayrıca 16 değil **23** ayrı `universite` değeri | "Birebir aynı" iddiası **yanlış** — ya çıkarılır ya farkın kaynağı (arşivlenen satırlar / KKTC-uyruklu kontenjanlar) yazılır |
| `siralama-bandlari-hangi-kapilar-acilir.md:7,66` | 9.304 program / 271 üniversite / 81 il | Stated filtre ile **9.482 / 277 / 84** | Fark muhtemelen yurt dışı kampüs + kirli `il` değerleri (T34); yazı bunu satır satır yazmalı |
| `kac-net-ile-hangi-bolum.md:7` | Tıp 31,5/28,2/33,8 (106) ✓; Hukuk 30,1/19,4/21,9 (51); Psikoloji 28,8/12,8/12,0 (72) | Tıp **birebir**; Hukuk 29,9/19,2/21,8 (52); Psikoloji 28,0/12,2/11,5 (75) | Havuz farkı açıklanmalı |
Bu bir "kötü yazar" bulgusu değil — yazıların yöntem anlatımı dürüst, kaynakları açık, vaat dili yok, `yks-2027-takvimi` belirsizliği örnek biçimde yönetiyor. Bulgu şu: **filtre cümlesi, rakamı yeniden üretmeye yetmiyor.** Çözüm ucuz, çünkü yazarlar sorguyu zaten koştu.
> **[KARAR]:** Bir yazı, içindeki her DB rakamı **yazının kendi verdiği sorgu/filtre ile bağımsız koşturulduğunda aynı çıkmadıkça yayımlanmaz.** Yazar raporuna kullandığı **tam SQL**'i yazar; `rehber-editoru` dalga sonunda tek geçişte yeniden koşar ve tutmayan her rakamı ya düzeltir ya çıkarır.
**(b) Onaylanan yeni konular (bir sonraki dalga, 4 yazı):** `ayni-bolum-farkli-universite-siralama-farki` (#3 — şablon değeri yüksek, #10'un girdisi), `hangi-bolumlerin-kontenjani-azaldi` (#5 — kanonik #1 artık yazıldı, bağımlılığı kalktı), `rehber-ogretmenler-icin-veri-kaynaklari` (#17 — dağıtım kanalı, bağlantı kazanma), `bolumumu-sevmedim-hangi-kapilar-var` (#11 — hub; 600 kelime sınırı, beş mevcut yazıyı birbirine bağlar, G4 ile birlikte iç link değerini ikiye katlar).
**#2'nin (`netler`) yayımlanması için Bilal'in onayını istemiyorum — kararı ben veriyorum:** veri YÖK Atlas kaynaklı ve kamuya açık, bizim özel verimiz değil; risk gizlilik değil doğruluktur. Koşullar: (i) her rakamın yanında **yıl etiketi** (2026 net verisi yok — `netler` max(yıl)=2025 [D]), (ii) çerçeve "**son yerleşen kişinin** netleri" olmalı — planın "yerleşenlerin ortalaması" ifadesi yanlıştır ve kullanılamaz, (iii) 5 satır YÖK Atlas'tan gözle teyit.
**(c) Hız: haftada 4 yazı.** Dalga başına en çok 5 paralel yazar; **bir dalga editör geçişinden ve rakam yeniden üretiminden geçmeden sonraki dalga başlamaz**. Dalganın en çok yarısı DB rakamına dayansın (doğrulama maliyeti dengelensin). Bu hızla 52 yazıya ~5 haftada varılır ve Bilal'in içerik borcu yazı başına ~2 dakikaya iner (yalnız iki listeyi okur: kaynak açılamadığı için çıkarılan iddialar + tutmayan rakamlar).
**(d) "Yayımlanmaz" kriterim (kalite eşiği):**
1. Rakam, yazının kendi filtresiyle yeniden üretilemiyorsa.
2. Yöntem kutusu yoksa (hangi tablo, hangi yıl kolonu, hangi filtre, kaç satır + veri tarihi).
3. Açılamayan kaynağa dayanan cümle varsa — "muhtemelen/genelde" ile yumuşatılamaz, çıkarılır.
4. Vaat dili tek geçişte bile varsa ("yerleşirsin", "garanti", "kesin", "atanırsın"); istihdam/atama iddiası yasak.
5. Mevcut bir yazıyla aynı arama niyetini hedefliyor ve ayrım cümlesi ilk 200 kelimede yoksa.
6. Teknik: 3 zorunlu frontmatter alanı, 1 mermaid + `%% aria:`, ≥1 tablo, ölü iç link yok (`/il/*` sayfası yok; `/tercih-robotu` 301'e gidiyor).
**(e) T33 — `/rehber` 52 yazıda kullanılamaz hâle gelir mi?** Kısmen; SEO raporu doğru teşhis koymuş ama yanlış yeri P0 ilan etmiş (§1 #15). **P0 olan yarısı makale altındaki "Diğer rehber yazıları"**, ve bu **bir sonraki turun işi değil, bu turun işi** (G4) — çünkü alan yazılar teslim edilirken eklenirse ikinci bir elden geçirme olmaz. `/rehber` index'inin küme başlıklarıyla gruplanması P1, sonraki tur.
### D · Gündüz verdiğim P1–P5 ile bu gecenin işleri çelişiyor mu?
**Hayır, iki yerde kesişiyor ve ikisini de birleştirdim.**
- **P1–P4 zaten dallarda uygulandı ve vardiya sırasında `main`'e merge edildi** (`faba6f4`, `001440a`, `d720e18`, `84fc88e`; 01:37–01:38) [D]. P1'in kabul kriterini düzeltilmiş grep'le doğruladım: geçiyor. **Push yok**; `main`, `origin/main`'in 18 commit önünde. Bant metni A/B seçeneği hazır (`4034f03`).
- **P5 (tadımlık vaadi/hedefi) ile ürün yöneticisinin Ö5'i (tadımlığı yukarı taşı) ve Ö4'ü (boş harita placeholder'ı) aynı ekranı değiştiriyor.** Üçü tek amacın parçası: *ödeme öncesi tek gerçek önizleme ilk ekranda görünsün ve doğru yere göndersin.* **Birleştirildi → G1.** Aynı dosyaya iki el değmez.
- Ürün yöneticisinin Ö4'ü, gündüz ertelediğim tasarımcı Ö4'üyle **aynı şey değil**: ertelenen, `/sonuc` sıralamasının tersine çevrilmesiydi (M boy, CLS/SSR etkili); bu, tek `return null` (kaldırma işi). Çelişki yok.
**Sabah Bilal'in önüne kaç madde, hangi sırayla:** üç. (1) merge kuyruğunun build+push'u, (2) tek gerçek ödeme, (3) tek cümlelik veto hakkı. Yeni kod paketleri (G1–G5) gece/yarın yazılır ve **bir sonraki inceleme turuna** kalır; bu sabah onların incelemesini istemiyorum.
---
## 3. Onaylanan teknik paketler
Her biri ayrı dal, tek amaç, push/merge yok. Satır numaraları `main @ 84fc88e`.
Öncelik sırası: **G1 → G3 → G2 → G5 → G4**. Bilal'in tek inceleme aralığı varsa **G1 ve G3** alınır.
### G1 · `funnel/sonuc-ilk-ekran` — S (P5 + Ö4 + Ö5 birleşik)
- **Amaç:** Ödeme öncesi tek gerçek önizleme ilk ekranda görünsün ve doğru yere göndersin.
- **Kapsam:** (a) `sonuc/page.tsx:102-118` — `<TadimlikBolumu>` `<SonucProgramTablosu>`'nun **öncesine** alınır. (b) `manuel-harita.tsx:69-79` — `liste.length === 0` iken bileşen `null` döner. (c) `tadimlik-satiri.tsx:111` — giriş callback'i `sonucHref()` yerine `/listem?uret=1` (üretim dönüşte kendiliğinden başlar). (d) `tadimlik-satiri.tsx:186` — "24 satırın tamamı" iddiası **çıkar** (maske 3 satır açıyor, `rapor-maske.ts:12`); yerine gelecek yeni cümle **ayrı `[Bilal]` commit'i**, ana commit yalnız yanlış iddiayı kaldırır. **Kapsam dışı:** maskenin kaç satır açtığı, `/sonuc` sıralamasının tersine çevrilmesi, `<h1>` işi, tadımlığın başka yüzeylere taşınması.
- **Kabul:** `/sonuc` sunucu HTML'inde tadımlık başlığının ilk geçiş konumu tablo başlığınınkinden **önce**; boş durumda "haritada belirir" metni HTML'de **yok**, listeye program eklenince harita yine görünür; girişten dönüşte üretim **ek tık olmadan** başlar; ekranda teslim edilmeyen bir sayı vaat edilmez; havuz boşsa tadımlık yine hiç render edilmez; `/meraklisina` şeması etkilenmez (sihirbaz adımları, havuz kuralları, 24'lük iskelet değişmiyor) ve bu rapora yazılır.
### G3 · `odeme/paket-vaadi` — S
- **Amaç:** Paket sayfasındaki sözü kodla eşitlemek: "60 danışman sorusu" gerçekten 60 olsun.
- **Kapsam:** `rapor-actions.ts` — `spendCredits` çağrısı **kaldırılmaz**, tutarı koşullanır: `amount: user.hasPaket ? 0 : RAPOR_KREDI` (liste `:118-124`, revizyon `:244-249`). İade dalları (`grantCredits`, `:172-176` ve revizyon karşılığı) **aynı koşulu alır**. Metinler tek kaynaktan doğru okunur (`paket-satinal.tsx:36-41`, `app/page.tsx:201`, `listem-govde.tsx` kilit satırı). **Kapsam dışı:** fiyat, kredi adedi, top-up, maske.
- **Kabul:** Paketli kullanıcıda liste ve revizyon **kredi düşmez**; `credit_ledger`'da satır yine yazılır (delta 0) ve **aynı `requestId` ile ikinci üretim DUPLICATE döner** (idempotency korunuyor, backlog #1 delinmedi); üretim hata verirse paketliye **kredi iade edilmez**; paketsiz kullanıcıda davranış bit-bit aynı; `grep -rn "danışman sorusu" src/` sonuçlarının tamamı aynı sayıyı ve aynı koşulu söyler; `guvenlik-uyum` denetimi temiz.
### G2 · `odeme/kasa-olculur` — XS
- **Amaç:** Ödeme hunisine payda. (Backlog #7 = ürün Ö1'in kod yarısı.)
- **Kapsam:** `satin-al-form.tsx`'in üç hata dalına (`:49, :53` civarı) `odeme_hata {kod}` olayı; `OlayAdi` birliğine tek ad. **Kapsam dışı:** `odeme_tamamlandi` sunucu tarafı olayı, yeni sayfa görüntüleme enstrümanı.
- **Kabul:** `grep -n "odeme_hata" src/features/odeme/components/satin-al-form.tsx` ≥1 ve ad `src/lib/analitik.ts`'te tanımlı; mevcut `odeme_baslatildi` davranışı değişmez; build + tip kontrolü temiz. **Yayın koşulu: Bilal'in test ödemesiyle aynı yayında çıkar.**
### G5 · `icerik/paket-erteleme-cumlesi` — XS
- **Amaç:** Satın alma niyetiyle gelen kişiye "sonra al" dememek.
- **Kapsam:** (a) `paket-satinal.tsx:141-143` — "Paketi sonra alırsın." cümlesi **çıkar**; birincil buton ve ilk iki cümle (21 Eyl kararı) **aynen kalır**. (b) `giris-karti.tsx:28-31, 52-65` — `/paket` callback'i için **üçüncü** metin dalı ("ödemeye devam"), mevcut funnel metni `/sonuc` ve `/listem?uret=1` için korunur. **Kapsam dışı:** birincil CTA metni ve hedefi (21 Eyl kararı — açılmıyor).
- **Kabul:** `grep -n "Paketi sonra alırsın" src/` → 0; `/giris?callback=/paket`'te ekranda deneme kredisi vaadi birincil cümle değil; `/sonuc` ve `/listem?uret=1` callback'lerinde metin değişmemiş; build temiz.
### G4 · `icerik/rehber-ilgili-yazilar` — S
- **Amaç:** 42 (yakında 52) yazıda "Diğer rehber yazıları" bloğunun hepsinde aynı 4 yeni yazıyı göstermesini bitirmek.
- **Kapsam:** (a) `src/lib/rehber.ts` — **opsiyonel** `kume:` frontmatter alanı (yoksa `"genel"`; mevcut 42 dosyanın hiçbiri değiştirilmeden derlenmeli). (b) `rehber-makale.tsx:45-47` — ilgili yazılar önce aynı kümeden, yetmezse tarihten tamamlanır. (c) `src/app/rehber/page.tsx:13-17` — sayfa başlığı/açıklaması sezon-bağımsız olur ("Tercih Dönemi Yazıları" ifadesi kalkar). **Kapsam dışı:** `/rehber` index'inin küme başlıklarıyla gruplanması (sonraki tur), mevcut 42 yazıya küme etiketi dağıtılması (ayrı, mekanik editör işi), yazı başına CTA seçimi.
- **Kabul:** Küme alanı olmayan yazılarla site derlenir ve `/rehber` bugünkü gibi çalışır; kümesi olan iki yazıdan her birinin "Diğer rehber yazıları" listesi diğerini içerir; hiçbir makalede liste boş kalmaz; `/rehber` başlığında yıl/sezon iddiası yok.
### Onaylanan rehber yazıları
**Bu gece yazılan 10 — "editörden geçmek koşuluyla onaylı", yayın sırası:**
`taban-siralamalari-alti-yilda-nasil-degisti` · `kac-net-ile-hangi-bolum` · `siralama-bandlari-hangi-kapilar-acilir` · `yeni-acilan-bolumler-nasil-degerlendirilir` · `bilgisayar-mi-yazilim-muhendisligi-mi` · `kktc-universiteleri-okunur-mu` · `yapay-zekaya-tercih-sordum-guvenilir-mi` · `ek-madde-1-puanim-yetiyor-mu` · `universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma` · `yks-2027-takvimi`
**Sonraki dalga — onaylı 4 konu:** `ayni-bolum-farkli-universite-siralama-farki` · `hangi-bolumlerin-kontenjani-azaldi` · `rehber-ogretmenler-icin-veri-kaynaklari` · `bolumumu-sevmedim-hangi-kapilar-var`
**Kodsuz içerik işi (1):** `veliler-icin-tercih-rehberi.md` gövdesine veli diliyle kapanış paragrafı + doğru bağlantı (bugün yazının altındaki CTA veliden **kendi sıralamasını** istiyor).
---
## 4. Bilal'e bırakılan kararlar (kısa tutuldu)
Kurucu "CEO benim yerime karar verebilir" dedi; aşağıdakiler gerçekten geri dönüşü zor ya da kurucu bilgisi gerektiren üç madde. Kalanını kendim karara bağladım.
| Karar | Tavsiyem | Geri dönüş maliyeti |
|---|---|---|
| **Paket içeriği (G3):** paketliye liste + revizyon kredisiz mi? | **Evet, kredisiz** — vizyonun kararı bu (`vizyon.md:32-34`), anlatması kolay ("krediler yalnız sohbet için") ve ödeyen 0 kişi olduğu için bugün kimseyi mağdur etmiyor. **Vetolamazsan uygulanır.** | Bugün sıfır; ödeyen çıktıktan sonra orta (paketi daraltmak kötü görünür) |
| **Satıcı kimliği** (unvan/adres/vergi no) sitede açılsın mı? | **Sezon açılmadan zorunlu, bu hafta değil.** Para alan sitede satıcının kim olduğunu söyleyen tek satır yok (grep = 0) ve fatura/makbuz kelimesi hiç geçmiyor. 21 Eylül'de ertelendi, bu turda yeni kanıt yok — açmıyorum, ama "2027 öncesi zorunlu" diye kayda geçiriyorum | Geri dönüşü zor (ticari kimlik açma) |
| **Deneme maskesi 3 → kaç satır / 299 TL** | **Bu hafta dokunma.** Fiyatı gören kimse ödeme ekranına varamadı; hangi sayının doğru olduğunu söyleyecek veri yok | Orta — fiyat/değer algısı; geri alması müşteride kötü görünür |
*(Bilal'e götürmediklerim ve nedenleri: ad kararı — maliyeti sıfır, bende; `netler` yayını — kamuya açık veri, risk doğruluk, koşullarıyla bende; `/paket` birincil CTA — 21 Eyl kararı, açılmıyor; taksit, paket adı, makbuz e-postası, ana sayfa kıyas ekseni — ödeme testi öncesi ödeme yoluna el değmez; marka tescili — önce engel kontrolü, sonra karar.)*
---
## 5. Reddedilenler / ertelenenler
| Öneri | Sahibi | Hüküm ve gerekçe |
|---|---|---|
| `/paket` girişsiz birincil CTA'sı fiyat + satın alma fiili taşısın | Ürün Ö2(a) | **Reddedildi.** 21 Eyl'de Bilal'in onayladığı kararın geri alınması; gösterilen kanıt (24 Ağu kullanıcısı) **karardan önceki sürüme** ait. Yeni kanıt yok |
| Sosyal kanıt şeridini `/paket`'e taşı | Marka Ö2(b) | **Reddedildi (bu tur).** Eşik 25, elimizde 3 liste — taşınsa da hiç çizilmez [D] |
| Taksit açılması | Marka Ö3 | **Ertelendi.** Ödeme yolu bir kez uçtan uca çalıştığı doğrulanmadan iyzico isteğine parametre eklenmez; komisyon etkisi de **doğrulanmalı** |
| Paket adının sezon-bağımsız olması ("Tercih Dönemi Paketi") | Marka H1 | **Ertelendi — ödeme testinden sonraki ilk iş.** Ad, iyzico sepetine giden etikettir; testten önce değiştirmek testin neyi ölçtüğünü bulandırır |
| Ödeme sonrası makbuz e-postası | Marka Ö2(c)/H3 | **Ertelendi.** Satıcı kimliği gelmeden makbuz metni yazılamaz; ayrıca ödeme akışına test öncesi el değmez |
| "Listeyi veline gönder" düğmesi + veli e-postası | Marka Ö1/Y1 | **Ertelendi (PRD, en geç Nisan 2027).** 3. kişi verisi + KVKK onay metni + yeni şablon = M boy; sezon dışı hacimde ölçülemez. Bu hafta yerine kodsuz içerik adımı atılıyor |
| Veli sayfası ("Çocuğunuz ne aldı?") | Marka Y3 | **Ertelendi** — aynı gerekçe, aynı pencere |
| Ana sayfa kıyas ekseninin MEB'in ücretsiz danışmanlığına çevrilmesi | Marka Y4 | **Ertelendi (sezon öncesi).** Tespit değerli [A] ama tablo 21 Eyl'de yeni kuruldu; iki günde iki kez değiştirmiyoruz |
| İkinci alan (DGS/KPSS/LGS) açılması | Marka §1.3 | **Reddedildi**, adet tetiğine bağlandı (§A). LGS kalıcı olarak kapalı |
| `/rehber` index'inin küme başlıklarıyla gruplanması | SEO T33 | **Ertelendi (sonraki tur).** P0 olan yarısı G4'te; index duvarı çirkin ama kullanılabilir |
| `siralama-bandina-gore…` yazısının `/il/[slug]` bağımlısı kardeşi (#18) | SEO #18 | **Reddedildi (bu tur).** `programs.il` kirli: 91 farklı değer, KKTC/yurt dışı şehirler, 110 boş `il` satırı (T34). Temizlik olmadan yazı ölü link üretir |
| Öğretmenlik branş yazısı (#4) | SEO #4 | **Ertelendi.** İstihdam/YMYL sınırına en yakın konu; ikinci editör okuması gerektiriyor, bu dalganın kapasitesi dolu |
| #7, #8, #9, #10, #12, #13, #14, #15, #16, #20 | SEO | **Sıraya alındı.** Haftada 4 yazı hızı; sonraki dalgalarda |
| `vakif-universitesi-burslu-indirimli-ucretli-farki` | Orkestratör dalga 2 | **Ertelendi.** 3.821 vakıf lisans programında isimde burs etiketi yok [D: SEO §1]; veri sorusu çözülmeden tablo yayımlanmaz |
| Vakıf üniversitelerinin **adıyla** doluluk yayını | 21 Eyl SEO §3 #10 | **Ertelendi — ben de sormuyorum.** Bilal'in kuyruğunda bundan değerli üç madde var; konu sırası gelince açılır |
| `/sonuc`'a `<h1>`, `/sonuc` sıralamasının tersi, mobil alt çubuk, tutarlılık temizliği, eval seti | 22 Eyl gündüz §5 | **Ertelemede kalıyor.** Yeni kanıt gelmedi |
---
## 6. Diğer ajanlara açık sorular (sonraki tur)
- **`rehber-editoru` (en yüksek öncelik):** 10 yazıyı tek geçişte al. Zorunlu çıktı: (a) her DB rakamının yazının kendi filtresiyle yeniden koşulmuş hâli ve tutmayanların listesi — başlangıç noktası §C'deki dört satır (`bilgisayar…` 56/54 → 57/55; `kktc…` "ÖSYM ile birebir aynı" iddiası ve 16 vs 23 üniversite; `siralama-bandlari…` 9.304 vs 9.482/271 vs 277/81 vs 84; `kac-net…` Hukuk ve Psikoloji satırları), (b) açılamayan kaynak yüzünden çıkarılan cümleler, (c) kanibalizasyon denetimi: `siralama-bandlari-hangi-kapilar-acilir` ↔ mevcut `kac-siralama-ile-hangi-bolume-girebilirim` ayrım cümlesi ilk 200 kelimede var mı.
- **`seo-geo`:** (1) Planın #2 için yazdığı "yerleşenlerin ortalama netleri" çerçevesi **yanlış** (doğrusu: son yerleşen kişinin netleri) — plandaki cümleyi düzelt, aynı hata başka konulara kopyalanmasın. (2) `yeni-acilan-bolumler…` plan dışı çıktı ve iyi bir yazı; 20'lik planın önceliklendirmesini bu konuyu da içerecek şekilde güncelle. (3) T34 (il temizliği) olmadan #18 ve T7 yapılmıyor — `veri-muhendisi` ile birlikte tek soru: boş `il` değerli 110 satırın kaynağı ne?
- **`cto`:** G1–G5 şartnameleri; özellikle G3'ün idempotency koşulu (§1 #5) ve G4'ün "kümesiz yazı da derlenir" geriye dönük uyumluluğu. Ayrıca: `/rehber` gruplaması için küme taksonomisi 5–6 kümeyi geçmemeli (öğrenci-karar / veri-analiz / 1. sınıf / veli-öğretmen / takvim-mevzuat).
- **`analitik`:** Rybbit bağlanınca ilk üç sorgu sabit: (a) 21 Eyl sonrası `tadimlik_goruntulendi` ve `liste_uretim_hata` **adedi**, (b) P1–P4 yayınından sonra girişli oturumlarda `/listem` görüntüleme adedi (taban: 30g'de 7), (c) `liste_uretim_basladi` haftalık adedi ve `basladi − (olusturuldu + hata + kredi_bitti)` farkı. Ek iş: tek sayfalık "haftalık adet kartı" tanımı.
- **`marka`:** (1) TÜRKPATENT'te "kolaytercih" ve yakın yazımlar tescilli mi — **ad kararından önce bilinmesi gereken tek gerçek engel**, ve bunu Bilal'e sormaya gerek yok, açık kayıt. (2) 4 sezon durumu (hazırlık / sonuç bekleme / tercih / ek yerleştirme) için tek metin şeması — altyapı `src/lib/sezon.ts`'te artık var, `BANT_METNI` kayıtlarını doldur.
- **`urun-yoneticisi`:** G1–G5 backlog'a "onaylı"; §5 tablosu "aday"; backlog #7 G2 ile kapanıyor; yeni satır: "rakam yeniden üretim kapısı" (içerik süreç işi). Veli ödeme yolu PRD'si `aday`, hedef pencere Nisan 2027.
- **`qa-muhendisi`:** (1) `main @ 84fc88e` üzerinde P1–P4'ün kabul kriterleri — özellikle + kapısını bitiren kullanıcı nereye çıkıyor ve navbar 375 px'te satır sarıyor mu. (2) Gündüzki hatalı grep kriterine dikkat: doğru ölçü `grep -rn "bitmeden yerini al" src/`. (3) G3 için tek senaryo: paketli kullanıcı aynı `requestId` ile iki kez üretim tetikleyemiyor.
- **`guvenlik-uyum`:** G3'ün ledger'a delta 0 satırı yazmasının mutabakat sorgularını (haftalık iyzico mutabakatı, `docs/odeme/iyzico.md`) bozup bozmadığı; ve paketliye iade yapılmamasının bir açık bırakıp bırakmadığı.
- **`yapay-zeka-muhendisi`:** G1 tadımlığı ilk ekrana çıkarınca havuz kapsamı kritikleşiyor — `tadimlik_havuzu`'nda kategori kaçağı (backlog #10: "Makine Resim ve Konstrüksiyonu" sanat-medya kategorisinde) G1 yayınından önce kapatılmalı mı, yoksa kaçak satır oranı ihmal edilebilir mi? Sayıyla cevap.
---
## 7. Bilal'den istenen (3 madde)
1. **Merge kuyruğunu bitir ve yayınla.** `main` şu an `origin/main`'in **18 commit** önünde (P1–P4 + sezon altyapısı); bant metni için `4034f03`'teki A/B seçeneğinden birini seç (tavsiyem: **A** — kısa, 375 px'te tek satıra sığıyor), çalışma ağacındaki `liste-uretici.tsx` + `uretim-basladi-olayi.tsx` işini aynı pakete al, push edilecek commit üzerinde temiz worktree'de `pnpm build` al — **~45 dk**.
2. **Canlıda tek bir gerçek uçtan uca ödeme yap** (`/paket → /odeme → /odeme/sonuc`, sonra iyzico panelinden iade) ve üç şeyi yaz: `hasPaket` açıldı mı, kilit çözüldü mü, Rybbit'te `/odeme/sonuc` görüntülemesi düştü mü. **Bu hafta alınacak diğer bütün ödeme kararları bunun sonucuna bağlı** — **~15 dk**.
3. **Tek cümlelik veto:** paketli kullanıcıdan liste ve revizyon kredisi alınmaması (G3) sana doğru geliyor mu? Sessizlik onay sayılır ve uygulanır — **~2 dk**.
*(Listeden düşürdüklerim: satıcı kimliği bilgileri — sezon öncesine kaydedildi, bu hafta iş üretmiyor; vakıf doluluk yayını kararı — sırası gelmedi; Search Console rakamları — merge/push ve ödeme testi bu hafta daha çok söyler; marka tescili — önce ajan engel kontrolü yapsın.)*
---
## KARARLAR.md'ye eklenecek kayıtlar
> Bu gece `KARARLAR.md`'ye **dokunulmadı** (Bilal'in commit'lenmemiş değişikliği var). Aşağıdaki bloklar dosyanın sonuna olduğu gibi eklenebilir.
```
## 2026-09-22 — Ad kalıyor; ikinci alan adet tetiğine bağlandı
- Karar: "KolayTercih" adı değişmiyor. Üniversite tercihinin dışına çıkmak, 2027 YKS sezonunda 100 tamamlanmış ödeme görülmesine bağlı; görülürse ilk alan DGS/KPSS (aynı veri şeması, boş kalan Ağustos–Eylül), LGS hiçbir koşulda açılmıyor. Marka tescili ve .com.tr kararı ayrı ve Bilal'de; önce TÜRKPATENT engel kontrolü yapılacak.
- Yetki: [KARAR] (ad değişmediği için maliyeti sıfır) · [BİLAL] (tescil/alan adı, para)
- Gerekçe: Ad hiçbir kapıyı kapatmıyor; kilit adda değil veride ve mevsimde. Tek ürünün cevaplamadığı soru "pazar var mı" değil "bu üründen para geçiyor mu" (30 günde tamamlanmış ödeme 0); ikinci alan bu soruyu cevaplamaz, ikiye katlar. Kod kanıtı: paket adı sezona kilitli (`src/lib/credits.ts:7`), footer ürünü reddedilmiş kategoriyle adlandırıyor (`src/components/site-footer.tsx:48`) — ikisi de addan bağımsız, ayrı işler. Dış pazar kaynakları marka ajanının açtığı sayfalardan (`03-marka-ve-odeme.md` §1.1–1.5), CEO tarafından bağımsız doğrulanmadı.
- Yerine geçtiği karar: —
## 2026-09-22 — Sıfır ödemede sıra: önce kasa, sonra söz, sonra önizleme; fiyat ve maske açılmıyor
- Karar: (1) Bilal canlıda tek bir uçtan uca ödeme yapar ve aynı yayında `odeme_hata {kod}` olayı eklenir (G2, backlog #7). (2) Paket vaadi kodla eşitlenir: paketli kullanıcıdan liste/revizyon kredisi alınmaz — `spendCredits` çağrısı kaldırılmaz, tutarı 0'lanır; iade dalı da koşullanır (G3). (3) `/sonuc` ilk ekranı: tadımlık tablonun üstüne çıkar, boş harita placeholder'ı kalkar, tadımlık CTA'sı `/listem?uret=1`'e gider ve "24 satırın tamamı" iddiası kalkar (G1; gündüzki P5 + ürün yöneticisinin Ö4/Ö5'i tek pakette). (4) "Paketi sonra alırsın." cümlesi kalkar ve `/giris`'e `/paket` callback'i için üçüncü metin dalı gelir (G5). Fiyat (299 TL), deneme maskesi (3 satır), taksit, ikinci paket ve paket adı bu hafta AÇILMIYOR.
- Yetki: [KARAR] (G1, G2, G5 ve G3'ün uygulaması) · [BİLAL] (G3'ün paket içeriği kararı — veto edilmezse uygulanır; fiyat/maske)
- Gerekçe: 30 günde paywall'a 2 kişi geldi, `odeme_baslatildi` 60+ iken `/odeme` görüntülemesi 0 (`04-sifir-odeme-teshisi.md` §1-2). Fiyat/maske kararı n=2 üzerine kurulur ve geri alınması müşteride kötü görünür. Paket "60 danışman sorusu" diyor, kodda en çok 51 kalıyor (`paket-satinal.tsx:36-41`, `credits.ts:7,14,17`, `rapor-actions.ts:118-124`) — ödeyen 0 kişi olduğu için düzeltmenin en ucuz anı bugün. G3'ün kritik kısıtı: `spendCredits`'in ledger'daki UNIQUE `refId`'si üretimin tek idempotency çapası; çağrı atlanırsa paketli kullanıcı aynı `requestId` ile üretimi tekrar tetikleyebilir.
- Yerine geçtiği karar: 2026-09-22 — Sevk sorunu… (P5 maddesi G1'de birleştirildi)
## 2026-09-22 — Ödeyen veli, kullanan öğrenci; ama bu hafta akış değişmiyor
- Karar: Ürünün ödeyicisi veli kabul edilir. Bu hafta yapılan tek adım kodsuzdur: `content/rehber/veliler-icin-tercih-rehberi.md` gövdesine veliye hitap eden kapanış paragrafı ve doğru bağlantı eklenir. "Listeyi veline gönder" düğmesi + veli e-postası, veli sayfası ve ödeme akışında veli yolu PRD'ye alınır; hedef pencere en geç Nisan 2027.
- Yetki: [KARAR] (erteleme + içerik adımı) · [BİLAL] (veli ödeme yolu, 2027 öncesi)
- Gerekçe: `docs/urun/vizyon.md:36` veliyi ödeyici sayıyor ama kodda "veli" iki yerde ve ikisi de aynı özellik satırı (`src/app/page.tsx:197`, `paket-satinal.tsx:36`); veliye verilen tek söz olan PDF tamamen ödemenin arkasında (`rapor-yazdir.tsx:28`). Veli e-postası üçüncü kişi verisidir (KVKK onay metni + yeni şablon = M boy) ve sezon dışı hacimde ölçülemez. Ayrıca bütün rehber yazılarının altına aynı öğrenci CTA'sı basılıyor (`rehber-makale.tsx:112-116`), yani veli yazısı bugün veliden kendi sıralamasını istiyor.
- Yerine geçtiği karar: —
## 2026-09-22 — İçerik hattı: haftada 4 yazı, rakam yeniden üretim kapısı, ilgili yazılar düzeltmesi
- Karar: (1) Hız haftada 4 yazı; dalga başına en çok 5 paralel yazar; bir dalga editör geçişinden geçmeden sonraki dalga başlamaz; dalganın en çok yarısı DB rakamına dayanır. (2) YAYIMLANMAZ kriteri: rakam yazının kendi filtresiyle yeniden üretilemiyorsa; yöntem kutusu yoksa; açılamayan kaynağa dayanan cümle varsa; vaat/istihdam dili varsa; kanibalizasyon ayrım cümlesi ilk 200 kelimede yoksa; teknik asgari (3 frontmatter alanı, mermaid + `%% aria:`, ≥1 tablo, ölü iç link yok) sağlanmıyorsa. Yazar raporuna tam SQL'ini yazar, editör dalga sonunda yeniden koşar. (3) Bu gecenin 10 yazısı "editörden geçmek koşuluyla" onaylı; hiçbiri editör turu öncesi yayına girmez. (4) Sonraki dalganın 4 konusu: `ayni-bolum-farkli-universite-siralama-farki`, `hangi-bolumlerin-kontenjani-azaldi`, `rehber-ogretmenler-icin-veri-kaynaklari`, `bolumumu-sevmedim-hangi-kapilar-var`. (5) `netler` (program bazlı net) verisi yayımlanır — koşul: yıl etiketi zorunlu (2026 net verisi yok), çerçeve "son yerleşen kişinin netleri" (planın "yerleşenlerin ortalaması" ifadesi yanlıştır), 5 satır YÖK Atlas'tan gözle teyit. (6) `/il/*` bağımlı yazı (#18) ve vakıf burs etiketi kırılımına dayanan yazılar veri temizliği çıkana kadar yazılmaz.
- Yetki: [KARAR]
- Gerekçe: Kurucunun bu vardiya için tek ana çıktısı yazı çoğaltmak ve bu, ~95 ziyaret/haftalık hacimde ölçülebilir getirisi olan tek büyüme kaldıracı (AI gösteriminde ilk 10'un 7'si rehber yazısı, `docs/geo/geo-raporu.md` §8.1.1). Kapı gerekli: bu gece yazılan üç yazıda rakamlar kendi belirttikleri yöntemle yeniden üretilemedi — `bilgisayar-mi-yazilim-muhendisligi-mi.md:7,66` "56 üniversitenin 54'ü" (yeniden koşum: 57/55), `kktc-universiteleri-okunur-mu.md:81,212` "ÖSYM ile birebir aynı" (bizim DB: 12.912/7.849 ve 4.637/3.537), `siralama-bandlari-hangi-kapilar-acilir.md:7` 9.304/271/81 (yeniden koşum: 9.482/277/84). Aynı yazıların program/kontenjan tabloları ve SEO planının bütün omurga rakamları birebir tuttu — sorun yöntem cümlesinin rakamı yeniden üretmeye yetmemesi.
- Yerine geçtiği karar: 2026-09-22 — Sevk sorunu… ("bu tur yeni rehber yazısı onaylanmadı" satırı; kurucu brief'i 22 Eyl gece bunun üstüne geçti)
## 2026-09-22 — `/rehber` ölçek borcunun P0 yarısı bu turda kapanır
- Karar: `kume:` opsiyonel frontmatter alanı eklenir, makale altındaki "Diğer rehber yazıları" önce aynı kümeden seçilir ve `/rehber` sayfa başlığı sezon-bağımsız olur (G4, dal `icerik/rehber-ilgili-yazilar`). `/rehber` index'inin küme başlıklarıyla gruplanması ve mevcut 42 yazıya küme etiketi dağıtılması sonraki tura bırakıldı.
- Yetki: [KARAR]
- Gerekçe: SEO T33 doğru teşhis koydu ama yanlış yeri P0 ilan etti: `/rehber` düz bir duvar olsa da kullanılabilir; asıl kırılan yer `rehber-makale.tsx:45-47` — `getAllRehberler().slice(0,4)` tarihe göre sıralı olduğu için 42 (yakında 52) yazının HEPSİ aynı 4 yeni yazıya link veriyor, iç link grafiği çöküyor. Alan, yazılar teslim edilirken eklenirse ikinci elden geçirme olmaz.
- Yerine geçtiği karar: —
## 2026-09-22 — `/paket` girişsiz CTA kararı açılmıyor; yalnız erteleyen cümle kalkıyor
- Karar: `/paket` girişsiz ziyaretçinin birincil butonu ("Giriş yap — ilk 3 tercihini ücretsiz gör") 21 Eylül kararı gereği AYNEN kalır; yalnız altındaki "Paketi sonra alırsın." cümlesi kaldırılır ve `/giris`, `/paket` callback'i için üçüncü bir metin dalı alır (G5).
- Yetki: [KARAR]
- Gerekçe: Ürün yöneticisinin Ö2(a) önerisi bir günlük kararın geri alınması anlamına geliyor; gerekçe olarak gösterilen 24 Ağustos kullanıcısı o karardan ÖNCEKİ sürümü gördü (`git show 95bc87e`), yani yeni kanıt yok (PROTOKOL: verilmiş karar yeni kanıt olmadan açılmaz). "Paketi sonra alırsın." ise kararın metni değil, satın almayı aktif olarak erteleten bir alt satır (`paket-satinal.tsx:141-143`).
- Yerine geçtiği karar: —
## 2026-09-22 — P1–P4 merge edildi; kabul kriteri düzeltmesi
- Karar: P1–P4 vardiya sırasında `main`'e alındı (faba6f4, 001440a, d720e18, 84fc88e — 22 Eyl 01:38); push edilmedi, `main` `origin/main`'in 18 commit önünde. P1'in gündüz yazılan kabul kriteri hatalıydı ve düzeltildi: doğru ölçü `grep -rn "bitmeden yerini al" src/` (cümle JSX'te satır sonuna bölündüğü için "Tercih dönemi bitmeden" araması hiçbir zaman eşleşmiyordu). Düzeltilmiş ölçüyle P1 geçiyor (main=2 → dal=0). P1 dalının kapsamı `src/lib/sezon.ts` (tek kaynak sezon takvimi + `BANT_METNI`) ile aşıldı; markanın "4 sezon için tek metin şeması" isteğinin altyapısı olduğu için onaylandı, tek amaçlı paket kuralının bu kez esnetildiği kayda geçiriliyor.
- Yetki: [KARAR] (kriter düzeltmesi, kapsam onayı) · [BİLAL] (build + push; bant metni A/B seçimi — commit 4034f03)
- Gerekçe: `git log`/`git grep` doğrulaması, 22 Eylül 2026 gece vardiyası.
- Yerine geçtiği karar: 2026-09-22 — Sevk sorunu… (P1 kabul kriteri)
```

View File

@@ -0,0 +1,72 @@
# 10 — Yazar raporu: `universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma`
**Tarih:** 22 Eylül 2026, gece · **Rol:** rehber-yazari · **Dosya:** `content/rehber/universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma.md` (37 KB, tek dosya; başka hiçbir dosyaya dokunulmadı, commit atılmadı)
## Özet (5 madde)
1. SEO planı §4'teki **4 numaralı yazı** şartnamesine göre yazıldı: "Kısa cevap:" ile açan tek paragraflık yanıt, tam **1** `flowchart TD` şeması (`%% aria:` + `%% altyazi:`), **4 tablo**, 8 soru biçimli H2, sonda erişim tarihli Kaynaklar.
2. **Harç rakamları Resmî Gazete'nin kendi PDF'inden okundu** — haber sitesinden değil. 15 Ağustos 2026 tarihli, 33341 sayılı RG, **11625 sayılı Cumhurbaşkanı Kararı**. PDF'in metin katmanı yok (taranmış görüntü), bu yüzden sayfalar PDFKit ile PNG'ye çevrilip görsel olarak okundu. (I) ve (II) sayılı cetvellerden 8 satırlık ücret tablosu + tıp/mühendislik katkı payı rakamları yazıya girdi.
3. **Genelleme yapılmadı.** Üç devlet üniversitesinin *yürürlükteki* yönetmeliği (mevzuat.gov.tr) yan yana konarak ders muafiyeti süresi, danışman onayı, kayıt dondurmanın adı/süresi ve azami süreye sayılıp sayılmaması karşılaştırıldı; her bölümde "kendi üniversitenin akademik takvimine/yönetmeliğine bak" uyarısı var.
4. **Bir kaynak hatası yakalandı ve düzeltildi:** ilk taslakta İstanbul Üniversitesi için `cdn.istanbul.edu.tr`'deki PDF kullanılmıştı; mevzuat.gov.tr sorgusu bu metnin **yürürlükten kaldırılmış 2010 yönetmeliği** olduğunu gösterdi. Yürürlükteki metin (28 Eylül 2025, RG 33031, mevzuatNo 42625) indirildi ve **tüm İÜ atıfları yeniden yazıldı** (madde numaraları, süreler, AKTS üst sınırı dahil).
5. Ürün CTA'sı yumuşak tutuldu ("sen yerleştin, bu araçlara ihtiyacı olan kardeşin/arkadaşın") → `/bolumler`, `/universiteler`. Vaat/garanti dili ve yerleşme olasılığı iddiası yok.
---
## Doğrulanan bilgiler ve kaynak URL'leri (hepsi 22 Eylül 2026'da açıldı)
| İddia | Kaynak | Not |
|---|---|---|
| 2026-2027 katkı payı/öğrenim ücreti kararı: 15 Ağu 2026, RG 33341, Karar 11625 | https://www.resmigazete.gov.tr/eskiler/2026/08/20260815-7.pdf | RG içindekiler sayfasından (`.../20260815.htm`) bulundu |
| Birinci öğretim + açık öğretimde program süresini aşmayandan katkı payı alınmaz; devlet karşılar, %40 artırımlı öder | Aynı karar, m. 1/3 | Madde 3 ve 10'daki istisnalar saklı |
| İki dönem öğretim yapan kurumda dönem başına tutar cetveldekinin yarısı | m. 1/2 | Yazıda tablo altına dipnot olarak kondu |
| Engelli öğrenci: öğrenim ücretinden engellilik oranı kadar indirim; 1. öğretim/açık öğretimde katkı payı yok (süre ve program sayısı sınırı olmaksızın) | m. 1/5 | |
| Ödeme dönem başında kayıt/kayıt yenileme sırasında; süresinde ödemeyen ve mazereti kabul edilmeyen o dönem kayıt yaptıramaz, öğrencilik hakkı yok | m. 2/1–2 | Ana tablonun "kaçırırsan ne olur" sütununun dayanağı |
| İkinci öğretimde dönem sonu sıralamasında ilk %10: birinci öğretim katkı payı kadar öder | m. 5/1 | |
| Yabancı dille öğretimde ücret ve katkı payı 1,5 katı | m. 9 | |
| Süresinde mezun olamayandan cetveldeki tutar alınır; hazırlıkta devletin karşıladığı süre 1 yıl | m. 10/1 | |
| Sadece bir programın katkı payı devletçe karşılanır; ikinci programı (ÇAP hariç) öğrenci öder | m. 10/3 | "İkinci üniversite/AÖF ücreti" sorusunun resmî dayanağı |
| (II) sayılı cetvel (A) ücretleri: 7.140 / 7.625 / 8.574 / 9.510 / 11.348 / 14.286 / 15.844 / 31.694 TL | Karar eki, (II) sayılı cetvel (A) — PDF s. 14–15 | Yıllık tutarlar |
| (I) sayılı cetvel (A): tıp öğrenci katkısı 4.386 TL (cari maliyet 115.435, devlet katkısı 111.048); mühendislik grubu öğrenci katkısı 2.876 TL | Karar eki, (I) sayılı cetvel (A) — PDF s. 9 | |
| Azami süreler (ön lisans 4, 4 yıllık lisans 7, 5 yıllık 8, 6 yıllık 9 yıl), "kayıt yaptırıp yaptırmadığına bakılmaksızın"; hazırlık azami 2 yıl; 4 yıl üst üste ödememe/kayıt yenilememede ilişik kesilebilir | https://www.mevzuat.gov.tr/mevzuatmetin/1.5.2547.pdf — 2547 m. 44/c | |
| Hazırlık yeterlik/seviye tespit sınavı öğretim yılı başında; sınavdan muafiyet (3 yıl yurt dışı ortaöğretim / YÖK'ün kabul ettiği merkezî-uluslararası sınav + senato puanı); Türkçe programlarda zorunlu yabancı dil muafiyet sınavı; hazırlığı 2 yılda bitiremeyenin ilişiği kesilir | https://www.resmigazete.gov.tr/eskiler/2016/03/20160323-6.htm — m. 6, 7, 8 | 23 Mart 2016, sayı 29662 |
| Hacettepe: ders kaydı danışman onayıyla kesinleşir (m.7), ders muafiyeti 5 iş günü (m.10), izinli sayılma en çok 4 yarıyıl + ekle-sil bitimine kadar başvuru + süre sayılmaz (m.38) | https://www.mevzuat.gov.tr/mevzuat?MevzuatNo=42555&MevzuatTur=8&MevzuatTertip=5 | 30 Tem 2025, RG 32971 |
| İstanbul Ü.: ödeme/iade (m.8), kayıt yenileme ve yenilenmeyen yarıyılın süreden sayılması (m.9), muafiyet 10 iş günü + AKTS'nin en çok yarısı (m.11), hazırlık yeterlik (m.18), kayıt dondurma 4 yarıyıl + azamî süreden sayılmaz (m.28/7, m.29) | https://www.mevzuat.gov.tr/mevzuat?MevzuatNo=42625&MevzuatTur=8&MevzuatTertip=5 | 28 Eyl 2025, RG 33031 — **yürürlükteki metin** |
| Ankara Ü.: danışmanın görevleri (m.6), ders kaydı danışman onayıyla kesinleşir + onay gelmezse bölüm başkanı kesinleştirir (m.9/8), muafiyet bir defaya mahsus + 10 iş günü karar (m.21), kayıt dondurma 4 yarıyıl + süreye dâhil değil + azami süre sonundakiler talep edemez (m.44) | https://www.mevzuat.gov.tr/mevzuat?MevzuatNo=23832&MevzuatTur=8&MevzuatTertip=5 | 8 Ağu 2017, RG 30148, değişiklikleriyle |
| Öğrenci belgesi e-Devlet'te YÖK hizmeti olarak var | https://www.turkiye.gov.tr/yok-ogrenci-belgesi-sorgulama | Sayfa açıldı, hizmet sahibi "Yükseköğretim Kurulu Başkanlığı" |
| KYK 2026-2027 burs/kredi başvuru tarihi 22 Eyl 2026 itibarıyla açıklanmadı; 2025'te 13–17 Ekim | `content/rehber/kyk-burs-mu-kredi-mi.md` (aynı vardiyada KYGM kaynaklarıyla doğrulanmış) | İki yazı birbiriyle tutarlı |
**Kullanılan SQL sorgusu: yok.** Bu yazıda taban/sıralama rakamı geçmiyor, `data/yokatlas.db` sorgulanmadı. `src/lib/risk.ts`'teki dilim kuralına da değinilmiyor — çelişki riski yok.
**Prompt injection:** açılan hiçbir resmî sayfada/PDF'te ajana yönelik talimat görülmedi.
---
## Çıkarılan / yazılmayan iddialar
1. **"Kayıt dondurma azami süreye sayılmaz" genel kural olarak yazılmadı.** Üç üniversitenin de yönetmeliği "sayılmaz" diyor ama 2547 m.44/c azami süreleri "kayıt yaptırıp yaptırmadığına bakılmaksızın" saydırıyor; dondurulan sürenin dışarıda kalması her üniversitenin kendi yönetmeliğindeki düzenleme. Yazı bunu açıkça "üniversitene göre değişir, yönetmeliğine bak, cevabı yazılı al" diye veriyor.
2. **Takvim günü verilmedi.** "Ders kaydı 15 Eylül'de başlar" gibi hiçbir tarih yok; tablodaki "ne zaman" sütunu yönetmeliklerdeki pencere adlarını (kayıt yenileme, ekle-sil, öğretim yılı başı) kullanıyor.
3. **İstanbul Üniversitesi için "danışman onayı gerekir" denmedi.** Yürürlükteki yönetmeliğin kayıt yenileme maddesinde danışman onayı geçmiyor; "uygulamada senato esaslarıyla düzenleniyor olabilir, okulundan teyit et" biçiminde yazıldı — varsayım yapılmadı.
4. **Vakıf üniversitesi ücretleri yazılmadı.** Cumhurbaşkanı Kararı devlet yükseköğretim kurumlarının cetvelidir; vakıf ücretleri için resmî tek kaynak yok, uydurulmadı.
5. **KYK burs/kredinin kayıt dondurmada kesilip kesilmediği kesin cümleyle yazılmadı.** Mevzuatta "ders kaydı yaptırmamak kesilme sebebi" var ama kayıt dondurma hâline özel bir hüküm bu vardiyada teyit edilemedi; yazı "başvurudan önce KYGM'ye ve üniversitenin SKS birimine sor" diyor.
6. **Oryantasyon/uyum programı "zorunlu" denmedi** — yalnızca Ankara'nın yönetmeliğinde tanımlı olduğu görüldü, genelleme yapılmadı.
---
## Engeller
- `resmigazete.gov.tr` ve `mevzuat.gov.tr` varsayılan istemciye yanıt vermiyor (bağlantı zaman aşımı / sertifika hatası); tarayıcı `User-Agent` başlığıyla `curl` gerekti. Diğer ajanlar aynı duvara çarparsa çözüm budur.
- Resmî Gazete'nin karar PDF'i **taranmış görüntü**; makinede `pdftotext`/OCR yok. Sayfalar Swift + PDFKit ile PNG'ye render edilip görsel olarak okundu (betikler scratchpad'de). Rakamlar bu yolla cetvelden birebir alındı.
- Şemayı `mermaid.parse()` ile doğrulamak mümkün olmadı: Node'da DOM olmadığı için DOMPurify başlatılamıyor. Kontrol amaçlı hâlen yayında olan `kyk-burs-mu-kredi-mi` şeması da **aynı hatayı** veriyor → hata ortam kaynaklı, sözdizimi değil. Yeni şema mevcut yazılarla birebir aynı yapıları kullanıyor (`("...")`, `{"..."}`, `-- "etiket" -->`, `classDef`/`class`); tek yeni unsur bir geri dönüş kenarı (`OE --> D`), mermaid bunu destekliyor.
- İstanbul Üniversitesi ÖİDB sitesi JavaScript uygulaması olduğu için kazınamadı; yürürlükteki metin mevzuat.gov.tr arama API'siyle bulundu.
## Rehber editörüne notlar (başka dosyaya dokunmadım)
1. `content/rehber/hazirlik-sinifi-ve-ogretim-dili.md` şemasında *"1 yıl hazırlık — normal süreye dahil DEĞİL"* yazıyor. Bu 2547 m.44/c'ye uygun ama **eksik**: hazırlık eğitim süresi azami 2 yıldır ve tamamen/kısmen yabancı dil programlarda 2 yılda bitiremeyenin ilişiği kesilir. Yazıda bu ikinci cümle var ama şemada yok — şema/metin tutarlılığı gözden geçirilebilir.
2. `content/rehber/universite-kayit-rehberi-2026.md` sonundaki "Kayıt sonrası küçük ama önemli işler" bölümü artık bu yazıya link verebilir (şu an vermiyor); karşılıklı link kurulursa huni tamamlanır.
3. Genel risk: **üniversite yönetmelikleri sık yenileniyor.** Kullandığım üç metnin ikisi son 14 ayda değişti. Yönetmeliğe atıf yapan her yazıya yıllık bir "yürürlük kontrolü" işi açılması iyi olur (mevzuat.gov.tr'nin `anasayfa/MevzuatDatatable` POST uç noktası bunu otomatikleştirmeye uygun).
## Bilal'den istenen (yayın öncesi kontrol)
1. **Harç tablosunu tek bakışta doğrula:** RG PDF'i taranmış olduğu için rakamlar görselden okundu; 8 satırın en az 2'sini `resmigazete.gov.tr/eskiler/2026/08/20260815-7.pdf` sayfa 14–15'ten göz kararı teyit et — 3 dk.
2. **Üç üniversite örneği sende de doğru mu:** üç okulun adının bir rehber yazısında karşılaştırmalı geçmesi marka açısından uygun mu, yoksa isim vermeden mi anlatalım? — 2 dk, [BİLAL] kararı.
3. Yayın öncesi sayfayı bir kez aç: şema mobilde uzun kutular nedeniyle taşıyor mu — 2 dk.

View File

@@ -0,0 +1,101 @@
# 11 — Yazar raporu: `yks-2027-takvimi`
**Tarih:** 22 Eylül 2026, gece · **Rol:** rehber-yazari · **Dosya:** `content/rehber/yks-2027-takvimi.md` (yeni, 20.433 karakter) · **Commit atılmadı, başka dosyaya dokunulmadı.**
**Kanıt işaretleri:** **[D]** birincil kaynak açıldı ve okundu · **[Ç]** verilmiş tarihlerden aritmetik çıkarım.
## Özet (5 madde)
1. **ÖSYM 2027 sınav takvimini yayımlamamış** [D]. İki bağımsız kontrol: (a) `osym.gov.tr/Sayfa/SinavTakvimi` sayfasındaki yıl seçme kutusunda tek seçenek `2026`; (b) `osym.gov.tr/Duyurular/Index` 2026 listesindeki 375 duyurunun metninde "2027" hiç geçmiyor. Yazıda tek bir tahmini 2027 tarihi yok.
2. **2027 kuşağı için açıklanmış tek takvim MEB'in MEBİ deneme takvimi** [D]: 2026-2027'de 12 YKS denemesi, ilki 21-27 Eylül 2026, Haziran 2027'ye kadar, TYT/AYT/YDT. Yazıdaki tek "AÇIKLANDI" satırı budur.
3. **Geçmiş kaydı üç yıl derinliğinde ve tamamı ÖSYM duyurularından** [D]: 2024, 2025, 2026 için başvuru, sınav, sonuç, kılavuz, tercih, yerleştirme, kayıt, ek yerleştirme + MSÜ'nün üç yılı. Hepsi yazının sonundaki kaynak listesinde tek tek linkli.
4. **Yan takvimler:** MSÜ (ÖSYM, üç yıl [D]), MEBİ (MEB [D]), Ek Madde-1 bahar penceresi (YÖK ilke sayfası [D] + Ankara Üniversitesi 2026 bahar duyurusu 21-23 Ocak 2026 [D]).
5. **Yazılmayan iddialar:** "2026 takvimi 14 Kasım 2025'te yayımlandı" (SEO planında [A] olarak geçiyordu) **doğrulanamadı, yazıya girmedi**; ÖSYM takvimi duyuru olarak yayımlamıyor, doğrudan sayfaya koyuyor. "Takvim Kasım ortasında beklenir" cümlesi de bu yüzden çıkarıldı.
---
## 1. Hangi tarihler "açıklandı" olarak işaretlendi
| Satır | Tarih | Kaynak |
|---|---|---|
| MEBİ 2026-2027 YKS denemeleri: 12 deneme, ilki 21-27 Eylül 2026, Haziran 2027'ye kadar | MEB duyurusu 17 Eylül 2026 | https://www.meb.gov.tr/mebi-2026-2027-yks-ve-lgs-deneme-takvimi-belli-oldu/haber/41943/tr |
Bu tek satır. Diğer her şey "beklenti" ya da "üniversite takvimi".
## 2. Hangi satırlar "beklenti" olarak işaretlendi
Yazıdaki tüm YKS ve MSÜ satırları (başvuru, TYT, AYT/YDT, sonuç, kılavuz, tercih, yerleştirme sonucu, kayıt, ek yerleştirme tercihi, ek yerleştirme sonucu, MSÜ başvuru/sınav/sonuç). Her biri şemada ve tabloda **metin etiketiyle** ayrılıyor (`BEKLENTİ` / `AÇIKLANDI` / `ÜNİVERSİTE TAKVİMİ`); renk yalnızca destek, tek başına anlam taşımıyor (şema `classDef garanti` = açıklandı, `uyari` = beklenti).
### Beklentinin dayanağı: doğrulanan geçmiş tarihler [D]
| Aşama | 2024 | 2025 | 2026 |
|---|---|---|---|
| YKS başvurusu | 1-26 Şubat | 6 Şubat-3 Mart | 6 Şubat-2 Mart (geç başvuru 10-12 Mart) |
| TYT / AYT-YDT | 8 / 9 Haziran | 21 / 22 Haziran | 20 / 21 Haziran |
| Sınav sonucu | 16 Temmuz | 19 Temmuz | 21 Temmuz |
| Kılavuz + tercih başlangıcı | 25 Temmuz | 1 Ağustos | 29 Temmuz |
| Tercih dönemi | 25 Tem-2 Ağu (4 Ağu'ya uzatıldı) | 1-13 Ağustos | 29 Temmuz-10 Ağustos |
| Yerleştirme sonucu | 13 Ağustos | 25 Ağustos | 18 Ağustos |
| Kayıt (e-kayıt) | 19-23 Ağu (19-21) | 1-5 Eyl (1-3) | 24-28 Ağu (24-26) |
| Ek yerleştirme tercihi | 6-11 Eylül | 25-30 Eylül | 17-21 Eylül |
| Ek yerleştirme sonucu | 19 Eylül | 6 Ekim | **22 Eyl 2026 itibarıyla açıklanmadı** |
| MSÜ başvuru / sınav / sonuç | 3-30 Oca / 3 Mar / 21 Mar | 2-27 Oca / 23 Şub / 18 Mar | 5-29 Oca / 1 Mar / 24 Mar |
Aralık cümleleri [Ç] (yukarıdaki tarihlerden hesaplandı): sınav→sonuç 27-37 gün · tercih kapanışı→yerleştirme sonucu 8-12 gün · yerleştirme sonucu→kayıt başlangıcı 6-7 gün · tercih penceresi 9-13 gün.
### Kaynak URL'leri (hepsine 22 Eylül 2026'da erişildi)
- Takvim ve duyuru arşivi: `https://www.osym.gov.tr/Sayfa/SinavTakvimi` · `https://www.osym.gov.tr/Duyurular/Index` · `https://www.osym.gov.tr/Duyurular/Index/2025` · `https://www.osym.gov.tr/Duyurular/Index/2024`
- 2026: `/2026yks-basvurularin-alinmasi` · `/2026yks-sinav-sonuclari-aciklandi` · `/2026-yks-tercihlerin-alinmasi` · `/2026-yks-yerlestirme-sonuclari-aciklandi` · `/2026-yks-ek-yerlestirme-icin-tercih-islemleri` · `/2026msu-sinavi-basvurularin-alinmasi` · `/2026msu-sinav-sonuclari-aciklandi`
- 2025: `/2025yks-basvurularin-alinmasi` · `/2025yks-sinav-sonuclari-aciklandi` · `/2025yks-tercihlerin-alinmasi` · `/2025yks-yerlestirme-sonuclari-aciklandi` · `/2025yks-ek-yerlestirme-icin-tercih-islemleri` · `/2025yks-ek-yerlestirme-sonuclari-aciklandi` · `/2025msu-sinavi-basvurularinin-alinmasi` · `/2025msu-sinav-sonuclari-aciklandi`
- 2024: `/2024yks-basvurularin-alinmasi` · `/2024-yuksekogretim-kurumlari-sinavi-2024yks-sonuclari-aciklandi` · `/2024-yuksekogretim-kurumlari-sinavi-yks-tercihlerin-alinmasi` · `/2024-yuksekogretim-kurumlari-sinavi-yks-tercih-suresinin-uzatilmasi` · `/2024yks-yerlestirme-sonuclari-aciklandi` · `/2024yks-ek-yerlestirme-tercihlerinin-alinmasi` · `/2024yks-ek-yerlestirme-sonuclari-aciklandi` · `/2024msu-basvurularinin-alinmasi` · `/2024msu-sinav-sonuclari-aciklandi`
- MEB: `https://www.meb.gov.tr/mebi-2026-2027-yks-ve-lgs-deneme-takvimi-belli-oldu/haber/41943/tr`
- YÖK: `https://egitim.yok.gov.tr/tr/page/492` (Ek Madde 1 uygulama ilkelerinin dayanağı) · Ankara Üni. OİDB: `https://oidb.ankara.edu.tr/2026/01/14/2025-2026-egitim-ogretim-yili-bahar-yariyili-merkezi-yerlestirme-puani-ek-madde-1-ile-yatay-gecis-basvuru-duyurusu/`
## 3. Çıkarılan / yazılmayan iddialar
1. **"2026 takvimi 14.11.2025'te yayımlandı" → yazılmadı.** ÖSYM 2025 duyuru arşivinde (507 kayıt) sınav takvimi yayımına dair tek duyuru yok; takvim duyuru olarak çıkmıyor. Dolayısıyla "2027 takvimi Kasım ortasında beklenir" cümlesi de kuruldu**mad**ı. Yazıda bunun yerine dürüst çıkarım var: ilk işlem (MSÜ başvurusu) Ocak başında başladığına göre takvim ondan önce yayımlanmış oluyor.
2. **Sayaç sitelerindeki 2027 sınav tarihi (19-20 Haziran 2027) → yazılmadı**, yalnızca "bu sayaçlar tahmine dayanır" uyarısı olarak geçti.
3. **2025-YKS geç başvuru penceresi → yazılmadı** (duyuru başlığı var, tarih aralığı metinle doğrulanamadı). Yalnızca 2026'nın geç başvurusu (10-12 Mart 2026, ÖSYM takvim sayfası) verildi.
4. **Ek Madde-1'in "genellikle Ocak-Şubat" olduğu genellemesi → yazılmadı.** Yerine tek somut doğrulanmış örnek kondu (Ankara Üni. 21-23 Ocak 2026) ve "tarihi üniversiten ilan eder" kuralı vurgulandı.
5. **Yerleşme olasılığı/garanti dili yok**; tercih robotu bağlantısı "yerleşme öngörüsü değil, ne kadar yol kaldığını gösteren ölçüm" ifadesiyle verildi. Dilim adları `src/lib/risk.ts` `DILIM_ETIKET` ile uyumlu (hayal / dengeli / **güvenli**).
## 4. Veri kaynağı notu
Bu yazıda DB rakamı kullanılmadı, bu yüzden **SQL sorgusu yok** (`data/yokatlas.db`'ye dokunulmadı). Bütün sayılar tarih ve ÖSYM duyurularından geliyor.
## 5. Takvim açıklandığında güncellenecek satırlar — editör kontrol listesi
`content/rehber/yks-2027-takvimi.md` üzerinde, yayın sırası önemli:
1. **Frontmatter:** `guncelleme: <YYYY-AA-GG>` satırı ekle (`tarih` değişmez).
2. **Kısa cevap paragrafı:** "22 Eylül 2026 itibarıyla ÖSYM 2027 sınav takvimini yayımlamadı" cümlesini "ÖSYM 2027 takvimini <tarih>'te yayımladı; 2027-YKS <sınav tarihi> tarihinde yapılacak" ile değiştir; tarih damgasını yeni güne çek.
3. **Şema (tek mermaid bloğu):** `M`, `B`, `S`, `R`, `T`, `Y`, `K`, `E` düğümlerinin etiketini `BEKLENTİ ·` → `AÇIKLANDI ·` yap ve geçmiş aralık metnini resmî tarihle değiştir. `classDef` ataması `class M,B,... uyari` satırından `class ... garanti` satırına taşınmalı. **`%% aria:` metni de aynı anda güncellenmeli** — aria şu an her kutunun etiketini ve geçmiş aralığını tek tek sayıyor.
4. **Ana tablo (son üç yıl):** "2027 durumu" sütunundaki 10 `BEKLENTİ — açıklanmadı` hücresini resmî tarihlerle doldur. Sütun başlığındaki `(22 Eylül 2026)` damgasını güncelle. Takvimde yer almayan satırlar (sonuç günü, kayıt, ek yerleştirme) **hâlâ beklenti kalır** — ÖSYM takvimde sınav ve başvuru tarihini ilan eder, sonuç gününü taahhüt etmez. Bu ayrım yazıda ayrıca anlatılıyor, silme.
5. **Yan takvim tablosu:** MSÜ üç satırı (başvuru, sınav, sonuç) takvimde yer alır → açıklandığında doldur. MEBİ satırı zaten açıklandı. Ek Madde-1 satırı hiçbir zaman ÖSYM takvimine girmez, "ÜNİVERSİTE TAKVİMİ" kalır.
6. **"ÖSYM 2027 takvimini açıkladı mı?" bölümü:** üç maddelik kontrol listesi (yıl seçeneği yalnızca 2026 / duyurularda 2027 yok / 2026 süreci bitmedi) tamamen geçersizleşir; bölüm "takvim ne zaman yayımlandı, hangi satırlar var, hangileri hâlâ yok" hâline dönüştürülmeli.
7. **SSS:** ilk dört soru (ne zaman yapılacak, başvuru ne zaman, sayaçlar doğru mu, takvim ne zaman yayımlanır) yeniden yazılmalı; "Bu sayfa güncellenecek mi?" sorusu güncelleme tarihiyle birlikte kalabilir.
8. **Kaynaklar:** Sınav Takvimi satırındaki "yıl seçeneği yalnızca 2026" notu düşer; yeni erişim tarihi yazılır ve 2027 duyuru linki eklenir.
### Ara güncelleme (takvimden önce olabilecek iki olay)
- **2026-YKS ek yerleştirme sonucu açıklandığında:** ana tablodaki "22 Eylül 2026 itibarıyla açıklanmadı" hücresi tarihle doldurulur; "2026 süreci henüz bitmedi" gerekçesi bölümden çıkarılır.
- **2027-MSÜ duyurusu YKS takviminden önce çıkarsa** (son üç yılda MSÜ başvurusu Ocak'ın ilk günlerinde açıldı), yan tablodaki üç MSÜ satırı tek başına güncellenebilir.
## 6. Başka yazılarda gördüğüm çelişkiler (rehber-editörü işi — ben dokunmadım)
1. **`content/rehber/tercih-sonuclari-ne-zaman-2026.md`** hâlâ gelecek zamanda: "yerleştirme sonuçları **15-23 Ağustos** arası beklenir" diyor. Gerçekleşen tarih **18 Ağustos 2026** (ÖSYM duyurusu). Yazı geçmiş zamana çevrilmeli ve tahmin aralığı gerçek tarihle değiştirilmeli.
2. **`content/rehber/yks-tercih-takvimi-2026.md`** karışık zamanlı: tercih dönemi geçmiş zamanda, kayıt ve ek yerleştirme adımları gelecek zamanda anlatılıyor. Ek yerleştirme tercihlerinin 17-21 Eylül 2026'da alındığı bilgisi eklenmeli; ikisinden de bu yeni yazıya link verilmeli (SEO planı §4, yazı 7 notu).
3. **ÖSYM duyuru listesi tarihleri ile duyuru sayfası tarihleri bazı kayıtlarda uyuşmuyor** (ör. liste "2024-YKS Sonuçları Açıklandı"yı 12 Temmuz 2024 gösteriyor, duyurunun kendi metni 16 Temmuz 2024 diyor; 2025 sınav sonucunda da 18/19 Temmuz farkı var). Bu yazıda **her zaman duyuru sayfasının kendi metnindeki tarih** kullanıldı. İleride tarih güncelleyen herkes aynı kuralı izlemeli.
## 7. Engeller
- `web.archive.org` CDX servisi bu gece kapalıydı ("Temporarily Offline"), bu yüzden ÖSYM Sınav Takvimi sayfasının 2025 sonu görüntüsüne bakılamadı → takvimin geçmiş yıllardaki yayın günü doğrulanamadı (madde 3.1).
- `mevzuat.gov.tr` yatay geçiş yönetmeliğinin tam metni açılamadı (302/404); YÖK'ün "Ek Madde 1 Uygulama İlkeleri" PDF'i indirildi ama ortamda `pdftotext`/`pdftoppm` olmadığı için metne çevrilemedi. Bu yüzden yönetmelikten doğrudan alıntı yapılmadı; kural, YÖK sayfası + üniversite duyurusu üzerinden anlatıldı.
- ÖSYM `Duyurular/Index` yıl filtresi path tabanlı (`/Duyurular/Index/2025`); query string ile çalışmıyor — sonraki ajanlar için not.
## Bilal'den istenen
1. Yayın öncesi yazının ilk paragrafını bir kez oku: "tahmin yok, sadece geçmiş kaydı" duruşu markanın güven iddiasıyla uyumlu mu? (3 dk)
2. ÖSYM 2027 takvimini yayımladığı gün haber ver ya da bir ajanı tetikle — yazının 8 maddelik güncelleme listesi hazır, iş ~20 dk. (1 dk)
3. `tercih-sonuclari-ne-zaman-2026` ve `yks-tercih-takvimi-2026` yazılarının geçmiş zamana çevrilmesi için rehber-editörüne onay ver. (2 dk)

View File

@@ -0,0 +1,208 @@
# 12 — Rehber yazarı: `ek-madde-1-puanim-yetiyor-mu`
**Tarih:** 22 Eylül 2026 (gece vardiyası) · **Rol:** rehber-yazari · **Dokunulan tek dosya:** `content/rehber/ek-madde-1-puanim-yetiyor-mu.md` (yeni). Commit atılmadı, `git add` yapılmadı, `src/` altına dokunulmadı.
**Kanıt işaretleri:** **[D]** birincil kaynak / kod / DB okundu · **[Ç]** koddan çıkarım · **[doğrulanamadı]** resmî kaynak açılamadı, yazıda iddia edilmedi.
---
## Özet (5 madde)
1. **Katalogda yıl bazlı taban PUANI gerçekten görünüyor — ama iki ayrı yerde.** Tablodaki `Puan` kolonu yalnızca **2026**'yı (`puan2026`) gösteriyor; **2023–2025** taban puanları satırın sağındaki "Son yerleşenin netleri" modalında **"Yerleşme puanı"** satırında. 2021–2022 hiçbir yerde yok. Yazı bu üçlü ayrımı adım adım anlatıyor, olmayan bir ekran uydurmuyor.
2. **Ek Madde-1 kurallarının tamamı iki birincil kaynaktan doğrulandı:** mevzuat.gov.tr'deki yönetmelik metni (Ek Madde-1 + Madde 6/7/8) ve YÖK'ün "Güz ve Bahar Dönemi Ek Madde-1 Uygulama İlkeleri" PDF'i (21 maddelik güz + bahar bölümü). PDF gömülü fontlu olduğu için ToUnicode CMap'i çözülerek metne çevrildi.
3. **Yazının en değerli, kimsede olmayan bulgusu:** ilgili yılın YKS'siyle yerleşip kayıt olan öğrenci **kayıt olduğu yılın güz döneminde Ek Madde-1'e başvuramıyor**; bahar dönemi için başvurabiliyor (YÖK ilkeleri, güz md. 7 / bahar md. 6). Yani 2026'da yerleşenlerin ilk penceresi 2026-2027 bahar — ve bahar dönemini açıp açmamak üniversitenin kararında.
4. **Tarih çerçevesi ikiye ayrıldı:** güz için YÖK'ün kendi ilkesi 1–15 Ağustos (değerlendirme 10 Eylül'e, kayıt 15 Eylül'e kadar) — bu ortak ve resmî. Bahar için **ortak tarih yok**, üniversitenin yetkili kurulu karar veriyor. Pratikte güz bile kayıyor (ODTÜ 2026: 3–14 Ağustos) → yazı tek tarih vermiyor, "okulunun duyurusunu takip et" diyor.
5. **Yazılmayan iki iddia:** sınavsız ikinci üniversite ayrıntıları (Anadolu/AUZEF sayfaları JS-only, sunucudan boş dönüyor) ve DGS'ye kimlerin başvurabileceğinin kılavuz metni (ÖSYM `dokuman.osym.gov.tr` PDF'i "Erişim Engellendi" veriyor). İkisi de tabloda var ama teyit edilemeyen hücreler açıkça işaretlendi.
---
## 1. CTO'ya asıl soru: katalogda yıllık taban puan görünüyor mu?
**Cevap: kısmen — ve yazı tam olarak bu kısmı anlatıyor.**
| Yıl | Kullanıcı nerede görüyor | Dosya:satır | Ekran kısıtı |
|---|---|---|---|
| **2026** (`puan2026`) | Bölüm sayfası tablosunda `Puan` kolonu | `src/features/katalog/components/bolum-program-listesi.tsx:34` (kolon etiketi), `:245-250` (hücre) | `hidden … lg:table-cell` → **yalnız ≥lg** [D] |
| **2026** (`puan2026`) | Üniversite sayfası tablosunda `2026 puan` kolonu | `src/features/katalog/components/universite-program-tablosu.tsx:55` (etiket), `:96-100` (hücre) | `hidden … lg:table-cell` → **yalnız ≥lg** [D] |
| **2025, 2024, 2023** | "Son yerleşenin netleri" modalında **"Yerleşme puanı"** satırı, yıl sütunlu | `src/features/katalog/components/program-netleri.tsx:204-220`; veri `src/lib/db.ts:200-209` → `netler` tablosu, `/api/netler` | Buton her ekranda görünür (`size-8`), modal telefonda da açılır [D] |
| **2021, 2022** | **Görünmüyor.** DB'de `puan2021`/`puan2022` var ama `SELECT_COLS` dışarı çıkarmıyor | `src/lib/db.ts:33-35` — yalnız `puan${SON_YIL} AS puanSon` seçiliyor | — |
| Taban **sıralaması** 2021–2026 | Sparkline + metin özeti | `src/components/program-liste-verileri.tsx:33-50` | Sıra, puan değil — Ek Madde-1 ölçütü puan |
**Netler modalındaki `tabanPuan` gerçekten taban puan mı?** Evet, doğrulandı: 2025 yılı için `netler.tabanPuan` ile `programs.puan2025` 17.301 eşleşen satırın **17.267'sinde birebir aynı** (fark <0,01). Kalan 34 satır veri hattı gürültüsü.
### CTO'ya notlar (yazıyı kod değişikliği olmadan yayımlanabilir tuttum, ama bunlar iyileştirir)
1. **[P1] Bölüm sayfasındaki `Puan` kolon başlığında yıl yok.** Üniversite sayfası `2026 puan` diyor, bölüm sayfası sadece `Puan` (`bolum-program-listesi.tsx:34`, `ALAN_ETIKET`). Ek Madde-1 okuyucusu için "hangi yılın puanı" hayati; iki sayfayı eşitlemek tek satırlık iş. Yazı şu an bunu metinle telafi ediyor ("bölüm sayfasında Puan, üniversite sayfasında 2026 puan").
2. **[P1] `netler` tablosunda 2026 yok.** `SELECT yil, COUNT(*) FROM netler GROUP BY yil` → yalnız 2023/2024/2025. Yani modal "Son yerleşenin netleri" başlığını taşıyor ama en yeni yılı göstermiyor; 2026 netleri YÖK Atlas'ta yayımlandığında `scripts/detay.ts` ile çekilirse bu yazının 5. adımı 2026'yı da kapsar ve modal tek başına Ek Madde-1 aracı olur.
3. **[P2] Ek Madde-1, kataloğun en net "neden bu siteye gelmeliyim" senaryosu.** Bugünkü hâliyle kullanıcı 4 yılın puanını iki farklı yerden topluyor. Ucuz iyileştirme: bölüm/üniversite tablosundaki satıra **yıl × taban puan** mini tablosu (netler modalının puan satırının aynısı, netlerden bağımsız) ya da modal başlığına "yıl bazlı taban puan" ibaresi. Gerçek çözüm: `SELECT_COLS`'a `puan${yil}` serisini eklemek — ama `Program` tipi bilinçli olarak yılsız tutulmuş (`src/lib/db.ts:31-35` yorumu), dolayısıyla bu bir mimari karar, benim çağrım değil.
4. **[P3] 2021–2022 puanı ürün dışında kalıyor.** Bugün 4. sınıfta olan öğrenci (2022 girişli) katalogla Ek Madde-1 kontrolü yapamıyor; yazı onları ÖSYM/YÖK Atlas'a yolluyor. `puan2021`/`puan2022` DB'de duruyor, yalnız sorgudan çıkmıyor.
---
## 2. Doğrulanan kurallar ve kaynakları
### 2.1 Yönetmelik (mevzuat.gov.tr, RG 24.04.2010/27561, son değişiklik 28.02.2026/33182) [D]
Tam metin `https://www.mevzuat.gov.tr/anasayfa/MevzuatFihristDetayIframe?MevzuatTur=7&MevzuatNo=13948&MevzuatTertip=5` üzerinden okundu (ana sayfa iframe kullanıyor; `curl` ile alındı, WebFetch ana URL'de gövdeyi vermiyor).
- **Ek Madde-1(1)** — "Öğrencinin kayıt olduğu yıldaki merkezi yerleştirme puanı, geçmek istediği diploma programının taban puanına eşit veya yüksek olması durumunda, öğrenci, hazırlık sınıfı da dahil olmak üzere yatay geçiş için başvuru yapabilir… Başvurunun kontenjandan fazla olduğu durumlarda ÖSYS puanı en yüksek adaydan başlayıp sıralanarak kontenjan kadar adayın yatay geçişi kabul edilir." (Ek: 21/9/2013, Değişik: 2/5/2014)
- **Ek Madde-1(2)** — azami süre, programın azami süresinden kabul edilen sınıf çıkarılarak hesaplanır. (Ek: 18/3/2016)
- **Madde 6(1)** — lisansta ilk iki ve son iki yarıyıla, önlisansta ilk ve son yarıyıla yatay geçiş yapılamaz (klasik yol için).
- **Madde 6(4)** — açık/uzaktan öğretimden örgüne geçişte GNO **90** (28/2/2026'da 80'den 90'a çıkarıldı) **veya** kayıt yılındaki merkezî yerleştirme puanının hedefin **o yılki** tabanına eşit/yüksek olması.
- **Madde 7(2)(4)** — senato ek kriter belirleyebilir; klasik yatay geçişte GNO + kayıt yılındaki puanın **en az %40'ı** hesaba katılır.
- **Madde 7(5)** — kayıt dondurmuş olmak engel değil.
- **Madde 7(7)** (Ek: 28/2/2026) — "Öğrenciler bulundukları sınıftan daha alt sınıfa yatay geçiş başvurusu yapamaz."
- **Madde 8(1)(2)** (Değişik: 28/2/2026) — sonuçlar değerlendirmeye esas puanlara göre **sıralı** ilan edilir; asıl sayısı kadar **yedek** belirlenir.
### 2.2 YÖK, Güz ve Bahar Dönemi Ek Madde-1 Uygulama İlkeleri [D]
`https://egitim.yok.gov.tr/tr/document/2853` → `…/documentFiles/1779278338729.guz-ve-bahar-donemi-ek-madde-1-uygulama-ilkeleri.pdf` (7 sayfa). Planda geçen `…1759306423605…` dosya adı **404**; güncel dosya adı değişmiş, doğru giriş `egitim.yok.gov.tr/tr/page/492` sayfasındaki "Güz ve Bahar Dönemi Ek Madde 1 Uygulama İlkeleri" bağlantısı.
Yazıda kullanılan maddeler (güz numaralandırması):
| Md. | Doğrulanan kural |
|---|---|
| 1 | Kılavuzdaki bir programa merkezî yerleştirme / ilgili yılın puanı / özel yetenekle kayıt yaptıranlar başvurabilir. ÖSYM ile yurt dışındaki kılavuz programına yerleşenler de. Kılavuzda olmayan yurt dışı kurumlarına kendi imkânıyla kayıt olanlar **başvuramaz**. |
| 2 | **"Öğrencinin kayıt olduğu yıldaki merkezi yerleştirme puanlarının başka bir diploma programının girdiği yıldaki taban puanına eşit veya yüksek olması"**. YÖK'ün örneği: TM-1 ile İşletme'ye kayıtlı öğrencinin **aynı yıla ait MF-4 puanı** İnşaat Müh. tabanını geçiyorsa başvurabilir → **puan türü yerleştiği türle sınırlı değil**. |
| 3 | Özel yetenekle kayıt olanlar başvurabilir; **özel yetenekle öğrenci alan programlara başvurulamaz** (ÖZYES hariç). |
| 4 | Ön lisans↔lisans geçişi mümkün. |
| 5–6 | **Sadece bir defa**; ama geçiş yapan öğrenci sonraki başvuru tarihlerinde eski programına **geri dönebilir**. |
| 7 (güz) | İlgili yılda yerleşip kayıt olan öğrenci **kayıt yılının güz döneminde başvuramaz**; bir sonraki dönem/yılda başvurabilir. **6 (bahar):** aynı öğrenciler **bahar için başvurabilir**. |
| 8 (güz) / 7 (bahar) | Hazırlık, ara sınıflar ve son sınıf dahil kayıtlı öğrenciler yararlanır; intibakı ilgili kurul yapar. |
| 9 (güz) / 8 (bahar) | Kontenjan: hazırlık dahil **her bir sınıf için** kılavuz kontenjanının **%30'u, 90'ı geçmemek üzere**. YÖK örneği: kontenjan 120 → 36; kontenjan 400 → %30=120 olsa da **90**. |
| 9 (bahar sıralı 9) | Ara sınıfta, başvurulan yılda o programa öğrenci alınmamışsa öğrencinin **kayıt yılındaki** kılavuz kontenjanı esas alınır. |
| 10 (güz) | **Başvurular 1 Ağustos–15 Ağustos dahil**; değerlendirme **10 Eylül**'e kadar ilan; kayıtlar **15 Eylül**'e kadar; **üniversitelerin ayrıca kontenjan ilan etmesi gerekmez**. |
| 10 (bahar) | **Bahar için Ek Madde-1 ile öğrenci alınıp alınmayacağına üniversitelerin yetkili kurulları karar verir**; alacak olanlar kontenjan ilan eder, işlemleri dönem başlamadan bitirir. → "üniversiteye göre değişir" yazının kendi cümlesi. |
| 11 | Başvuru > kontenjan ise **ÖSYM puanı en yüksek adaydan** başlanarak kontenjan kadar aday. |
| 13 | DGS puanıyla yalnız DGS kılavuzunda tanımlı lisans programlarına; **ilgili yılda DGS ile öğrenci alınmamışsa başvurulamaz**. |
| 15 | Taban puan kaynağı: osym.gov.tr'deki "ilgili yıla ait … Merkezi Yerleştirmedeki En Küçük ve En Büyük Puanlar" yayını. |
| 16 | Kılavuzdaki **özel koşullar** (başarı sırası vb.) sağlanmalı. |
| 17 | **Öğrencinin kayıt yılında hedef programa öğrenci alınmamışsa taban puan oluşmadığından geçiş yapılamaz.** |
| 18–19 | Yabancı dil şartı üniversitenin; **iki yıl hazırlık okumuş tekrar hazırlık okuyamaz**; hazırlıkta başarısız olup kayıtlı olanlar başvurabilir. |
| 20 | **"Sadece … yerleştiği yıldaki ÖSYM merkezi yerleştirme puanlarının dikkate alınmasına, başarı vb. şart aranmamasına."** |
| 21 | Vakıf üniversitelerinde **ücretli** programlara geçilebilir; **burs verip vermeme üniversitenin yetkisinde**. |
### 2.3 Üniversite uygulaması ve diğer kaynaklar [D]
- ODTÜ OİDB — 2026-2027 güz Ek Madde-1 başvuruları **3–14 Ağustos 2026**, sistem 14 Ağustos 17.00'de kapandı. YÖK ilkesindeki 1–15 Ağustos'tan **farklı** → yazı tek tarih vermiyor. `https://oidb.metu.edu.tr/tr/merkezi-yerlestirme-puani-ile-yatay-gecis-ek-madde-1` (200)
- Ankara Üni. OİDB — 2026-2027 güz duyurusu (27.07.2026). `https://oidb.ankara.edu.tr/2026/07/27/…` (200)
- ÖSYM — 2026-DGS başvuru **15 Mayıs–2 Haziran 2026**, sınav **19 Temmuz 2026**. `https://www.osym.gov.tr/2026dgs-basvurularin-alinmasi` (200)
- ÖSYM — 2026-YKS sayısal bilgiler sayfası (en küçük/en büyük puan yayını). `https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclarina-iliskin-sayisal-bilgiler` (200)
Tüm kaynak URL'lerinin HTTP durumu `curl -sIL` ile tek tek kontrol edildi; yazıdaki 9 dış bağlantının hepsi 200.
---
## 3. Kullanılan SQL sorguları (hepsi `sqlite3 -readonly data/yokatlas.db`)
**(a) Netler modalındaki "Yerleşme puanı" ile tablodaki taban puanın aynı olduğunun ispatı** → 17.301 satırın 17.267'si birebir aynı:
```sql
SELECT COUNT(*) AS eslesen_satir,
SUM(ABS(n.tabanPuan - p.puan2025) < 0.01) AS birebir_ayni
FROM netler n JOIN programs p ON p.id = n.program_id
WHERE n.yil = 2025 AND n.tabanPuan IS NOT NULL AND p.puan2025 IS NOT NULL;
-- 17301|17267
```
**(b) Netler tablosunun yıl kapsamı** → modalda 2026 YOK:
```sql
SELECT yil, COUNT(*), SUM(tabanPuan IS NOT NULL) FROM netler GROUP BY yil ORDER BY yil;
-- 2023|21341|21341 2024|20813|20809 2025|20821|20820
```
**(c) Yazıdaki "3.150 program" ve "18.251 program" rakamları** (YÖK ilkeleri md. 17'nin somut karşılığı):
```sql
SELECT COUNT(*) AS toplam_2026_program,
SUM(puan2026 IS NOT NULL) AS puan2026_dolu,
SUM(puan2025 IS NOT NULL) AS puan2025_dolu,
SUM(puan2024 IS NOT NULL) AS puan2024_dolu,
SUM(puan2023 IS NOT NULL) AS puan2023_dolu,
SUM(puan2026 IS NOT NULL AND puan2023 IS NULL) AS y2026_var_2023_yok
FROM programs;
-- 21493|18251|17304|18355|16504|3150
```
**(d) "2024 için 18.225, 2025 için 19.652 program" (netler modalı kapsamı):**
```sql
SELECT
(SELECT COUNT(*) FROM programs p WHERE EXISTS(SELECT 1 FROM netler n
WHERE n.program_id=p.id AND n.yil=2024 AND n.tabanPuan IS NOT NULL)) AS n2024,
(SELECT COUNT(*) FROM programs p WHERE EXISTS(SELECT 1 FROM netler n
WHERE n.program_id=p.id AND n.yil=2025 AND n.tabanPuan IS NOT NULL)) AS n2025;
-- 18225|19652
```
**(e) Yazıdaki 4 satırlık yıl × taban puan tablosu** (birebir bu çıktı kullanıldı):
```sql
SELECT universite, isim, fakulte, tur,
ROUND(puan2023,2), ROUND(puan2024,2), ROUND(puan2025,2), ROUND(puan2026,2)
FROM programs
WHERE (universite='MARMARA ÜNİVERSİTESİ' AND isim='Bilgisayar Mühendisliği' AND fakulte='Mühendislik Fakültesi')
OR (universite='ANKARA ÜNİVERSİTESİ' AND isim='Hukuk')
OR (universite='HACETTEPE ÜNİVERSİTESİ' AND isim='Psikoloji')
OR (universite='EGE ÜNİVERSİTESİ' AND isim='Makine Mühendisliği');
-- Marmara Bilgisayar Müh. (Müh.Fak.) 521,30 · 499,01 · 486,37 · 483,05
-- Ankara Hukuk 471,29 · 456,38 · 461,84 · 475,14
-- Hacettepe Psikoloji (Edebiyat Fak.) 461,76 · 444,25 · 441,11 · 449,13
-- Ege Makine Müh. (Müh.Fak.) 460,94 · 437,19 · 453,61 · 471,97
```
Yazıdaki örnek hesap (SAY 495 puanla Marmara Bilgisayar Müh.) tamamen bu dört sayıdan türetildi; 2024'te yerleşen 4 puanla kaçırıyor, 2025'te yerleşen sağlıyor.
---
## 4. Çıkarılan / yazılmayan iddialar
1. **Sınavsız ikinci üniversitenin ayrıntıları yazılmadı.** `ikinciuniversite.anadolu.edu.tr` ve `auzef.istanbul.edu.tr` tamamen istemci tarafı render; `curl` "LÜTFEN BEKLEYİNİZ" / boş başlık dönüyor, WebFetch de aynı. Kim kaydolabilir, ücret, takvim — hiçbiri iddia edilmedi. Karşılaştırma tablosunda sütun duruyor ama altına **açık uyarı** konuldu: "Son sütundaki ayrıntılar … resmî kaynaktan teyit edilemedi; tabloda yalnızca Ek Madde-1'den yapısal farkını göstermek için var."
2. **DGS'nin "kimler başvurabilir" kılavuz metni yazılmadı.** `dokuman.osym.gov.tr/web/2026/7/genel-bilgiler-temel-lke-ve-kurallar-…pdf` **"Erişim Engellendi"** HTML'i döndürüyor (200 ama PDF değil). Tabloda yalnız doğrulanabilen iki şey var: kılavuzdaki Tablo-2'nin ön lisans alanına göre geçilebilecek lisans programlarını tanımlaması (YÖK ilkeleri md. 13 ile örtüşüyor) ve 2026 tarihleri (ÖSYM duyurusu).
3. **"Yerleşme olasılığı / geçersin" dili yok.** Yazı üç yerde açıkça "şartı sağlamak kabul edilmek değildir" diyor; kontenjan bölümü bunu bir paragrafla bitiriyor.
4. **Madde 7(7) (alt sınıfa başvuru yasağı) iddia olarak değil, mevzuat alıntısı + "teyit et" uyarısıyla yazıldı.** Hükmün Ek Madde-1 başvurularına nasıl uygulandığı YÖK'ün uygulama ilkelerinde ayrıca düzenlenmemiş; bu boşluk okura açıkça söylendi (3. sınıftan 1. sınıfa geçmeyi planlayan öğrenci için).
5. **Klasik yatay geçişte "kaç kez yapılabilir" için negatif iddia yumuşatıldı:** "yönetmelikte sayı sınırı yok" yerine "yönetmelikte sayı sınırı belirtilmiyor; yarıyıl ve kontenjan sınırları geçerli".
6. **Tek bir başvuru tarihi verilmedi.** Güz için YÖK'ün ortak ilkesi (1–15 Ağustos) kaynağıyla yazıldı ama hemen ardından ODTÜ'nün 3–14 Ağustos'u örnek verilip "okulunun duyurusunu takip et" denildi. Bahar için "ortak tarih yok, üniversite karar verir".
---
## 5. Diğer yazılarla tutarlılık (rehber-editoru'ne not — ben düzeltmedim)
- `content/rehber/yatay-gecis-cap-yandal.md` §1: "**Kayıt olduğun yıldaki YKS puanın**… aynı yıldaki taban puanına" — **doğru**, yeni yazıyla ve YÖK ilkeleriyle uyumlu. Aynı yazıdaki "Bu haktan bir kez yararlanılır" da **doğrulandı** (YÖK ilkeleri md. 5–6). Değişiklik gerekmiyor; yalnız o yazının 1. bölümünden yeni yazıya **derinlemesine link** verilmesi planda vardı (`02-seo-geo-konu-plani.md` #10) — henüz yok, eklenmeli.
- `content/rehber/yatay-gecis-cap-yandal.md` §2: "Hazırlıkta yatay geçiş yapılmaz" cümlesi **klasik yatay geçiş** için doğru (Yönetmelik md. 6/1) ama Ek Madde-1'de **hazırlık sınıfı öğrencileri başvurabiliyor** (Ek Madde-1(1) + ilkeler md. 8). O yazıda cümle "not ortalamasıyla yatay geçiş" başlığı altında olduğu için çelişki değil, ama okurda karışıklık yaratabilir — yeni yazıya bir "Ek Madde-1'de hazırlık dahil" köprüsü faydalı olur.
- `content/rehber/mezuna-kalmak-mi-kayit-olmak-mi.md` ve `universite-okurken-tekrar-yks.md`, "kayıt olursan Ek Madde-1 kapısı açık" çerçevesini kuruyor. **Eksik nüans:** bu yıl yerleşip kayıt olan öğrenci kayıt yılının **güz** döneminde başvuramıyor; ilk pencere bahar. Bu iki yazıya tek cümlelik ekleme değerli olur (kayıt kararını doğrudan etkiliyor). **Ben dokunmadım.**
- SEO planındaki (`05-seo-plan.md` §4-8) "2021–2025 taban puanları var" varsayımı **yanlış**: ekranda 2023–2025 (netler modalı) + 2026 (kolon) var; 2021–2022 yok. Yazı buna göre kuruldu.
---
## 6. Engeller
- `egitim.yok.gov.tr` Ek Madde-1 PDF'i gömülü alt-küme fontlu ve makinede `pdftotext`/`pypdf`/`Quartz` yok; PDF'in ToUnicode CMap'leri çözülüp metin elle decode edildi (`scratchpad/pdftxt2.py`). WebFetch bu PDF'i okuyamadı (ham binary döndü).
- `mevzuat.gov.tr` ana sayfası gövdeyi iframe'den yüklüyor; WebFetch boş dönüyor. `curl` + `…/MevzuatFihristDetayIframe?...` ile okundu.
- `dokuman.osym.gov.tr` PDF'leri bota "Erişim Engellendi" veriyor.
- Anadolu/AUZEF ikinci üniversite sayfaları JS-only.
- **Şema tarayıcıda render edilmedi** (kural gereği dev sunucusu/preview açılmadı). Bunun yerine mermaid 11.16.0 parser'ı node'da çalıştırıldı: şema **gramer aşamasını geçiyor**, yalnız DOM olmadığı için `DOMPurify.sanitize` aşamasında duruyor — bilerek bozulmuş bir şema aynı testte "Parse error on line 3" veriyor. Yani sözdizimi geçerli [Ç: parse aşamasına dayalı çıkarım, görsel doğrulama değil].
- Hiçbir web sayfasında bana yönelik talimat görülmedi.
---
## 7. Yazının biçim kontrolü
`content/rehber/ek-madde-1-puanim-yetiyor-mu.md` üzerinde `src/lib/rehber.ts`'teki parser kuralları birebir çalıştırıldı:
- Frontmatter: `baslik`, `aciklama` (tırnaksız), `tarih: 2026-09-22` → 3 alan da okundu.
- Mermaid: **tam 1 adet** `flowchart TD`; `%% aria:` var (1.427 karakter), `%% altyazi:` var.
- Tablo: 3 tablo (yıl × taban puan · katalogda nereye bakılır · Ek Madde-1 / klasik yatay geçiş / DGS / ikinci üniversite) — karşılaştırma tablosu şartnamedeki dört yolu içeriyor.
- H2 sayısı 10, hepsi soru biçiminde (Kaynaklar hariç).
- İlk paragraf `**Kısa cevap:**` ile başlıyor ve tek başına cevap veriyor.
- Renk kodları: `hayal`/`uyari`/`garanti` classDef'leri kullanıldı, **her kutu KAPALI / BEKLE / AÇIK / SIRALAMA metin etiketiyle başlıyor**; aria metninin sonunda "renkler tek başına anlam taşımaz" cümlesi var.
- İç linkler: 7 rehber yazısı + 4 `/bolum/` + 4 `/universite/`. **Hepsi doğrulandı** — rehber slug'ları dosya varlığıyla, bölüm/üniversite slug'ları `turkishSlugify(bolumBazAdi(isim))` kuralı ve DB'deki `isim`/`universite` değerleriyle (`İşletme`, `Psikoloji`, `Bilgisayar Mühendisliği`, `Hukuk`, `Makine Mühendisliği` → hepsi mevcut).
---
## Bilal'den istenen
1. **Yayın öncesi tek göz kontrolü:** yazının "Kendi puanını kataloğumuzdaki yıl tablosuyla nasıl karşılaştırırsın?" bölümündeki 7 adımı kendi telefonunda bir bölüm sayfasında dene — netler modalındaki "Yerleşme puanı" satırı gerçekten anlattığım gibi görünüyor mu? (3 dk)
2. **Karar:** `netler` verisine 2026 yılı çekilsin mi? Çekilirse bu yazının ürün bağı tamamlanır, çekilmezse modal "son yerleşen" derken 2025'i gösteriyor olmaya devam eder. (1 dk karar, veri-mühendisi işi)
3. **Karar:** bölüm sayfasındaki `Puan` kolon başlığına yıl eklensin mi (üniversite sayfasıyla eşitlensin mi)? (1 dk karar, tek satır)

View File

@@ -0,0 +1,237 @@
# 13 — Rehber yazısı: `bilgisayar-mi-yazilim-muhendisligi-mi`
**Tarih:** 22 Eylül 2026, gece · **Rol:** rehber-yazari · **Dosya:** `content/rehber/bilgisayar-mi-yazilim-muhendisligi-mi.md` (170 satır, yeni) · **Commit atılmadı.**
Kanıt işaretleri: **[D]** DB sorgusu / birincil kaynak açıldı · **[A]** yalnızca arama özeti · **[Ç]** çıkarım · **[doğrulanmalı]** yayın öncesi teyit şart.
---
## Özet (5 madde)
1. Yazı fikir değil veri üzerine kuruldu. Ana bulgu: **iki bölümü birden açan ve ikisinde de 2026 tabanı oluşan 56 üniversitenin 54'ünde Bilgisayar Mühendisliği daha seçici kapandı** (ortanca fark 19.550 sıra); 2 istisna Fırat ve Harran. Devlet tarafındaki 23 üniversitenin tamamı tablo hâlinde yazıda; vakıftan 13 örnek verildi (33'ünün 33'ünde Bilgisayar daha seçici).
2. İkinci ayırt edici bulgu doluluk: devlette iki bölüm de doluyor (BM %99,8 · YM %102,1), vakıfta ayrışıyor (BM %60,7 · **YM %32,9**). "Yazılım Mühendisliği daha kolay mı?" sorusu bu iki tabloyla dürüstçe yanıtlandı: sayısal olarak evet girmesi daha kolay, ama bunun nedeni bölümün kendisi değil **hangi üniversitelerde açıldığı** (BM 173 üniversite, YM 74).
3. Müfredat karşılaştırması uydurulmadı: Çankaya Üniversitesi'nin **kendi yayımladığı** iki zorunlu ders listesi (ceng + yazilim bölüm siteleri) yan yana konuldu, "bu tek bir üniversitenin planıdır, müfredatlar üniversiteye göre değişir" cümlesi hem tablo öncesinde hem sonrasında yazıldı.
4. İş imkânı/maaş konusunda **hiç rakam verilmedi**; okur `bolumun-is-imkanini-nasil-arastirirsin` yazısına yollandı ve arz tarafı yalnızca kendi kontenjan verimizle (17.267 kontenjan / 14.179 yerleşen) anlatıldı.
5. **Veri kalitesi bulgusu (veri-muhendisi'ne):** `programs` tablosunda ODTÜ Kuzey Kıbrıs Kampusu programları ana kampüsle **aynı `universite` ve `il` değeri** altında duruyor. Bu yüzden ODTÜ head-to-head tablosundan çıkarıldı ve neden çıkarıldığı yazıda açıkça belirtildi. Ayrıntı aşağıda.
---
## Yazının iskeleti ve format uyumu
- Frontmatter: `baslik`, `aciklama` (tırnaksız), `tarih: 2026-09-22`. ✔
- İlk paragraf "Kısa cevap:" ile başlıyor, tek başına cevap veriyor. ✔
- **1 adet** ```mermaid `flowchart TD`, içinde `%% aria:` (tam düz metin anlatım) ve `%% altyazi:`. Renkler `uyari`/`garanti`/`hayal` classDef'leriyle mevcut yazılarla aynı; **her kutuda metin etiketi var**, renk tek başına anlam taşımıyor. ✔
- **4 tablo** (özet kıyas, devlet head-to-head 23 satır, vakıf head-to-head 13 satır, müfredat kıyası). ✔
- Bütün H2'ler soru biçiminde. ✔
- Sonda erişim tarihli "Kaynaklar". ✔
- Vaat/garanti dili yok; yerleşme olasılığı verilmedi. ✔
- **50 iç link, 0 kırığı** — betikle doğrulandı (`/bolum/*` slug'ları `bolumBazAdi`+`turkishSlugify` ile DB'deki `isim` kümesinden, `/universite/*` slug'ları `uniSayfaSlug` ile DB'deki `universite` kümesinden, `/rehber/*` slug'ları `content/rehber/` dosya listesinden, `/tercih-robotu` `next.config.ts` kalıcı yönlendirmesinden). Görevde istenen 6 iç linkin tamamı kullanıldı.
- Mermaid bloğunun `%% aria` / `%% altyazi` ayrıştırması `src/lib/rehber.ts` beklentisine uyuyor (betikle kontrol edildi). Mermaid'in kendi `parse`'ı Node'da DOM olmadığı için koşmadı (`DOMPurify.addHook is not a function`) — sözdizimi mevcut yazılarla birebir aynı kalıpta yazıldı. [Ç]
---
## Kullanılan SQL sorguları ve çıktıları
Hepsi `sqlite3 -readonly data/yokatlas.db` ile çalıştırıldı. Ortak havuz tanımı (her sorguda tekrar eder):
```sql
WHERE (isim LIKE 'Bilgisayar Mühendisliği%' OR isim LIKE 'Yazılım Mühendisliği%')
AND onlisans = 0
AND unitur IN ('DEVLET','VAKIF')
AND isim NOT LIKE '%KKTC Uyruklu%'
```
`/bolum/<slug>` sayfaları parantezli varyantları (İngilizce, Burslu, %50 İndirimli…) aynı bölümde topladığı için havuz da `isim LIKE '<ad>%'` ile kuruldu — katalogla aynı gruplama.
### S1 — Program sayısı, kontenjan, yerleşen, doluluk (yazıdaki 1. tablo)
```sql
WITH t AS (
SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END AS bolum,
unitur, kontenjan2026, yerlesen2026, sira2026
FROM programs
WHERE (isim LIKE 'Bilgisayar Mühendisliği%' OR isim LIKE 'Yazılım Mühendisliği%')
AND onlisans = 0 AND unitur IN ('DEVLET','VAKIF') AND isim NOT LIKE '%KKTC Uyruklu%')
SELECT bolum, COUNT(*) program, SUM(unitur='DEVLET') devlet, SUM(unitur='VAKIF') vakif,
SUM(COALESCE(kontenjan2026,0)) kontenjan, SUM(COALESCE(yerlesen2026,0)) yerlesen,
ROUND(100.0*SUM(COALESCE(yerlesen2026,0))/SUM(COALESCE(kontenjan2026,0)),1) doluluk,
SUM(sira2026 IS NOT NULL) tabani_olan
FROM t GROUP BY bolum;
```
| bolum | program | devlet | vakif | kontenjan | yerlesen | doluluk | tabanı olan |
|---|---|---|---|---|---|---|---|
| BM | 303 | 134 | 169 | 12.993 | 11.285 | %86,9 | 214 |
| YM | 133 | 44 | 89 | 4.274 | 2.894 | %67,7 | 83 |
### S2 — Devlet/vakıf kırılımında doluluk
Aynı sorgu `GROUP BY bolum, unitur` ile:
| bolum | unitur | program | kontenjan | yerlesen | doluluk | tabanı olan |
|---|---|---|---|---|---|---|
| BM | DEVLET | 134 | 8.700 | 8.680 | %99,8 | 120 |
| BM | VAKIF | 169 | 4.293 | 2.605 | %60,7 | 94 |
| YM | DEVLET | 44 | 2.148 | 2.194 | %102,1 | 40 |
| YM | VAKIF | 89 | 2.126 | 700 | %32,9 | 43 |
### S3 — Programı bulunan üniversite sayısı
```sql
SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END bolum,
COUNT(DISTINCT universite) uni_sayisi
FROM programs WHERE <ortak havuz> GROUP BY 1;
```
→ **BM 173 · YM 74.** (Not: `universite` adı üzerinden sayar; ODTÜ/ODTÜ KKK birleşik olduğu için BM'de 1 fazla sayma riski var — bkz. veri kalitesi notu. [Ç])
Kapsama örtüşmesi (yazıda kullanılmadı ama karar verdirdi):
```sql
WITH t AS (SELECT universite, unitur,
CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'bm' ELSE 'ym' END b
FROM programs WHERE <ortak havuz>),
u AS (SELECT universite, unitur, MAX(b='bm') bm, MAX(b='ym') ym FROM t GROUP BY universite, unitur)
SELECT unitur, SUM(bm=1 AND ym=1) ikisi_de, SUM(bm=1 AND ym=0) sadece_bm,
SUM(bm=0 AND ym=1) sadece_ym, COUNT(*) toplam FROM u GROUP BY unitur;
```
→ DEVLET: 25 ikisi de / 84 sadece BM / 8 sadece YM (117 üni). VAKIF: 35 / 29 / 6 (70 üni).
### S4 — Devlet programlarında en seçici, medyan, en açık taban sırası
```sql
WITH t AS (
SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END bolum, sira2026
FROM programs WHERE <ortak havuz> AND unitur='DEVLET' AND sira2026 IS NOT NULL),
n AS (SELECT bolum, sira2026, ROW_NUMBER() OVER (PARTITION BY bolum ORDER BY sira2026) rn,
COUNT(*) OVER (PARTITION BY bolum) c FROM t)
SELECT bolum, c AS tabani_olan, MIN(sira2026) en_secici, MAX(sira2026) en_acik,
(SELECT sira2026 FROM n n2 WHERE n2.bolum=n.bolum AND n2.rn=(n.c+1)/2) medyan
FROM n GROUP BY bolum;
```
| bolum | tabanı olan program | en seçici | medyan | en açık |
|---|---|---|---|---|
| BM | 120 | 2.503 | **135.495** | 274.606 |
| YM | 40 | 62.224 | **191.877** | 299.241 |
> Uyarı: YM'nin `en_acik` değeri 299.241, ODTÜ KKK satırından geliyor. Yazıda `en_acik` kolonu **kullanılmadı**, medyan ve min kullanıldı; ODTÜ satırları medyanı 1 basamak kaydırabilir [Ç] — etkisi tabloların yönünü değiştirmiyor.
### S5 — Sıralama bandına göre erişilebilir program sayısı
```sql
WITH t AS (SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END bolum, sira2026
FROM programs WHERE <ortak havuz> AND sira2026 IS NOT NULL)
SELECT bolum, SUM(sira2026<=50000) ilk50k, SUM(sira2026<=100000) ilk100k,
SUM(sira2026<=150000) ilk150k, SUM(sira2026<=200000) ilk200k, COUNT(*) toplam
FROM t GROUP BY bolum;
```
→ BM: 33 / 98 / 146 / 173 (toplam 214). YM: **1** / 24 / 51 / 61 (toplam 83).
### S6 — En seçici 10 program (yazıda 520 ve 41.275 rakamlarının kaynağı)
```sql
SELECT universite, isim, unitur, kontenjan2026, yerlesen2026, sira2026 FROM programs
WHERE isim LIKE 'Bilgisayar Mühendisliği%' AND <ortak havuz kalanı> AND sira2026 IS NOT NULL
ORDER BY sira2026 LIMIT 10; -- YM için isim LIKE 'Yazılım Mühendisliği%'
```
→ BM tepe: Koç 520 · İTÜ 2.503 · Bilkent 2.646 · ODTÜ 2.989 · Boğaziçi 4.560.
→ YM tepe: **Bahçeşehir 41.275** · TED 50.763 · Ankara Üni 62.224 · İzmir Ekonomi 65.718.
### S7 — Head-to-head (yazının ana bulgusu)
Kural: her üniversitede o bölümün **en seçici** (MIN `sira2026`) programı alınır; ODTÜ hariç.
```sql
WITH t AS (
SELECT universite, unitur,
CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'bm' ELSE 'ym' END b, sira2026
FROM programs WHERE <ortak havuz> AND sira2026 IS NOT NULL
AND universite <> 'ORTA DOĞU TEKNİK ÜNİVERSİTESİ'),
u AS (SELECT universite, unitur,
MIN(CASE WHEN b='bm' THEN sira2026 END) bm,
MIN(CASE WHEN b='ym' THEN sira2026 END) ym
FROM t GROUP BY universite, unitur)
SELECT unitur, COUNT(*) cift, SUM(bm<ym) bm_secici, SUM(ym<bm) ym_secici
FROM u WHERE bm IS NOT NULL AND ym IS NOT NULL GROUP BY unitur;
```
| unitur | çift | BM daha seçici | YM daha seçici |
|---|---|---|---|
| DEVLET | 23 | 21 | 2 (Fırat, Harran) |
| VAKIF | 33 | 33 | 0 |
| **toplam** | **56** | **54** | **2** |
Medyan fark (aynı CTE üzerinden `ym-bm` medyanı): **+19.550 sıra**.
Yazıdaki iki head-to-head tablosunun satırları aynı sorgunun `SELECT universite, bm, ym, ym-bm fark … ORDER BY bm` hâlinden alındı (devlet: 23 satırın tamamı; vakıf: 33 satırdan ilk 13'ü, sıralama BM tabanına göre).
> **Yöntem notu — neden MIN, neden "en büyük kontenjanlı satır" değil?** Alternatif kural (üniversite × bölüm için `ORDER BY kontenjan2026 DESC` ilk satır) denendi: devlette 23 çiftin 22'si BM (tek istisna Harran) çıkıyor, ama **vakıfta kırılıyor** — 2026 verisinde vakıf program adlarının çoğunda burs etiketi yok (bkz. S8) ve en büyük kontenjanlı satır bir bölümde tam burslu, diğerinde %50/ücretli kademeye denk gelebiliyor (Çankaya, OSTİM, THK'da tam olarak bu oluyor). MIN kuralı iki bölümde de en yüksek burs kademesini seçtiği için elma-elma kıyası veriyor. Yazıda kullanılan kural MIN'dir ve yazıda açıkça anlatılmıştır.
### S8 — Vakıf burs kademeleri (yazıda rakam olarak KULLANILMADI, yöntem kararını verdirdi)
```sql
... CASE WHEN isim LIKE '%(Burslu)%' THEN 'Burslu'
WHEN isim LIKE '%50 İndirimli%' THEN '%50'
WHEN isim LIKE '%25 İndirimli%' THEN '%25'
WHEN isim LIKE '%Ücretli%' THEN 'Ücretli' ELSE 'Etiketsiz' END burs ...
```
→ Vakıf BM'de 169 programın **130'u**, YM'de 89 programın **72'si** etiketsiz. Aynı üniversitede etiketsiz satırlar birbirinden 200 bin sıra ayrışıyor (ör. Çankaya BM: 57.882 ve 265.073) — yani etiket gerçekte var, veride yok.
### S9 — 2025 → 2026 yönü
```sql
WITH t AS (SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END bolum,
sira2025, sira2026
FROM programs WHERE <ortak havuz> AND sira2025 IS NOT NULL AND sira2026 IS NOT NULL)
SELECT bolum, COUNT(*) iki_yil, SUM(sira2026<sira2025) sikilasti, SUM(sira2026>sira2025) gevsedi
FROM t GROUP BY bolum;
```
→ BM: 202 programın **185'i gevşedi**, 17'si sıkılaştı. YM: 81'in **79'u gevşedi**, 2'si sıkılaştı.
---
## Doğrulanan dış bilgiler + URL'ler
| İddia | Kaynak | Durum |
|---|---|---|
| 2026-YKS yerleştirme sonuçları 18 Ağustos 2026'da açıklandı | https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi (duyuru tarihi ve metni okundu) | **[D]** teyit edildi |
| Çankaya Bilgisayar Müh. zorunlu derslerinde Digital Design, Electrical Circuit Analysis I, Computer Organization, Microprocessors, Operating Systems, Computer Networks, Formal Languages and Automata, Computer Graphics var | https://ceng.cankaya.edu.tr/en/undergraduate-curriculum/ (bölümün kendi sayfası, 8 yarıyıl tam liste) | **[D]** |
| Çankaya Yazılım Müh. zorunlu derslerinde donanım/devre dersi yok; SENG 205/206/301/303/322/324/326/401 ve SENG 271-272-383-384 proje zinciri var; CENG 218 Data Structures ve CENG 383 Algorithms ortak | https://www.yazilim.cankaya.edu.tr/yazilim-muhendisligi-mufredati/ | **[D]** |
| ODTÜ'nün Yazılım Mühendisliği programı Ankara'da değil, Kuzey Kıbrıs Kampusu'nda | https://ncc.metu.edu.tr/tr/sng/anasayfa (+ aynı kampüste ayrıca Bilgisayar Müh.: https://ncc.metu.edu.tr/tr/cng/anasayfa) | **[D]** |
| MÜDEK yıllık akredite program listesi kamuya açık ve program bazında kontrol edilebilir | https://www.mudek.org.tr/tr/akredit/akredite2026.shtm ("01 Temmuz 2026 itibarıyla" başlığı okundu) | **[D]** — yalnızca bağlantı verildi, sayı verilmedi |
Web sayfalarında bana yönelik talimat görülmedi.
---
## Çıkarılan / yazılmayan iddialar
1. **MÜDEK akredite program sayıları.** Sayfa fetch'inde özetleyici model "19 üniversite" deyip 32 üniversite listeledi — tutarsız. Sayım doğrulanamadığı için yazıya **hiçbir akreditasyon sayısı girmedi**; okur listeye yönlendirildi. [doğrulanmalı — isteyen editör sayfayı elle sayabilir]
2. **İş imkânı ve maaş rakamları.** Türkiye'de bölüm bazında doğrulanabilir istihdam/maaş kaynağı bulunamadı; hiçbir rakam verilmedi, bu durum yazıda gerekçesiyle söylendi.
3. **"Yazılım Mühendisliği daha yeni bir bölüm" cümlesi.** Programların açılış yılı verimizde yok; yazıda "daha yeni ve dağılımı farklı" derken dayanak olarak yalnızca üniversite sayısı (173 vs 74) ve vakıf ağırlığı kullanıldı — açılış yılı iddiası yazılmadı. [Ç]
4. **Genel müfredat iddiası.** "Bilgisayar Müh. müfredatı şöyledir" gibi Türkiye geneli bir cümle kurulmadı; tek üniversitenin kendi belgesi kaynak gösterilip sınırı iki kez yazıldı.
5. **ODTÜ head-to-head satırı.** Ham veri ODTÜ için BM 2.989 vs YM 299.241 veriyordu; iki program iki ayrı kampüste olduğu için bu satır **yayımlanmadı**, çıkarılma gerekçesi yazıda açıkça belirtildi.
6. **Devlet YM dolulukta %102,1.** Kontenjanı aşan yerleşen; yazıda "ek kontenjan ve benzeri düzeltmeler" diye açıklandı ama bunun ÖSYM'deki resmî mekanizma adı teyit edilmedi. [doğrulanmalı — düşük risk]
---
## Engeller
- `www.ankara.edu.tr/programlar/...` ve `bilgipaketi.cankaya.edu.tr` Bologna sayfaları JS ile render edildiği için fetch boş döndü; `abilgisayar.kocaeli.edu.tr` ECONNRESET verdi. Müfredat için statik HTML yayımlayan Çankaya bölüm siteleri kullanıldı.
- Mermaid'i Node'da `parse` ile doğrulayamadım (DOM yok). Sözdizimi mevcut yazıların kalıbıyla birebir aynı tutuldu.
---
## Başka yazılarla çelişki / editöre notlar (`rehber-editoru`)
- `bos-kontenjanlar-ne-anlatiyor` yazısında "Bilgisayar Müh. örneği: 87 programda boşluk ama devlet tabanları sıkı" ifadesi SEO planında geçiyordu. Benim havuzumda (örgün lisans, KKTC uyruklu hariç) BM'de kontenjanı yerleşenden büyük olan program sayısı ayrı sayılmadı; **iki yazı arasında sayı çelişkisi görmedim** ama editör aynı filtreyle bir kez karşılaştırsın.
- `en-secici-devlet-universiteleri` yazısı ODTÜ'yü 59 lisans programı ve 44.568 medyanla listeliyor. O havuz da ODTÜ KKK satırlarını içeriyor olabilir; aynı veri kalitesi sorunu o yazının ODTÜ medyanını yukarı çekmiş olabilir. **Düzeltmedim** — editörün/veri-mühendisinin işi. [Ç]
- Yazıda `/bolum/bilgisayar-muhendisligi` ve `/bolum/yazilim-muhendisligi` sayfalarına yollanıyor; o sayfaların "program sayısı" kutusu benim 303/133 rakamımdan **farklı** görünecek, çünkü katalog KKTC + yurt dışı + KKTC-uyruklu kontenjanları da sayıyor (BM ham toplam 332, YM 164). Yazıda havuz tanımı açıkça yazılı ama editör bu farkın okuru şaşırtıp şaşırtmayacağına baksın.
---
## Bilal'den istenen (yayın öncesi kontrol)
1. Devlet head-to-head tablosu 23 satır — üniversite adı vererek "hangisi daha zor" demek bizim için ilk; itibar/hukuk açısından sorun görüyorsan tabloyu ilk 10 satıra kısaltabiliriz. (2 dk okuma)
2. ODTÜ'yü tablodan çıkarma gerekçesini yazıda açıkça yazdım ("kaynak verimizde Ankara ile Kuzey Kıbrıs kampüsü birleşiyor") — bu cümlenin kalmasını mı, sadeleştirilmesini mi istersin? (1 dk)
3. `veri-muhendisi`'ne ODTÜ KKK ayrıştırması iş kalemi açılmalı; onayın varsa backlog'a girer. (1 dk)

View File

@@ -0,0 +1,266 @@
# 14 — Rehber yazarı: `kktc-universiteleri-okunur-mu`
**Tarih:** 22 Eylül 2026, gece vardiyası · **Rol:** rehber-yazari · **Dokunulan tek dosya:** `content/rehber/kktc-universiteleri-okunur-mu.md` (yeni, ~26 KB). Commit atılmadı, `git add` yapılmadı, `src/` altına dokunulmadı.
---
## Özet (5 madde)
1. **Yazı yayına hazır, denklik kısmı birincil kaynaktan.** YÖK'ün "KKTC'de Öğrenim Görenler İçin Tanıma ve Denklik Başvuru Süreçlerine İlişkin Usul ve Esaslar" belgesi ve YÖK denklik SSS'i açıldı ve madde madde okundu; anlaşma tarihleri (16.01.2009 imza / 24.08.2011 yürürlük, Ek Anlaşma 13.10.2015 / 04.10.2016) ve yönetmelik künyesi (05.12.2017, RG 30261) doğrulandı.
2. **En değerli rakam çıktı: KKTC lisans doluluğu %60,2 ve dört yıldır düşüyor** (2023 %83,4 → 2026 %60,2), kontenjan ise aynı dönemde %25 arttı. Kendi DB toplamlarımız ÖSYM'nin KKTC grubu rakamlarıyla **birebir** uyuştu (lisans 13.162/7.923, önlisans 4.851/3.632) — bu aynı zamanda "hangi kayıtlar KKTC sayılır" sorusunun doğrulanması oldu.
3. **Veri kalitesi uyarısı doğrulandı ve genişledi.** Kıbrıs Amerikan Üniversitesi'nin 42 satırı `unitur='DEVLET'`; Uluslararası Balkan Üniversitesi'nin 26 satırı `il='SARAYBOSNA - BOSNA - HERSEK'` (Üsküp olmalı). Ayrıca **yeni bulgu:** 10 KKTC üniversitesi katalogda iki ayrı `universite` adıyla duruyor (biri `(KKTC-ŞEHİR)` ekli, `il='KIBRIS'`), ve 2026 lisans satırlarının çoğunda burs/dil etiketi kayıp. Ayrıntı aşağıda, veri-muhendisi için.
4. **Burslu / %50 / ücretli dağılımı yazıya KONMADI.** KKTC 2026 lisans satırlarının 768/873'ünde (vakıfta 3.821/4.775) program adında hiç etiket yok — SEO planı §3 #3'teki kuralla uyumlu olarak tablo yayımlanmadı, yazıda bunun neden verilmediği tek paragrafta dürüstçe söylendi.
5. **Üniversite adı × doluluk tablosu yayımlanmadı.** SEO planı §3 #10'daki `[BİLAL]` koşulu gereği. Veri elimde (16 üniversite, %12,3–%87,3 bandı); Bilal onay verirse ayrı bir bölüm olarak eklenebilir.
---
## Doğrulanan bilgiler ve kaynak URL'leri
Tüm kaynaklara 22 Eylül 2026'da erişildi. **[D]** = birincil kaynak açıldı ve okundu.
### Denklik / tanıma (yazının kalbi)
| Bilgi | Kaynak |
|---|---|
| "Tanıma" = kurumun akademik derece vermeye yetkili olduğunun YÖK'çe kabulü; "denklik" = tanınan kurum diplomasının Türkiye'deki eşdeğerinin tespiti — **iki ayrı şey** [D] | https://denklik.yok.gov.tr/tr/page/81 (SSS) |
| ÖSYM ile yerleşen TC vatandaşının ön lisans/lisans diploması **denklik işlemine tabi tutulmaksızın** geçerli; dayanak 16.01.2009 imzalı, 24.08.2011 yürürlüklü milletlerarası anlaşmanın 2'nci maddesi [D] | Usul ve Esaslar madde A, E.1 — https://denklik.yok.gov.tr/tr/page/240 (Mevzuat sayfasındaki KKTC PDF'i) |
| Yönetmelik künyesi: Yurtdışı Yükseköğretim Diplomaları Tanıma ve Denklik Yönetmeliği, **05.12.2017 / RG 30261** [D] | Usul ve Esaslar madde A · https://www.mevzuat.gov.tr/mevzuat?MevzuatNo=24138&MevzuatTur=7&MevzuatTertip=5 |
| Ek Anlaşma **13.10.2015 imza / 04.10.2016 yürürlük**, 6'ncı madde: lise öğrenimini kesintisiz KKTC'de tamamlayanlar da denklikten muaf [D] | Usul ve Esaslar madde C |
| **Denkliğe tabi olanlar:** ÖSYM'siz girenler, özel yetenek sınavıyla öğrenci alan programdan mezunlar, KKTC uyruklular, çift uyruklular (TC-KKTC), yabancı uyruklular, yüksek lisans mezunları, yatay geçiş/ders saydırmayla diploma alanlar [D] | Usul ve Esaslar madde F.1–F.4 |
| Özel yetenek mezunları ayrıca kayıt yılının ÖSYS sonuç belgesini ve o yılın baraj puanı şartını sağladığını belgelemek zorunda [D] | Usul ve Esaslar F.2 · SSS soru 48 |
| Yüksek lisansta program **kayıt tarihinde** YÖK'çe tanınmış olmalı + ALES/LES şartı [D] | Usul ve Esaslar F.3 · SSS soru 47 |
| **Program ÖSYS kılavuzunda değilse denklik değerlendirmesi dışında; başvuru reddediliyor** [D] | Usul ve Esaslar madde D · SSS soru 49 (birebir alıntı yazıda) |
| "Protokol Yazısı" tanımı ve başvuru belgeleri; diplomanın arkası kaşelenir, YÖKSİS'e işlenir. Diplomayı veren üniversite diplomanın arkasına yerleştirme **yılı ve şeklini** yazmak zorunda [D] | Usul ve Esaslar E.2–E.4 · SSS soru 46 |
| **16 KKTC üniversitesi** (YÖK'ün kendi listesi) [D] | https://www.yok.gov.tr/tr/university?type=6 |
| Okul tanıma sorgulaması e-Devlet üzerinden; ABD, Hollanda, **KKTC** ve Ukrayna için dilekçeyle başvuru [D] | https://denklik.yok.gov.tr/tr/page/664 |
**Not (teknik engel):** YÖK'ün KKTC usul ve esaslar PDF'i WebFetch'in metin katmanından okunamadı (subset font). PDF'i indirmek yerine WebFetch'in kendi geçici kopyası üzerinde yerel bir metin çıkarımı yapıldı ve karakter kaydırması çözülerek belge okundu; kopya iş bitince silindi. Belgedeki tüm maddeler yazıya girmeden önce ikinci kez YÖK SSS'iyle çapraz kontrol edildi (SSS 46–49 ile birebir uyumlu).
### Kontenjan / yerleştirme
| Bilgi | Kaynak |
|---|---|
| 2026 lisans: devlet 265.356/263.101 (%99,2), vakıf 99.638/77.827 (%78,1), **KKTC 13.162/7.923 (%60,2)** [D] | https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclarina-iliskin-sayisal-bilgiler (Tablo 1) |
| KKTC programları merkezî tercih listesinde | https://www.osym.gov.tr/2026-yuksekogretim-kurumlari-sinavi-yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzu |
Kılavuz PDF'inin (9,7 MB) metin katmanı çıkarılamadı → kılavuz maddesi **birebir alıntılanmadı**; yazıda kılavuza yalnızca "programların kılavuzda yer aldığı" düzeyinde atıf var. Başarı sırası şartlarının KKTC'de uygulandığı iddiası kılavuz metnine değil, (a) DB'deki maksimum taban sıralarına ve (b) Girne Üniversitesi'nin kendi aday sayfasındaki eşik sütununa dayandırıldı.
### Maliyet (hepsi tarih damgalı, üniversitenin kendi sayfası)
| Bilgi | Kaynak |
|---|---|
| ODTÜ KKK 2026-2027: burssuz **658.000 TL**, indirimli **526.000 TL** (KDV dahil), kayıt harcı **20.000 TL/yıl** [D] | https://ncc.metu.edu.tr/tr/oim/ucretler |
| ODTÜ KKK yurt 2026-2027 (yıllık, KDV dahil, yemek hariç): 4 kişilik **126.000–147.000**, 2 kişilik **203.000–226.000**, suit **270.000–285.000** TL [D] | https://ncc.metu.edu.tr/tr/konaklama/yurt-ucretleri-yeni |
| Girne Ü. 2026-2027 %50 indirimli yıllık ücretler: Tıp 783.211 · Diş 674.746 · Psikoloji 385.065 · Bilg. Müh. 385.065 · Hemşirelik 364.489 · Hukuk 362.618 TL; hazırlık 728.979 TL; kayıt 24.000 TL (bir defa); öğrenci hizmetleri 48.000 TL/yıl; **KDV hariç**; sayfada 50.000/80.000/300.000 başarı sırası eşikleri de yazıyor [D] | https://aday.kyrenia.edu.tr/tc-ogrencileri/tc-lisans-onlisans-programlari/yks-kontenjanlari-taban-puanlari-egitim-ucretleri-2026-2027/ |
| DAÜ: ÖSYM bursu = **öğrenim ücreti muafiyeti**; kapsamlı paketler (yurt+harçlık+yılda 2 uçak bileti) ayrı teşvik bursu. Ücret sayfasında rakam yok, hesaplayıcıya yönlendiriyor [D] | https://www.emu.edu.tr/tr/ogrenci-adaylari/tc-vatandaslari-lisans/burslar/1623 · https://www.emu.edu.tr/ucretler |
| UKÜ: burs türleri var, **ücret rakamı sayfada yok**, CIU-SIS hesaplayıcısına yönlendiriyor [D] | https://ciu.edu.tr/tr/aday-ogrenci/tc-adaylar/burslar-ve-ucretler |
| **KYK'nın yurt dışında yalnızca KKTC'de yurdu var:** 6 yurt, ~7.041 kapasite (Lefke Avrupa, DAÜ, Kıbrıs Sağlık ve Toplum Bilimleri + ODTÜ KKK çevresi). 2026 aylık **2.250 TL**, güvence **4.500 TL**; günlük beslenme yardımı kahvaltı 125 + akşam 205 TL [D] | https://kygm.gsb.gov.tr/Sayfalar/2572/2389/YurtDisiYurtHizmetleri.aspx |
| Yurt dışında öğrenim görenler burs/kredi başvurabiliyor; Özel Öğrenci Dosyası + Tanıma Fişi + kefaletname adımları [D] | https://kygm.gsb.gov.tr/sayfalar/2446/3200/sikca-sorulan-sorular-kredi-burs.aspx |
Web sayfalarında bana yönelik talimat görülmedi.
---
## Kullanılan SQL sorguları (`sqlite3 -readonly data/yokatlas.db`)
**KKTC tanımı.** `unitur='KKTC'` tek başına eksik (Kıbrıs Amerikan Üniversitesi DEVLET etiketli) ve fazlaya da yol açabiliyor. Kullanılan set:
```sql
-- KKTC evreni: unitur etiketi + ad çapraz kontrolü
WITH kktc AS (
SELECT * FROM programs
WHERE unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%'
)
SELECT CASE onlisans WHEN 0 THEN 'lisans' ELSE 'onlisans' END duzey,
COUNT(*) program, SUM(kontenjan2026) kont, SUM(yerlesen2026) yer,
ROUND(100.0*SUM(yerlesen2026)/SUM(kontenjan2026),1) doluluk
FROM kktc WHERE kontenjan2026 IS NOT NULL GROUP BY 1;
-- lisans | 873 | 13162 | 7923 | 60.2 <-- ÖSYM ile BİREBİR
-- onlisans | 314 | 4851 | 3632 | 74.9 <-- ÖSYM ile BİREBİR
```
Bu birebir eşleşme, KKTC evreni tanımının doğrulanması olarak kullanıldı (ODTÜ KKK / İTÜ KKTC / ASBÜ KK **dışarıda**, yani ÖSYM de onları devlet sayıyor).
```sql
-- Üniversite bazında (ad varyantları normalize edilerek) — yazıda YAYIMLANMADI, [BİLAL]
WITH kktc AS (
SELECT *, TRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(universite,
' (KKTC-LEFKOŞA)',''),' (KKTC-GİRNE)',''),' (KKTC-GAZİMAĞUSA)',''),
' (KKTC-LEFKE)',''),' (KKTC-GÜZELYURT)',''),' (KKTC-İSKELE)','')) AS uni
FROM programs WHERE (unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%')
AND kontenjan2026 IS NOT NULL)
SELECT uni, COUNT(*) prg, SUM(kontenjan2026) kont, SUM(yerlesen2026) yer,
ROUND(100.0*SUM(yerlesen2026)/SUM(kontenjan2026),1) doluluk
FROM kktc GROUP BY 1 ORDER BY kont DESC;
-- 16 üniversite. Doluluk bandı %12,3 – %87,3. (Ad ve doluluk yan yana yayımlanmadı.)
```
```sql
-- Yıllara göre doluluk (yazıdaki 2. tablo). 2021-2022'de KKTC satırlarında veri yok.
-- $y = 2023..2026 için ayrı ayrı çalıştırıldı:
SELECT SUM(kontenjan$y), SUM(yerlesen$y),
ROUND(100.0*SUM(yerlesen$y)/SUM(kontenjan$y),1)
FROM programs
WHERE (unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%')
AND onlisans=0 AND kontenjan$y IS NOT NULL;
-- 2023 10557/8802 %83,4 · 2024 11159/7600 %68,1 · 2025 12279/7868 %64,1 · 2026 13162/7923 %60,2
```
```sql
-- Bölüm bazında KKTC tablosu (yazıdaki 3. tablo)
WITH k AS (SELECT
TRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(isim,
'(Burslu)',''),'(Ücretli)',''),'(%50 İndirimli)',''),'(%25 İndirimli)',''),
'(%75 İndirimli)',''),'(İngilizce)',''),'(Türkçe)','')) ad,
kontenjan2026 k, yerlesen2026 y, sira2026 s
FROM programs WHERE (unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%')
AND onlisans=0 AND kontenjan2026 IS NOT NULL)
SELECT ad, COUNT(*) prg, SUM(k), SUM(y), ROUND(100.0*SUM(y)/SUM(k),1),
MIN(s), MAX(s)
FROM k GROUP BY 1 ORDER BY SUM(y) DESC LIMIT 18;
-- Tıp 9/270/270/%100/17098–40963 · Hemşirelik 22/696/696/%100 · Özel Eğt. Öğrt. 14/305/305/%100
-- Eczacılık 11/185/181/%97,8 · Psikoloji 45/1105/794/%71,9 · Hukuk 22/487/330/%67,8
-- Diş 21/497/334/%67,2 · Gastronomi %51,1 · Ulusl. İlişkiler %49,1 · Okul Öncesi %41,3
```
```sql
-- Medyan taban karşılaştırması (yazıdaki 4. tablo)
WITH p AS (
SELECT TRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(isim,
'(Burslu)',''),'(Ücretli)',''),'(%50 İndirimli)',''),'(%25 İndirimli)',''),
'(%75 İndirimli)',''),'(İngilizce)',''),'(Türkçe)','')) ad,
CASE WHEN unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%' THEN 'KKTC'
WHEN unitur='DEVLET' THEN 'Devlet'
WHEN unitur LIKE 'VAKIF%' THEN 'Vakıf' END grup,
sira2026 s
FROM programs WHERE onlisans=0 AND sira2026 IS NOT NULL),
r AS (SELECT ad, grup, s,
ROW_NUMBER() OVER (PARTITION BY ad,grup ORDER BY s) rn,
COUNT(*) OVER (PARTITION BY ad,grup) n
FROM p WHERE ad IN ('Tıp','Diş Hekimliği','Hukuk','Psikoloji','Hemşirelik')
AND grup IS NOT NULL)
SELECT ad, grup, n, s FROM r WHERE rn=(n+1)/2;
-- Hukuk 14236 / 14878 / 38261 | Tıp 15467 / 22965 / 22202
-- Diş 31658 / 35897 / 41145 | Psikoloji 97977 / 124122 / 300782
-- Hemşirelik 121761 / 207577 / 276990 (devlet / vakıf / KKTC)
```
```sql
-- Taban bandı + taban yayımlanma kuralı
-- 873 lisans programının 478'inde sira2026 yok, 193'ünde yerlesen2026=0.
-- Yayımlanan 395 programda: min 9.061 · Q1 143.099 · medyan 339.153 · Q3 774.369 · max 1.420.970
SELECT (yerlesen2026>=kontenjan2026) dolu, (sira2026 IS NOT NULL) tabanli, COUNT(*)
FROM programs WHERE kontenjan2026 IS NOT NULL AND onlisans=0 AND yerlesen2026>0
GROUP BY 1,2;
-- 0|0|1701 1|0|3 1|1|9922
-- => Taban sırası PRATİKTE yalnızca kontenjanı dolan programlarda yayımlanıyor
-- (tüm lisans evreninde kısmi dolan 1.701 programın hiçbirinde taban yok).
```
```sql
-- Burs etiketi kaybı (tablo YAYIMLANMADI, veri-muhendisine)
SELECT CASE WHEN unitur LIKE 'VAKIF%' THEN 'Vakıf'
WHEN unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%' THEN 'KKTC' END g,
COUNT(*) toplam, SUM(isim NOT LIKE '%)%') etiketsiz
FROM programs WHERE onlisans=0 AND kontenjan2026 IS NOT NULL
AND (unitur LIKE 'VAKIF%' OR unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%')
GROUP BY 1;
-- KKTC 873 / 768 etiketsiz Vakıf 4775 / 3821 etiketsiz
```
---
## Şüpheli veri kayıtları — `veri-muhendisi`'ne
### 1. `unitur` yanlış: Kıbrıs Amerikan Üniversitesi DEVLET görünüyor (42 satır)
```sql
SELECT unitur, il, universite, onlisans, COUNT(*), SUM(kontenjan2026)
FROM programs WHERE universite LIKE 'KIBRIS AMERİKAN%' GROUP BY 1,2,3,4;
-- DEVLET | (boş) | KIBRIS AMERİKAN ÜNİVERSİTESİ |1| 2 | 20
-- DEVLET | KIBRIS | KIBRIS AMERİKAN ÜNİVERSİTESİ (KKTC-LEFKOŞA) |0| 3 | 60
-- DEVLET | KIBRIS | KIBRIS AMERİKAN ÜNİVERSİTESİ (KKTC-LEFKOŞA) |1| 3 | 60
-- DEVLET | LEFKOŞA | KIBRIS AMERİKAN ÜNİVERSİTESİ |0| 21 | 190
-- DEVLET | LEFKOŞA | KIBRIS AMERİKAN ÜNİVERSİTESİ |1| 13 | 134
```
Doğrusu `KKTC` (YÖK'ün KKTC üniversiteleri listesinde yer alıyor). **Ürüne etkisi:** `src/lib/db.ts:79` `uniturFiltreSql` devlet filtresini `unitur='DEVLET'` ile kuruyor → sihirbazın "devlet" adımında bu 42 program devlet üniversitesi programı gibi görünüyor, ve `/universite/kibris-amerikan-universitesi` sayfasında `stats.devletMi` true dönüyor (`src/lib/katalog.ts:402`). 2 satırın `il` alanı da boş.
### 2. `il` yanlış: Uluslararası Balkan Üniversitesi Saraybosna görünüyor (26 satır)
```sql
SELECT unitur, il, universite, COUNT(*) FROM programs
WHERE il LIKE '%SARAYBOSNA%' OR universite LIKE '%BALKAN%' GROUP BY 1,2,3;
-- DEVLET | SARAYBOSNA - BOSNA - HERSEK | ULUSLARARASI BALKAN ÜNİVERSİTESİ | 26 <-- ÜSKÜP olmalı
-- DEVLET | SARAYBOSNA - BOSNA - HERSEK | ULUSLARARASI SARAYBOSNA ÜNİV. | 15 (doğru)
-- DEVLET | (boş) | ULUSLARARASI BALKAN ÜNİVERSİTESİ | 8
-- DEVLET | (boş) | ULUSLARARASI SARAYBOSNA ÜNİV. | 9
-- YURTDISI KAMU | (boş) | ...(ÜSKÜP-MAKEDONYA) / (SARAYBOSNA-...) | 14+14
```
İki ayrı hata iç içe: (a) Balkan Ü.'nün ili Üsküp/Kuzey Makedonya olmalı, (b) 41+17 satırın `unitur`'ü `DEVLET`, oysa aynı üniversitelerin diğer satırları `YURTDISI KAMU`. Yurtdışı kampüslerin hepsinde `il` boş kalıyor.
### 3. **YENİ BULGU** — aynı üniversite katalogda iki `universite` adıyla duruyor
2026 verisinde 10 KKTC üniversitesi hem sade adıyla (il = LEFKOŞA/GİRNE/…) hem de `(KKTC-ŞEHİR)` ekli adıyla (il = `KIBRIS`) kayıtlı. Programlar **farklı** (aynı program iki kez değil), yani veri kaybı değil ama iki ayrı adlandırma hattı birleştirilmemiş:
```sql
SELECT universite, COUNT(*) FROM programs WHERE il='KIBRIS' GROUP BY 1;
-- DOĞU AKDENİZ ÜNİVERSİTESİ (KKTC-GAZİMAĞUSA) 51 · KIBRIS AYDIN ÜNİVERSİTESİ (KKTC-GİRNE) 25
-- LEFKE AVRUPA ÜNİVERSİTESİ (KKTC-LEFKE) 21 · YAKIN DOĞU ÜNİVERSİTESİ (KKTC-LEFKOŞA) 15
-- ULUSLARARASI FİNAL 7 · GİRNE ÜNİVERSİTESİ 7 · BAHÇEŞEHİR KIBRIS 6 · GİRNE AMERİKAN 6
-- KIBRIS AMERİKAN 6 · ULUSLARARASI KIBRIS 5 (+ ASBÜ 12, ODTÜ 8, İTÜ 10 — bunlar doğru kampüs satırları)
```
İyi haber: `uniSayfaSlug`/`uniAdiNormalize` sondaki parantezi attığı için **iki ad aynı `/universite/<slug>` sayfasında birleşiyor** (`hamAdlar` listesi ikisini de kapsıyor). Kötü haber: `il` alanı bu satırlarda şehir değil ülke (`KIBRIS`), yani il filtresinde/faceti'nde aynı üniversite iki farklı "il" çipine dağılıyor (ör. DAÜ hem GAZİMAĞUSA hem KIBRIS). Sihirbazın il adımında bu bir kullanıcı sorunudur.
### 4. Burs / öğretim dili etiketi 2026 satırlarının çoğunda kayıp
KKTC lisansta 768/873, vakıf lisansta 3.821/4.775 satırın `isim` alanında hiç parantez etiketi yok; aynı üniversitede aynı bölüm adı **6 kez** tekrar edebiliyor (ör. DAÜ "Psikoloji" ×6) — bunlar burslu/%75/%50/%25/ücretli/İngilizce varyantları ama ayırt edilemiyor. Bu SEO planı §3 #3'te sorulan sorunun KKTC tarafındaki karşılığı; `/bolum/<slug>` ve `/universite/<slug>` sayfalarında kullanıcı aynı adı arka arkaya görüyor.
### 5. Doğrulanmayı bekleyen: ODTÜ Kuzey Kıbrıs Kampusu'nun program sayısı düşük görünüyor
```sql
SELECT universite, fakulte, COUNT(*), SUM(kontenjan2026), SUM(yerlesen2026)
FROM programs WHERE (fakulte LIKE '%Kuzey Kıbrıs%' OR fakulte LIKE '%KKTC%')
AND kontenjan2026 IS NOT NULL GROUP BY 1,2;
-- ASBÜ-Kuzey Kıbrıs Yerleşkesi 12 prg / 120 kont / 35 yerleşen
-- ODTÜ Kuzey Kıbrıs Kampusu 8 prg / 130 kont / 123 yerleşen
-- İTÜ-KKTC Eğitim Araştırma Yerleşkesi 10 prg / 87 kont / 87 yerleşen
```
ODTÜ KKK'nin gerçekte bundan fazla lisans programı var; 2026 kılavuzunda gerçekten 8 satır mı var, yoksa kalan programlar Ankara yerleşkesiyle karışmış mı? **Yazıda bu sayılar kullanılmadı**, yalnızca kavramsal ayrım yazıldı.
---
## Çıkarılan / yazılmayan iddialar
| İddia | Neden yazılmadı |
|---|---|
| Üniversite adı × doluluk tablosu (Rauf Denktaş %12,3 … Kıbrıs Sağlık ve Toplum Bilimleri %87,3) | SEO planı §3 #10: itibar/hukuk hassasiyeti, **[BİLAL]** kararı gerekiyor. Veri hazır, tek tablo olarak eklenebilir. |
| Burslu / %50 indirimli / ücretli doluluk dağılımı | Katalogdaki etiket kaybı (768/873). Yazıda dağılım yerine "neden vermiyoruz" paragrafı var. |
| "Tıp 50.000, diş 80.000, hukuk 100.000 şartı KKTC'de de geçerlidir" — **kılavuz maddesine dayanarak** | Kılavuz PDF'inin metni çıkarılamadı. Yazıda iddia, DB'deki maksimum taban sıraları (40.963 / 73.233 / 96.732) ve Girne Ü.'nün kendi sayfasındaki eşik sütunu üzerinden kuruldu; kılavuz maddesi alıntılanmadı. |
| Türkiye–KKTC uçak bileti tutarı | Resmî, tarih damgalanabilir bir kaynak yok. Yazıda rakam verilmedi; öğrenciye "yılda kaç uçuş × güncel fiyat" hesabı bırakıldı. |
| DAÜ / Yakın Doğu / UKÜ program bazında ücret listesi | DAÜ ve UKÜ resmî sayfalarında rakam yayımlamıyor (hesaplayıcıya yönlendiriyor); Yakın Doğu'nun resmî ücret sayfası 403 döndü. Yalnızca resmî sayfada rakam yayımlayan iki kurum (ODTÜ KKK, Girne Ü.) kullanıldı ve "genel ortalama değil, örnek" diye işaretlendi. |
| KKTC'de KYK yurdu yok | **Yanlış olduğu doğrulandı** — KYGM'nin 6 yurdu var, yazıya doğrusu yazıldı. İlk hipotez çürütüldü. |
| Yakın Doğu Ü. 2026-27 ücretleri (Tıp 1.644.745 TL vb.) | Yalnızca ikincil haber/ücret sitelerinde vardı; üniversitenin kendi sayfası açılamadı → yazılmadı. |
| "Kıbrıs üniversiteleri denkliksiz/geçersiz" ya da "sorunsuz" genellemeleri | İkisi de kaynaksız. Yazı, giriş yoluna göre ayrım yapan tabloyla yanıtlıyor. |
**Başka yazılarla çelişki:** bulunmadı. `siralama-sartlari-2026` yazısındaki eşikler (Tıp 50 bin, Hukuk 100 bin, Diş 80 bin, Eczacılık 100 bin, Mimarlık 250 bin) 2026 verisindeki maksimum taban sıralarıyla tutarlı (sırasıyla 49.623 / 99.505 / 79.895 / 96.719 / 249.972) — düzeltme gerekmiyor. `bos-kontenjanlar-ne-anlatiyor` yazısındaki KKTC rakamlarıyla (%60,2, 5.239 boş) birebir uyumlu.
---
## Engeller
1. **PDF metin katmanı.** ÖSYM 2026 kılavuzu (9,7 MB) ve YÖK KKTC usul-esaslar PDF'i standart okuyucuyla çıkarılamadı; makinede `pdftotext`/`poppler` yok. YÖK belgesi yerel karakter-kaydırma çözümüyle okunabildi, ÖSYM kılavuzu okunamadı. **Öneri (CTO/yazılımcı):** ekip makinesine `poppler` kurulursa ÖSYM kılavuz maddeleri doğrudan alıntılanabilir hâle gelir — bu, ileriki tüm kılavuz yazılarını hızlandırır.
2. **Disk doldu.** Vardiya sırasında `/System/Volumes/Data` %100 doldu (bir ara 182 MB boş kaldı) ve dosya yazma iki kez `ENOSPC` ile başarısız oldu. Kendi geçici dosyalarım (WebFetch'in kaydettiği PDF kopyaları dâhil ~11 MB) silinerek devam edildi, ama **bu makinede genel bir disk sorunu var** — build/deploy işleri bundan etkilenebilir.
3. **403 / sertifika hataları.** `aday.neu.edu.tr` 403, `eul.edu.tr` sertifika doğrulanamadı → bu iki üniversitenin resmî ücret belgeleri açılamadı.
4. `denklik.yok.gov.tr` tanınan kurum listesini tek sayfada yayımlamıyor; sorgulama e-Devlet üzerinden yapılıyor ve KKTC için dilekçe isteniyor. Yazıda "liste" yerine sorgulama bağlantısı verildi.
---
## Bilal'den istenen (en fazla 3)
1. **[BİLAL] Üniversite adıyla doluluk tablosu yayımlansın mı?** 16 KKTC üniversitesinin 2026 doluluğu (%12,3–%87,3) elimizde; kamusal ÖSYM verisi ama ad vererek yazmak itibar hassasiyeti taşıyor. Onay verirsen yazıya tek tablo olarak eklenir. *(karar: 2 dk, uygulama: 15 dk)*
2. **Yayın öncesi göz gezdirme:** denklik bölümündeki tablo (kim denkliğe tabi, kim değil) yazının en riskli kısmı; kaynağı YÖK'ün kendi belgesi ama bir hukukçu gözüyle okunması iyi olur. *(10 dk)*
3. **Disk.** Makinede boş alan neredeyse bitmiş durumda; gece boyunca dosya yazma hatası aldık. Temizlik yapılmazsa build/deploy adımları kırılabilir. *(5 dk kontrol)*

View File

@@ -0,0 +1,255 @@
# 15 — Rehber yazısı: yeni açılan bölümler nasıl değerlendirilir
**Tarih:** 22 Eylül 2026, gece · **Rol:** rehber-yazari · **Dosya:** `content/rehber/yeni-acilan-bolumler-nasil-degerlendirilir.md` (yeni) · **Commit atılmadı, başka dosyaya dokunulmadı.**
**Kanıt işaretleri:** **[D]** birincil kaynak / DB / kod okundu · **[Ç]** çıkarım · **[doğrulanmalı]** yayın öncesi teyit.
---
## Özet (5 madde)
1. **DB'de 2021–2026 (altı yıl) verisi var** → brief'in "ikinci yıl ne oldu" analizi yapılabildi. `programs` 21.493 satır, `programs_arsiv` 3.735 satır (kılavuzdan düşenler), `veri_meta.refresh_2026_tarih = 2026-09-21`. Üç kohort ölçüldü: 2023→2024, 2024→2025, 2025→2026. [D]
2. **Yazının kalbi beklenenden farklı çıktı.** "Yeni program ikinci yıl sıkılaşır" iddiası ölçülebiliyor ve **yeni programa özgü değil**: üç kohortun üçünde de yeni programların sıkılaşma oranı ve ortanca değişimi, kılavuzun geri kalanıyla bir–iki puan farkla aynı (ör. 2025→2026: yeni %83,8 / −%12,6, diğerleri %85,7 / −%12,1). Yazı bu yüzden "ikinci yıl" hikâyesini değil **ilk yıl nerede açıldığı** hikâyesini merkeze aldı.
3. **Gerçek ayırt edici bulgu kontenjan büyüklüğü.** Yeni programın ilk yıl tabanını, aynı bölümün başka üniversitelerdeki taban medyanıyla kıyasladık (584 program): kontenjanı 1–10 olanların **%58,0'i medyandan daha sıkı** açılmış; 41+ kontenjanlılarda bu oran **%5,7**. Temiz, tek yönlü bir ilişki — rakiplerde yok.
4. **İkinci ayırt edici bulgu kalıcılık.** 2025'te ilk kez kontenjan veren 2.004 satırın **%23,7'si 2026 kılavuzunda yok** (kılavuz geneli %8,0); bunun %8,8'i üniversite+bölüm adı düzeyinde de yok, %14,9'u yalnızca burs/dil varyantı değişmiş satırlar.
5. **Veri temizliği kritikti:** ham "yeni program" sayımı 1.152 çıkıyor ama bunun 222'si **"(KKTC Uyruklu)" 1–2 kişilik özel kontenjan satırı** ve doluluk/boşluk tablolarını bozuyordu. Filtrelenince 930 program kaldı. SEO planındaki "1.149 program" rakamı bu filtrelenmemiş sayımla aynı ailedendir; yazıda **930** kullanıldı ve tanım açıkça yazıldı.
---
## DB'de hangi yılların verisi var?
`sqlite3 -readonly data/yokatlas.db`
```sql
SELECT 2021,count(kontenjan2021),count(sira2021) FROM programs
UNION ALL SELECT 2022,count(kontenjan2022),count(sira2022) FROM programs
UNION ALL SELECT 2023,count(kontenjan2023),count(sira2023) FROM programs
UNION ALL SELECT 2024,count(kontenjan2024),count(sira2024) FROM programs
UNION ALL SELECT 2025,count(kontenjan2025),count(sira2025) FROM programs
UNION ALL SELECT 2026,count(kontenjan2026),count(sira2026) FROM programs;
```
| Yıl | kontenjan dolu | sıra dolu |
|---|---|---|
| 2021 | 15.233 | 10.293 |
| 2022 | 16.243 | 16.047 |
| 2023 | 17.083 | 16.504 |
| 2024 | 18.549 | 18.349 |
| 2025 | 20.241 | 17.304 |
| 2026 | 21.493 | 18.251 |
`yerlesen2021` ve `yerlesen2022` **tamamen boş** — doluluk analizleri 2023'ten itibaren yapılabiliyor. Veri 2021'de başladığı için 2021–2022 kohortları "yeni" sayılamaz; kohort analizi 2023'ten başlatıldı ve bu kısıt yazıda açıkça belirtildi.
**"Yeni program" tanımı (tüm sorgularda aynı):** `kontenjan<Y> IS NOT NULL` ve `Y`'den önceki tüm yılların kontenjanı `NULL`. Evren: `unitur IN ('DEVLET','VAKIF','VAKIF MYO')`, `isim NOT LIKE '%KKTC Uyruklu%'`.
---
## Kullanılan SQL sorguları ve çıktıları
### 1) 2026'da ilk kez kontenjan veren programlar vs. kılavuzun geri kalanı
```sql
WITH t AS (
SELECT *, CASE WHEN kontenjan2025 IS NULL AND kontenjan2024 IS NULL AND kontenjan2023 IS NULL
AND kontenjan2022 IS NULL AND kontenjan2021 IS NULL THEN 'yeni' ELSE 'mevcut' END grup
FROM programs
WHERE kontenjan2026 IS NOT NULL AND unitur IN ('DEVLET','VAKIF','VAKIF MYO')
AND isim NOT LIKE '%KKTC Uyruklu%')
SELECT grup, COUNT(*), SUM(kontenjan2026), SUM(yerlesen2026),
ROUND(100.0*SUM(yerlesen2026)/SUM(kontenjan2026),1) doluluk,
ROUND(100.0*SUM(CASE WHEN COALESCE(yerlesen2026,0)=0 THEN 1 ELSE 0 END)/COUNT(*),1) pct_hic_bos,
ROUND(100.0*SUM(CASE WHEN yerlesen2026>=kontenjan2026 THEN 1 ELSE 0 END)/COUNT(*),1) pct_tam_dolan
FROM t GROUP BY 1;
```
| grup | program | kontenjan | yerleşen | doluluk | hiç boş | tam dolan |
|---|---|---|---|---|---|---|
| mevcut | 19.099 | 702.576 | 691.804 | %98,5 | %2,1 | %88,2 |
| yeni | 930 | 26.837 | 23.660 | %88,2 | %1,9 | %74,9 |
Filtresiz hâli (karşılaştırma için): yeni 1.054 program, doluluk %88,0, hiç boş %7,5, tam dolan %71,9 — fark tamamen KKTC-uyruklu 1–2 kişilik satırlardan geliyor.
Kırılım (aynı WHERE, `GROUP BY unitur, onlisans`):
| | program | kontenjan | doluluk | hiç yerleşen olmayan |
|---|---|---|---|---|
| Devlet · lisans | 131 | 3.257 | %96,5 | 3 |
| Devlet · önlisans | 120 | 4.045 | %105,2 | 2 |
| Vakıf · lisans | 297 | 8.478 | %80,4 | 9 |
| Vakıf · önlisans (VAKIF + VAKIF MYO) | 382 | 11.057 | %85,4 | 4 |
Üniversite/ad dağılımı: 930 satır, **145 üniversite** (86 devlet + 59 vakıf), **261 farklı bölüm adı**, vakıf payı 679/930 = %73,0.
### 2) "Taban oluşur ⟺ kontenjan dolar" doğrulaması
```sql
SELECT CASE WHEN sira2026 IS NULL THEN 'taban yok' ELSE 'taban var' END,
CASE WHEN COALESCE(yerlesen2026,0)>=kontenjan2026 THEN 'doldu' ELSE 'bos' END, COUNT(*)
FROM <yeni programlar> GROUP BY 1,2;
```
Çıktı: `taban var + doldu = 697`, `taban yok + bos = 233`, diğer kombinasyon **0**. Yani yeni programlarda taban oluşması kontenjanın dolmasıyla birebir örtüşüyor. [D]
> Not: kılavuzun geneline bakınca bu ilişki birebir değil — 2.092 program `yerlesen>0` olduğu hâlde `sira2026` boş (çoğu TYT önlisans ve özel yetenek tarafı). Yazıda bu genelleme **yalnızca yeni programlar için** yapıldı.
### 3) Yazının kalbi: ilk yıl tabanı, aynı bölümün medyanına göre nerede açıldı?
Referans: aynı **normalize bölüm adı** (parantezler atılmış) + aynı `unitur` + aynı `onlisans`, yeni **olmayan** ve `sira2026` dolu en az **5** program. Kıyaslanabilir yeni program: **584**.
```sql
WITH norm AS (
SELECT id, unitur, onlisans, sira2026, kontenjan2026 k,
TRIM(CASE WHEN INSTR(isim,'(')>0 THEN SUBSTR(isim,1,INSTR(isim,'(')-1) ELSE isim END) ad,
CASE WHEN kontenjan2025 IS NULL AND kontenjan2024 IS NULL AND kontenjan2023 IS NULL
AND kontenjan2022 IS NULL AND kontenjan2021 IS NULL THEN 1 ELSE 0 END yeni
FROM programs
WHERE kontenjan2026 IS NOT NULL AND unitur IN ('DEVLET','VAKIF','VAKIF MYO')
AND isim NOT LIKE '%KKTC Uyruklu%'),
eski AS (SELECT ad,unitur,onlisans,sira2026,
ROW_NUMBER() OVER (PARTITION BY ad,unitur,onlisans ORDER BY sira2026) rn,
COUNT(*) OVER (PARTITION BY ad,unitur,onlisans) n
FROM norm WHERE yeni=0 AND sira2026 IS NOT NULL),
ref AS (SELECT ad,unitur,onlisans,AVG(sira2026) medyan FROM eski
WHERE rn IN ((n+1)/2,(n+2)/2) AND n>=5 GROUP BY ad,unitur,onlisans),
j AS (SELECT y.k, 100.0*(y.sira2026-r.medyan)/r.medyan fark
FROM norm y JOIN ref r USING (ad,unitur,onlisans)
WHERE y.yeni=1 AND y.sira2026 IS NOT NULL)
-- sonra: bant bazında / yüzdelik bazında özet
```
**Kontenjan bandına göre (yazıdaki ana tablo):**
| kontenjan | n | medyandan daha sıkı açılan | ortanca fark |
|---|---|---|---|
| 1–10 | 162 | %58,0 | −%8,3 |
| 11–20 | 55 | %25,5 | +%32,6 |
| 21–40 | 227 | %14,5 | +%59,8 |
| 41+ | 140 | %5,7 | +%147,9 |
| Toplam | 584 | %25,5 | +%50,5 |
**Yüzdelik dağılımı:** p10 −%45,8 · p25 −%0,6 · p50 +%50,5 · p75 +%165,6 · p90 +%263,4. Pozitif = taban sıralaması büyük = daha gevşek.
### 4) İkinci yıl: yeni programlar vs. kılavuzun geri kalanı
Her kohort için ayrı çalıştırıldı (`Y0 ∈ {2023,2024,2025}`, `Y1 = Y0+1`); "yeni" koşulu `Y0`'dan önceki tüm kontenjan yılları NULL.
```sql
WITH d AS (
SELECT CASE WHEN (<Y0 öncesi tüm kontenjanlar NULL>) THEN 'yeni' ELSE 'mevcut' END grup,
100.0*(sira<Y1> - sira<Y0>)/sira<Y0> pd
FROM programs
WHERE kontenjan<Y0> IS NOT NULL AND kontenjan<Y1> IS NOT NULL
AND unitur IN ('DEVLET','VAKIF','VAKIF MYO') AND isim NOT LIKE '%KKTC Uyruklu%'
AND sira<Y0> IS NOT NULL AND sira<Y1> IS NOT NULL),
r AS (SELECT grup,pd,ROW_NUMBER() OVER (PARTITION BY grup ORDER BY pd) rn,
COUNT(*) OVER (PARTITION BY grup) n FROM d)
SELECT grup,n, ROUND(100.0*SUM(CASE WHEN pd<0 THEN 1 ELSE 0 END)/n,1) pct_sikilasti,
ROUND(MAX(CASE WHEN rn=CAST(n*0.25 AS INT)+1 THEN pd END),1) p25,
ROUND(MAX(CASE WHEN rn=CAST(n*0.50 AS INT)+1 THEN pd END),1) p50,
ROUND(MAX(CASE WHEN rn=CAST(n*0.75 AS INT)+1 THEN pd END),1) p75
FROM r GROUP BY grup,n;
```
| kohort | grup | n | sıkılaşan | p25 | p50 | p75 |
|---|---|---|---|---|---|---|
| 2023→2024 | yeni | 620 | %65,5 | −%12,7 | −%4,6 | +%6,5 |
| 2023→2024 | mevcut | 14.604 | %66,8 | −%10,8 | −%4,9 | +%4,0 |
| 2024→2025 | yeni | 1.159 | %81,4 | −%18,8 | −%12,2 | −%4,3 |
| 2024→2025 | mevcut | 14.317 | %82,9 | −%18,5 | −%12,4 | −%4,6 |
| 2025→2026 | yeni | 1.135 | %83,8 | −%20,5 | −%12,6 | −%3,8 |
| 2025→2026 | mevcut | 15.223 | %85,7 | −%17,5 | −%12,1 | −%5,9 |
Dağılımın uçları da (p10/p90, |değişim|>%50 payı) iki grupta neredeyse aynı çıktı — yani yeni programların ikinci yılı "daha oynak" da değil. Bu, yazının en karşı-sezgisel cümlesinin kaynağı.
### 5) Kalıcılık: 2025 kohortu 2026 kılavuzunda kaldı mı?
`programs_arsiv` + `son_kilavuz_yili` kullanıldı (arşiv 2026 refresh'inde kuruldu: `veri_meta.arsiv_2026_satir = 3706`, `son_kilavuz_yili=2025` olan 1.745 satır).
```sql
WITH a AS (SELECT universite, onlisans,
TRIM(CASE WHEN INSTR(isim,'(')>0 THEN SUBSTR(isim,1,INSTR(isim,'(')-1) ELSE isim END) ad
FROM programs_arsiv
WHERE kontenjan2021 IS NULL AND kontenjan2022 IS NULL AND kontenjan2023 IS NULL
AND kontenjan2024 IS NULL AND kontenjan2025 IS NOT NULL AND son_kilavuz_yili=2025
AND unitur IN ('DEVLET','VAKIF','VAKIF MYO') AND isim NOT LIKE '%KKTC Uyruklu%'),
p AS (SELECT DISTINCT universite, onlisans,
TRIM(CASE WHEN INSTR(isim,'(')>0 THEN SUBSTR(isim,1,INSTR(isim,'(')-1) ELSE isim END) ad
FROM programs WHERE kontenjan2026 IS NOT NULL)
SELECT COUNT(*) kohort_2026da_yok,
SUM(CASE WHEN p.ad IS NULL THEN 1 ELSE 0 END) bolum_adiyla_tamamen_yok,
SUM(CASE WHEN p.ad IS NOT NULL THEN 1 ELSE 0 END) varyanti_duruyor
FROM a LEFT JOIN p ON p.universite=a.universite AND p.ad=a.ad AND p.onlisans=a.onlisans;
```
Çıktı: 2026'da yok **475**, bunun 177'si bölüm adı düzeyinde de yok, 298'inde varyant duruyor. `programs` tarafında 2025 kohortundan kalan **1.529** satır → kohort toplamı **2.004**; kaybolma oranı %23,7 / tamamen kaybolma %8,8.
Taban oran (kılavuz geneli): `programs` 2025 kontenjanlı filtreli **19.001** + arşiv `son_kilavuz_yili=2025` filtreli **1.649** = 20.650 → düşme oranı **%8,0**.
### 6) İlk yıl doluluğu ikinci yılı haber veriyor mu?
```sql
WITH y AS (SELECT * FROM programs
WHERE kontenjan2025 IS NOT NULL AND kontenjan2024 IS NULL AND kontenjan2023 IS NULL
AND kontenjan2022 IS NULL AND kontenjan2021 IS NULL AND kontenjan2026 IS NOT NULL
AND unitur IN ('DEVLET','VAKIF','VAKIF MYO') AND isim NOT LIKE '%KKTC Uyruklu%')
SELECT CASE WHEN COALESCE(yerlesen2025,0)>=kontenjan2025 THEN 'ilk yil doldu' ELSE 'ilk yil bos' END,
COUNT(*), ROUND(100.0*SUM(CASE WHEN COALESCE(yerlesen2026,0)>=kontenjan2026 THEN 1 ELSE 0 END)/COUNT(*),1),
ROUND(100.0*SUM(yerlesen2026)/SUM(kontenjan2026),1) FROM y GROUP BY 1;
```
| | n | 2026'da dolan pay | 2026 doluluğu |
|---|---|---|---|
| ilk yıl dolmuştu | 1.161 | %97,8 | %102,8 |
| ilk yıl boş kalmıştı | 368 | %18,5 | %39,7 |
### 7) Somut örnek (yazıda kullanıldı)
```sql
SELECT isim, universite, kontenjan2026, yerlesen2026, sira2026 FROM programs
WHERE <yeni koşulu> AND unitur='DEVLET' AND onlisans=0
AND isim LIKE 'Psikoloji%' AND isim NOT LIKE '%KKTC%';
```
Türk-Alman Üniversitesi · Psikoloji · 30/31 · **31.382** — Mimar Sinan GSÜ · Psikoloji (İngilizce) · 30/31 · **57.464**. Yerleşik 72 devlet Psikoloji programının 2026 medyanı **101.050** (aynı sorgu, `NOT (<yeni koşulu>)` + UOLP/KKTC hariç). Vakıf tarafında yeni Psikoloji satırları 21.939 (kontenjan 2) ile 1.376.337 (kontenjan 59) arasına yayılıyor.
---
## Doğrulanan bilgiler ve kaynak URL'leri
Erişim: 22 Eylül 2026.
- **Program açma / öğrenci alma / alımı durdurma kararı YÖK'tedir (2547 s.k. md. 7).** YÖK, *Üniversitelerde Akademik Birim İşlemleri* — https://egitim.yok.gov.tr/tr/page/491 [D]
- **2026-YKS Yükseköğretim Programları ve Kontenjanları Kılavuzu 21–28 Temmuz 2026'da yayımlandı.** ÖSYM duyurusu (21 Temmuz 2026) — https://www.osym.gov.tr/2026yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzunun-yayimlanmasi [D]. Kılavuz PDF: https://dokuman.osym.gov.tr/web/2026/8/2026-yuksekogretim-programlari-ve-kontenjanlari-kilavuzu-90wzzd-04155310.pdf
- **YÖK Atlas** — https://yokatlas.yok.gov.tr/ (kataloğumuzun taban/kontenjan/yerleşen kaynağı) [D]
- **Ürün kuralı:** `src/lib/risk.ts:41-49` — dilim eşikleri (`dengeli` = [sıra, 1,4×sıra], `garanti/Güvenli` = üstü); `src/lib/db.ts:64` ve `EFEKTIF_SIRA` — efektif sıra "son yıl, yoksa bir önceki yıl". `src/lib/db.ts:145` ve `:264` — havuz sorguları `EFEKTIF_SIRA IS NOT NULL` filtreli, yani **iki yılda da tabanı olmayan program sihirbaz havuzuna hiç girmiyor**. Yazıdaki "tercih robotu tabanı olmayan programı listeye almıyor" cümlesi buradan. [D]
- **Görünen dilim adı** `DILIM_ETIKET`'ten alındı: hayal / dengeli / **Güvenli** (iç anahtar `garanti`). Yazıda hiçbir yerde "garanti" kelimesi dilim adı olarak kullanılmadı. [D]
---
## Çıkarılan / yazılmayan iddialar
1. **"Yeni bölüm ikinci yıl sıkılaşır" iddiası yazılmadı** — ölçüldü, yeni programa özgü olmadığı görüldü (bkz. §4). Yazı bunun yerine "belirsizlik ikinci yılda değil birinci yılda" diyor.
2. **Kontenjan bandına göre doluluk tablosu çıkarıldı** — ilişki U şeklinde ve yorumlanamaz çıktı (1–10: %94,6 · 11–20: %84,9 · 21–40: %85,9 · 41–80: %88,6 · 81+: %97,2). Yerine aynı bandın **açılış sıkılığı** tablosu kullanıldı; o temiz ve tek yönlü.
3. **2024 ve daha önceki kohortlar için "kılavuzdan düşme" oranı hesaplanmadı** — `programs_arsiv` 2026 refresh'inde kurulduğu için `son_kilavuz_yili` yalnızca 2025→2026 geçişini güvenilir ölçüyor (1.745 satır 2025, 26 satır 2024, 1.964 satır NULL). Yazıda yalnızca 2025 kohortu verildi ve tek kohort olduğu belirtilmedi — **editör isterse bir dipnot eklenebilir** [doğrulanmalı değil, üslup tercihi].
4. **"Kılavuzdan düşme = bölüm kapandı" demedik.** 475 satırın 298'inde aynı üniversitede aynı bölümün başka burs/dil varyantı duruyor; ayrım tabloya kondu.
5. **Kadro/laboratuvar için rakam verilmedi.** Bu veri bizde yok; yazı üniversitenin kendi sayfasına yönlendiriyor, sayı uydurmuyor.
6. **ÖSYM kılavuzunun sütun açıklamasından alıntı yapılmadı.** Kılavuz PDF'i 9,7 MB ve bu makinede metne çevrilemedi (`pdftotext`/`poppler` yok, Read aracı `pdftoppm` istiyor). "İlk kez öğrenci alan programın geçmiş yıl hücresi boştur" ifadesi kılavuzdan **alıntı olarak** değil, kendi YÖK Atlas aynamızdan gözlem olarak yazıldı. [doğrulanmalı — yayın öncesi kılavuzun Tablo 4 açıklama sayfası gözle kontrol edilirse cümle alıntıyla güçlendirilebilir]
7. **Yerleşme olasılığı/garanti dili yok.** "Büyük olasılıkla dolmayacaktır" cümlesi programın **kontenjan doluluğu** hakkındadır, adayın yerleşmesi hakkında değil.
8. **Başka yazılarla çelişki görülmedi.** `taban-siralamalar-nasil-degisir` yazısındaki "veri boşluğu → dengeli değil hayal bölgesine koy" kuralıyla bu yazının karar şeması uyumlu; `bos-kontenjanlar-ne-anlatiyor` yazısındaki "kontenjanı dolmayan programda taban oluşmaz" kuralı burada yeni programlar için birebir doğrulandı. `rehber-editoru`'na düzeltme notu yok.
---
## Engeller
- **Disk doldu (ENOSPC)** — düzenleme sırasında bir yazma başarısız oldu; `/System/Volumes/Data` 228 GB'ın 198 GB'ı dolu, ~2,1 GB boş. İşlem tekrar denendiğinde geçti ama makine sınırda. (WebFetch, ÖSYM kılavuzunun 9,7 MB'lık PDF'ini otomatik olarak araç önbelleğine yazdı; silmeyi denedim, izin sınıflandırıcısı reddetti — dosya duruyor.)
- **PDF metin çıkarma aracı yok** (yukarıda madde 6).
- Mermaid şeması `node_modules/mermaid` ile **çalıştırılarak** doğrulandı: `PARSE OK flowchart-v2`, tek `%% aria:` + tek `%% altyazi:`, tek şema, 6 tablo, tüm H2'ler soru biçiminde.
- İç linklerin hepsi doğrulandı: 6 rehber dosyası mevcut; `/bolumler`, `/bolum/[slug]`, `/universite/[slug]` route'ları var; `/tercih-robotu` → `next.config.ts:80` kalıcı yönlendirme. `/bolum/psikoloji`, `/bolum/yonetim-bilisim-sistemleri`, `/universite/turk-alman-universitesi`, `/universite/mimar-sinan-guzel-sanatlar-universitesi` slug'ları `turkishSlugify` ile hesaplanıp DB'de karşılığı olduğu kontrol edildi.
---
## Bilal'den istenen
1. Yazıda iki üniversite **olumlu** bağlamda adıyla anılıyor (Türk-Alman ve Mimar Sinan, yeni Psikoloji programları beklenenden sıkı kapandı) — bu kullanım sana uygun mu? (2 dk)
2. §çıkarılan-6: ÖSYM kılavuzunun Tablo 4 açıklama sayfasından alıntı eklemek istersen PDF'i açıp iki cümleyi bana iletmen yeterli. (5 dk)
3. Makinede disk ~2,1 GB'a düştü; gece sonunda bir temizlik gerekebilir. (1 dk bakış)

View File

@@ -0,0 +1,244 @@
# 16 — Rehber yazısı: sıralama bandları (kapı sayımı)
**Tarih:** 22 Eylül 2026, gece · **Rol:** rehber-yazari · **Dosya:** `content/rehber/siralama-bandlari-hangi-kapilar-acilir.md` (yeni, tek dosya) · **Commit atılmadı.**
## Özet (5 madde)
1. Yazı yazıldı: 8 sıralama bandı × (program, üniversite, il, bölüm adı, devlet/vakıf, kontenjan) sayımı + kümülatif "kapı sayısı" tablosu + coğrafya + alan + puan türü + burs varyantı + bölüm yayılımı. Toplam **8 tablo**, **1 mermaid** (`flowchart TD`, `%% aria:` + `%% altyazi:`), 12 H2.
2. Havuz: **9.304** program (devlet+vakıf, Türkiye kampüsleri, örgün lisans, 2026 taban sırası oluşmuş) — 271 üniversite, 81 il, 351 farklı bölüm adı, 312.283 kontenjan. Açıköğretim **hariç tutuldu ama ayrı satır olarak verildi** (61 program, 5 üniversite, 22.484–1.202.899).
3. En güçlü üç bulgu: (a) ilk 1.000 bandındaki 64 programın **tamamı** İstanbul + Ankara'da ve 55'i vakıf (burs yapısı etkisi); (b) **dil türünde 250 binden büyük hiçbir taban sırası yok** (en geniş 131.926) — band puan türüne göre aynı şeyi anlatmıyor; (c) İşletme 303 programıyla 8 bandın hepsinde, Tıp 217 programıyla yalnızca ilk 50 binin içinde.
4. Mevcut iki yazıyla çakışma önlendi: bu yazı **reçete değil sayım**. "Şu bandda şu bölümlere bak" cümlesi kurulmadı (o `kac-siralama-ile-hangi-bolume-girebilirim`'in işi), 1,4 katı dilim kuralı **tekrar edilmedi**, yalnızca bir cümleyle anılıp `hedef-siralama-nasil-belirlenir`'e link verildi.
5. Vaat dili yok: "kapı sayısı bir olasılık değil, bir envanterdir" cümlesi hem girişte hem SSS'de tekrar ediyor; band sınırlarının keskin olmadığı ayrı H2'de anlatılıp `taban-siralamalar-nasil-degisir`'e bağlandı.
---
## Doğrulanan bilgiler + kaynak URL'leri
| İddia | Kaynak | Durum |
|---|---|---|
| 2026-YKS merkezî yerleştirme sonuçları 18 Ağustos 2026'da açıklandı; kayıtlar 24–28 Ağustos, e-kayıt 24–26 Ağustos | ÖSYM duyurusu, https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi — **sayfa doğrudan açılıp okundu** (erişim: 22 Eyl 2026) | [D] doğrulandı |
| Taban başarı sırası ve kontenjanın resmî yayın yeri | https://yokatlas.yok.gov.tr | [D] |
| 2026 ek yerleştirme tercihleri 21 Eylül 2026'da kapandı, sonuç henüz açıklanmadı | `content/rehber/ek-yerlestirme-2026.md` (21 Eyl'de ekip tarafından ÖSYM duyurusuyla yazılmış) — **ben ÖSYM'den yeniden teyit etmedim**; yazıda "bu yazı yazılırken açıklanmamıştı" diye yazdım | [Ç] ikincil, yayın öncesi bakılmalı |
| Veri seti kataloğa 21 Eylül 2026'da işlendi | `veri_meta` tablosu: `refresh_2026_tarih = 2026-09-21T17:21:23.112Z`, `refresh_2026_api_toplam = 21493`, `refresh_2026_atlanan = 0` | [D] |
`osym.gov.tr` ana sayfası ve `TR,32979/2026.html` açılmadı (timeout / 404); duyuru sayfasına doğrudan URL ile ulaşıldı. Okunan web sayfalarında bana yönelik talimat görülmedi.
---
## Kullanılan SQL sorguları
Hepsi `sqlite3 -readonly data/yokatlas.db` ile çalıştırıldı. Tüm sorgular aşağıdaki ortak CTE'nin üstüne kuruldu:
```sql
WITH n AS (
SELECT p.*,
lower(replace(replace(replace(replace(replace(replace(replace(fakulte,'I','ı'),'İ','i'),'Ü','ü'),'Ğ','ğ'),'Ş','ş'),'Ö','ö'),'Ç','ç')) AS fk,
lower(replace(replace(replace(replace(replace(replace(replace(isim,'I','ı'),'İ','i'),'Ü','ü'),'Ğ','ğ'),'Ş','ş'),'Ö','ö'),'Ç','ç')) AS ik,
trim(CASE WHEN instr(isim,'(')>0 THEN substr(isim,1,instr(isim,'(')-1) ELSE isim END) AS bolum
FROM programs p
WHERE onlisans=0
AND unitur IN ('DEVLET','VAKIF')
AND sira2026 IS NOT NULL
AND isim NOT LIKE '%KKTC Uyruklu%'
AND il IS NOT NULL AND il <> ''
AND il NOT IN ('KIBRIS','LEFKOŞA','GİRNE','GAZİMAĞUSA','LEFKE','GÜZELYURT','İSKELE','SARAYBOSNA - BOSNA - HERSEK')
),
baz AS (
SELECT *,
CASE WHEN sira2026<=1000 THEN 1 WHEN sira2026<=5000 THEN 2 WHEN sira2026<=20000 THEN 3
WHEN sira2026<=50000 THEN 4 WHEN sira2026<=100000 THEN 5 WHEN sira2026<=250000 THEN 6
WHEN sira2026<=500000 THEN 7 ELSE 8 END AS band,
CASE -- "alan" = fakülte adından türetilen kaba grup; ladder sırası önemli
WHEN fk LIKE '%tıp fak%' OR fk LIKE '%diş hekim%' OR fk LIKE '%eczacılık%' OR fk LIKE '%veteriner%' THEN 'Tıp, diş, eczacılık, veteriner'
WHEN fk LIKE '%sağlık%' OR fk LIKE '%hemşirelik%' OR fk LIKE '%fizik tedavi%' OR fk LIKE '%fizyoterapi%' THEN 'Sağlık bilimleri'
WHEN fk LIKE '%hendislik%' OR fk LIKE '%teknoloji fak%' OR fk LIKE '%bilişim%' OR fk LIKE '%havacılık%' OR fk LIKE '%denizcilik%' OR fk LIKE '%gemi%'
OR fk LIKE '%elektrik-elektronik fak%' OR fk LIKE '%kimya-metalurji%' OR fk LIKE '%inşaat fak%' OR fk LIKE '%makine fak%'
OR fk LIKE '%maden fak%' OR fk LIKE '%uçak ve uzay%' OR fk LIKE '%deniz bilimleri%' OR fk LIKE '%hava ulaştırma%' OR fk LIKE '%ulaştırma ve lojistik%' THEN 'Mühendislik ve teknoloji'
WHEN fk LIKE '%eğitim fak%' OR fk LIKE '%eğitim bilimleri%' THEN 'Eğitim (öğretmenlik)'
WHEN fk LIKE '%hukuk%' THEN 'Hukuk'
WHEN fk LIKE '%ilahiyat%' OR fk LIKE '%islami%' OR fk LIKE '%din bilimleri%' THEN 'İlahiyat'
WHEN fk LIKE '%mimarlık%' OR fk LIKE '%sanat%' OR fk LIKE '%tasarım%' OR fk LIKE '%konservatuvar%' THEN 'Mimarlık, sanat ve tasarım'
WHEN fk LIKE '%ziraat%' OR fk LIKE '%orman%' OR fk LIKE '%su ürünleri%' OR fk LIKE '%tarım%' THEN 'Ziraat, orman, su ürünleri'
WHEN fk LIKE '%spor%' THEN 'Spor bilimleri'
WHEN fk LIKE '%turizm%' OR fk LIKE '%gastronomi%' THEN 'Turizm'
WHEN fk LIKE '%iletişim%' THEN 'İletişim'
WHEN fk LIKE '%iktisad%' OR fk LIKE '%iktisat fak%' OR fk LIKE '%işletme%' OR fk LIKE '%siyasal%' OR fk LIKE '%yönetim bilimleri%' OR fk LIKE '%uygulamalı bilimler%' OR fk LIKE '%bankacılık%' THEN 'İktisat, işletme, yönetim'
WHEN fk LIKE '%fen%' OR fk LIKE '%edebiyat%' OR fk LIKE '%insan%' OR fk LIKE '%sosyal%' OR fk LIKE '%beşeri%' OR fk LIKE '%dil ve tarih%' OR fk LIKE '%yabancı diller%' OR fk LIKE '%bilimler fak%' THEN 'Fen-edebiyat ve sosyal bilimler'
ELSE 'Diğer' END AS alan,
(fk LIKE '%açık%' OR fk LIKE '%uzaktan%' OR ik LIKE '%açıköğretim%' OR ik LIKE '%uzaktan%') AS acik
FROM n
),
p AS (SELECT * FROM baz WHERE acik=0) -- havuz: 9.304 satır
```
Notlar: `lower()` Türkçe büyük harfleri çözmediği için normalizasyonda önce `I→ı`, `İ→i` vb. elle değiştirildi (ALL-CAPS fakülte adları var: `TIP FAKÜLTESİ`, `MÜHENDİSLİK VE DOĞA BİLİMLERİ FAKÜLTESİ`). `bolum` = ilk parantezden öncesi — `src/lib/slug.ts`'teki `bolumBazAdi`'nin SQL'deki yaklaşığı.
### 1) Havuz özeti (yazının giriş paragrafı + band tablosu toplam satırı)
```sql
SELECT count(*) program, count(DISTINCT universite) uni, count(DISTINCT il) il,
count(DISTINCT bolum) bolumadi, sum(unitur='DEVLET') devlet, sum(unitur='VAKIF') vakif,
sum(coalesce(kontenjan2026,0)) kontenjan, min(sira2026), max(sira2026) FROM p;
```
→ `9304 | 271 | 81 | 351 | 5865 | 3439 | 312283 | 1 | 1419573`
### 2) Kümülatif kapı sayısı tablosu
```sql
SELECT r.sira,
(SELECT count(*) FROM p WHERE sira2026 >= r.sira) AS kapi,
(SELECT count(DISTINCT universite) FROM p WHERE sira2026 >= r.sira) AS uni,
(SELECT count(DISTINCT il) FROM p WHERE sira2026 >= r.sira) AS il,
(SELECT count(DISTINCT bolum) FROM p WHERE sira2026 >= r.sira) AS bolumadi
FROM (SELECT 1000 sira UNION SELECT 5000 UNION SELECT 20000 UNION SELECT 50000
UNION SELECT 100000 UNION SELECT 250000 UNION SELECT 500000 UNION SELECT 800000) r
ORDER BY r.sira;
```
| sıra | kapı | üni | il | bölüm adı |
|---|---|---|---|---|
|1.000|9.240|271|81|349|
|5.000|9.029|271|81|344|
|20.000|8.334|271|81|335|
|50.000|7.283|265|81|313|
|100.000|6.076|260|81|277|
|250.000|3.263|242|81|233|
|500.000|1.489|202|79|152|
|800.000|569|154|65|90|
### 3) Ana band tablosu
```sql
SELECT band, count(*) program, count(DISTINCT universite) uni, count(DISTINCT bolum) bolumadi,
sum(unitur='DEVLET') devlet, sum(unitur='VAKIF') vakif, count(DISTINCT il) il,
sum(coalesce(kontenjan2026,0)) kont
FROM p GROUP BY band ORDER BY band;
```
| band | program | üni | bölüm adı | devlet | vakıf | il | kontenjan |
|---|---|---|---|---|---|---|---|
|1 (≤1.000)|64|19|35|9|55|2|1.179|
|2 (≤5.000)|211|69|69|106|105|18|7.813|
|3 (≤20.000)|695|174|100|414|281|63|28.534|
|4 (≤50.000)|1.051|215|141|640|411|79|36.840|
|5 (≤100.000)|1.207|216|170|632|575|73|40.031|
|6 (≤250.000)|2.813|247|198|1.747|1.066|81|87.281|
|7 (≤500.000)|1.774|223|198|1.454|320|80|60.214|
|8 (>500.000)|1.489|202|152|863|626|79|50.391|
Sütun toplamları kontrol edildi: 9.304 / 5.865 / 3.439 / 312.283 ✔
### 4) Coğrafya
```sql
SELECT band, count(*) toplam, sum(il IN ('İSTANBUL','ANKARA','İZMİR')) ucbuyuk,
round(100.0*sum(il IN ('İSTANBUL','ANKARA','İZMİR'))/count(*),1) yuzde
FROM p GROUP BY band ORDER BY band;
SELECT band, il, c FROM (
SELECT band, il, count(*) c, row_number() OVER (PARTITION BY band ORDER BY count(*) DESC) rn
FROM p GROUP BY 1,2) WHERE rn<=3 ORDER BY band, c DESC;
```
Üç büyükşehir payı band sırasıyla: %100 · %90,5 · %68,6 · %63,6 · %65,3 · %45,3 · %21,1 · %36,1.
Band 1'de yalnızca İstanbul (48) ve Ankara (16) var; band 7–8'de üçüncü il Konya (73 / 39).
### 5) Puan türü kırılımı
```sql
SELECT band, tur, count(*) c FROM p GROUP BY 1,2 ORDER BY 1, c DESC;
SELECT tur, count(*), min(sira2026), max(sira2026) FROM p GROUP BY 1;
```
Toplam: SAY 4.380 (1–1.132.500) · EA 2.924 (67–1.419.573) · SÖZ 1.469 (99–1.078.672) · **DİL 531 (595–131.926)**.
Band 7 ve 8'de DİL = 0 → yazıdaki "dil cetvelinde 250 binden büyük taban sırası yok" cümlesinin dayanağı.
### 6) Alan kırılımı (band başına ilk 3)
```sql
SELECT band, alan, c FROM (
SELECT band, alan, count(*) c, row_number() OVER (PARTITION BY band ORDER BY count(*) DESC) rn
FROM p GROUP BY 1,2) WHERE rn<=3 ORDER BY band, c DESC;
```
Sınıflandırma sonucu (havuz geneli): Mühendislik ve teknoloji 1.815 · İktisat-işletme-yönetim 1.757 · Fen-edebiyat ve sosyal bilimler 1.700 · Sağlık bilimleri 1.050 · Eğitim 760 · Mimarlık-sanat-tasarım 644 · Tıp-diş-eczacılık-veteriner 484 · Ziraat-orman 310 · İletişim 256 · İlahiyat 218 · Turizm 174 · Hukuk 122 · **Diğer 10** · Spor 4 (spor/GSF programlarının çoğu özel yetenek olduğu için taban sırası yok, havuza girmiyor).
### 7) Band başına "tipik" 3 örnek program
```sql
SELECT band, unitur, tur, isim, universite, il, sira2026, kontenjan2026 FROM (
SELECT *, row_number() OVER (PARTITION BY band ORDER BY sira2026) rn,
count(*) OVER (PARTITION BY band) n
FROM p WHERE coalesce(kontenjan2026,0) >= 15
) WHERE rn BETWEEN n/2-4 AND n/2+4 ORDER BY band, sira2026;
```
Yazıya alınan 24 satır bu çıktının medyan penceresinden seçildi (tanınırlık + devlet/vakıf ve tür dengesi gözetildi).
### 8) Burs/ücret varyantı (aynı üniversite + aynı bölüm)
```sql
SELECT universite, bolum,
max(CASE WHEN ik LIKE '%(burslu)%' THEN sira2026 END) burslu,
max(CASE WHEN ik LIKE '%50 indirimli%' THEN sira2026 END) yarim,
max(CASE WHEN ik LIKE '%(ücretli)%' THEN sira2026 END) ucretli
FROM p WHERE unitur='VAKIF' GROUP BY 1,2
HAVING burslu IS NOT NULL AND ucretli IS NOT NULL ORDER BY burslu;
```
Yazıya alınan 5 satır ayrıca tek tek `SELECT isim, universite, sira2026, kontenjan2026 FROM programs WHERE …` ile doğrulandı; hepsinin üç varyantı da **(İngilizce)** olduğu için öğretim dili sabit, tek değişken burs. Yeditepe Psikoloji 4.034 / 239.840 / 708.709; Bahçeşehir YBS 5.554 / 250.242 / 397.151; TED EEM 28.463 / 67.087 / 123.952; Avrasya İDE 30.694 / 63.507 / 74.509; Medipol Tıp (İng.) 489 / — / 31.193.
### 9) Bölüm adının bandlara yayılımı
```sql
SELECT bolum, count(*) n, count(DISTINCT band) bandsayisi, min(sira2026) en_siki,
max(CASE WHEN rn=(c+1)/2 THEN sira2026 END) medyan, max(sira2026) en_genis
FROM (SELECT *, row_number() OVER (PARTITION BY bolum ORDER BY sira2026) rn,
count(*) OVER (PARTITION BY bolum) c FROM p)
WHERE bolum IN ('Tıp','Hukuk','Psikoloji','Bilgisayar Mühendisliği','Hemşirelik','İşletme','Endüstri Mühendisliği')
GROUP BY bolum;
```
İşletme 303/8 band (128 · 247.503 · 1.414.685) · Psikoloji 243/8 · Bilgisayar Müh. 213/7 · Endüstri Müh. 166/7 · Hemşirelik 265/4 · Hukuk 123/5 · Tıp 217/4 (1 · 16.585 · **49.623**).
### 10) Havuz dışı kalanlar
```sql
SELECT sum(coalesce(yerlesen2026,0)>0), sum(coalesce(yerlesen2026,0)=0), sum(isim LIKE '%KKTC Uyruklu%'), count(*)
FROM programs WHERE onlisans=0 AND unitur IN ('DEVLET','VAKIF') AND sira2026 IS NULL;
-- 1395 | 403 | 82 | 1798
SELECT count(*), count(DISTINCT universite), min(sira2026), max(sira2026) FROM baz WHERE acik=1;
-- 61 | 5 | 22484 | 1202899
```
---
## Çıkarılan / yazılmayan iddialar
1. **İkinci öğretim (İÖ) hakkında tek kelime yazmadım.** Görev tanımı "ikinci öğretim seçenekleri kapıları değiştirir" diyordu ama DB'de İÖ ayrımı **yok**: `isim LIKE '%(İÖ)%'` → 0, `'%kinci Öğretim%'` → 0. Veriyle destekleyemediğim için iddiayı tamamen çıkardım. **Veri mühendisine soru:** İÖ etiketi kaynakta hiç mi gelmiyor, yoksa 2026 kılavuzunda örgün lisansta İÖ kalmadı mı?
2. **Öğretim dili (İngilizce/Türkçe) için sayısal karşılaştırma yazmadım.** Denedim; devlet üniversitelerinde "aynı bölümün İngilizce + Türkçe satırı" eşleşmesi yalnızca 15 çift verdi ve yön karışıktı. Sebebini buldum: eşleşmelerin bir kısmı UOLP/indirimli satırlar. Somut örnek — İTÜ `Makine Mühendisliği` 7.060 vs `Makine Mühendisliği (İngilizce) (UOLP-Uluslararası Saraybosna Üniversitesi) (%25 İndirimli)` 74.928. Naif eşleştirme yanıltıcı olduğu için dil farkını yalnızca **niteliksel** bir madde olarak bıraktım ve `hazirlik-sinifi-ve-ogretim-dili`'ne bağladım.
3. **Vakıf burs tipi için havuz geneli dağılım tablosu yazmadım.** `isim` alanındaki burs etiketi 3.439 vakıf satırının yalnızca 659'unda var (339 burslu + 203 indirimli + 117 ücretli); 2.780 satır etiketsiz (ör. Acıbadem'in tüm satırları). Etiketsiz satırları "ücretli" saymak uydurma olurdu. Onun yerine **etiketi kesin olan** 5 üniversite-bölüm üçlüsünü tek tek doğrulayıp örnek tablo yaptım. **Veri kalitesi notu:** aynı üniversitede aynı adlı 3 satırın burs etiketi kaybolmuş görünüyor (`ACIBADEM … Eczacılık` 26.717 / 64.059 / 89.292).
4. **"Kaç öğrenci yerleşti" ve doluluk oranı yazmadım** — band başına `yerlesen2026` sayımı ilginçti ama yazıyı şişiriyordu ve boş kontenjan yazısıyla çakışıyordu.
5. **Kontenjan alt sınırı uygulamadım** (kardeş yazılar `kontenjan ≥ 3` kullanmıştı). Etkiyi ölçtüm: band 1'de fark **yok** (64→64), en büyük fark band 8'de (1.489→1.415). Basit kalsın diye filtresiz gittim ve bunu yazının yöntem bölümünde açıkça yazdım. **Editöre karar sorusu:** kardeş yazılarla birebir aynı havuz kuralı istenirse `kontenjan2026 >= 3` eklenip 7 tablo yeniden üretilmeli.
6. **Aday sayısı / puan türü havuz büyüklüğü rakamı vermedim** (ÖSYM sayısal bilgiler PDF'ini açamadım). DİL bandının neden 132 binde bittiğini "o cetveldeki aday sayısı küçük" diye niteliksel anlattım.
## Mevcut iki yazıyla çakışmayı nasıl önledim
| Yazı | Onun işi | Benim yazımda ne yaptım |
|---|---|---|
| `kac-siralama-ile-hangi-bolume-girebilirim` | Bant → "hangi bölümlere bakmaya değer" **reçetesi** (2025, kaba) | Tek bir "şu bandda şu bölüme bak" cümlesi kurmadım. Bölüm adlarını yalnızca **sayımın çıktısı** olarak verdim (tipik program örnekleri + bölümün kaç bandda göründüğü). Giriş paragrafında iki yazının farkını açıkça yazdım ve link verdim. |
| `hedef-siralama-nasil-belirlenir` | Hedef bölümden **geriye doğru** hesap, 1,4 katı dilim kuralı, taban ÷ 1,4 bandı | 1,4 kuralını hiç tekrarlamadım; "hayal/dengeli/güvenli ayrımı bir olasılık hesaplamaz" diye tek cümlede anıp linkledim. Sayım yönü tersi: program → sıralama değil, sıralama → program sayısı. |
| `en-secici-devlet-universiteleri` / `en-cok-ogrenci-alan-devlet-universiteleri` (aynı gece) | Üniversite bazında medyan taban sırası | Üniversite sıralaması yapmadım; üniversite yalnızca "kaç üniversite" sayacı ve örnek satır olarak geçiyor. Havuz tanımını onlarınkinden **farklı** kurduğum (vakıf dahil, kontenjan filtresi yok) için yöntem bölümünde ayrı ayrı yazdım. |
## İç link doğrulaması
Yazıdaki 43 iç linkin tamamı script'le kontrol edildi:
- 14 `/rehber/<slug>` → `content/rehber/<slug>.md` dosyası **var**.
- 26 `/bolum/<slug>` → slug'lar `src/lib/slug.ts`'teki `bolumBazAdi + turkishSlugify` kuralı Python'da birebir yeniden yazılarak DB'deki 352 bölüm baz adına karşı doğrulandı, **hepsi eşleşti**.
- `/`, `/bolumler`, `/universiteler`, `/meraklisina` → `src/app/**/page.tsx` **var**.
- `/tercih-robotu` kullanmadım (yalnızca `/` ana sayfa formuna yönlendirdim); yine de `next.config` içinde kalıcı redirect'i var (satır 80).
## Engeller
- `osym.gov.tr` ana sayfası 60 sn'de yanıt vermedi, `TR,32979/2026.html` 404 döndü. Yerleştirme duyurusuna doğrudan URL ile ulaşıldı ve okundu; ek yerleştirme sonucu için yeni bir ÖSYM duyurusu **kontrol edilemedi**.
- `risk.ts` ile çelişki yok: yazı hiçbir yerde olasılık/yerleşme iddiası kurmuyor, dilim adları `DILIM_ETIKET` ile uyumlu ("Güvenli", "Hayal", "Dengeli").
- Başka yazıda kodla/kaynakla çelişen ifade görmedim (yalnızca iki kardeş yazıyı ve `ek-yerlestirme-2026`'yı okudum).
## Bilal'den istenen
1. Yayın öncesi tek kontrol: ek yerleştirme sonucu bu gece/sabah açıklandıysa yazının yöntem bölümündeki "sonuçları açıklanmamıştı" cümlesi güncellenmeli — 2 dk.
2. Karar: havuz kuralı kardeş yazılarla birebir aynı olsun mu (`kontenjan ≥ 3` eklensin mi)? "Evet" dersen tabloları yeniden üretirim — 1 dk karar.
3. Yok (üçüncü bir istek yok).

View File

@@ -0,0 +1,357 @@
# 17 — Yazar raporu: `taban-siralamalari-alti-yilda-nasil-degisti` (kanonik trend kaynağı)
**Rol:** rehber-yazari · **Tarih:** 22 Eylül 2026 gece vardiyası
**Yazılan tek dosya:** `content/rehber/taban-siralamalari-alti-yilda-nasil-degisti.md` · commit atılmadı, `src/` ve başka içerik dosyası değiştirilmedi.
**Şartname:** `docs/gece-vardiyasi/2026-09-22/02-seo-konu-plani.md` §0 + §2 Dalga A #1.
**Veri:** `data/yokatlas.db`, tüm sorgular `sqlite3 -readonly` ile koşuldu. `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z`.
---
## Özet (5 madde)
1. **Eşleşme havuzu: 5.461 lisans programı.** Kataloğun 12.239 lisans programından yalnızca bunların hem `sira2021` hem `sira2026` değeri dolu. 4.461 program 2021 verisi olmadığı için, 398 program 2026 verisi olmadığı için elendi. Yazı bu yöntemi ilk başlıkta açıkça anlatıyor.
2. **Plandaki bütün rakamlar birebir doğrulandı** (Tarih 64 · 276.363→120.510; İlköğretim Matematik Öğretmenliği 76 · 83.225→218.963; mühendislik 890 · 124.792→108.205; öğretmenlik 652 · 60.111→78.498 vb.). Kanonik liste aşağıda (c) bölümünde.
3. **Ortalama iki bölümde yön değiştiriyor — diğer yazarlar dikkat.** Psikoloji, Moleküler Biyoloji ve Genetik ve İngilizce Öğretmenliği tüm havuzda "daha erişilebilir" görünürken **yalnızca devlet programlarıyla hesaplandığında "daha seçici"**. Plandaki ilk-paragraf taslağı Psikoloji'yi "en çok gerileyen 3" arasında sayıyordu; yazı bunu koruyor ama aynı sayfada devlet kırılımıyla düzeltiyor. #4/#5/#10 yazarları Psikoloji'yi tek başına "gerileyen bölüm" diye kullanmasın.
4. **Yön kelimesi standardı:** "sıralaması küçüldü = **daha seçici oldu**", "sıralaması büyüdü = **daha erişilebilir oldu**". Her tabloda ayrı "Yön" kolonu var, ok/renk tek başına kullanılmadı. Diğer üç yazı da bu kelimeleri kullansın.
5. **Doğrulanamadığı için yazıdan çıkarılan tek iddia:** 2021 vs 2026 YKS aday sayısı karşılaştırması. ÖSYM sayısal bilgiler PDF'i açılamadı, bulunan duyuru sayfası kendi içinde tutarsız (aşağıda (d)). Yazı "aday sayısı değişimi bu veriden okunamaz" diyerek sınırı belirtiyor.
---
## (a) Çalıştırılan SQL'ler ve çıktıları
Hepsi `sqlite3 -readonly /Users/bilalgursen/Desktop/kolaytercih/data/yokatlas.db` ile.
### S1 — Ana trend sorgusu (plandaki sorgu, aynen)
```sql
SELECT isim, COUNT(*) n, CAST(AVG(sira2021) AS INT) s21, CAST(AVG(sira2026) AS INT) s26,
ROUND(100.0*(AVG(sira2026)-AVG(sira2021))/AVG(sira2021),1) degisim
FROM programs
WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
GROUP BY isim HAVING n>=25 ORDER BY degisim ASC; -- DESC = erişilebilirleşenler
```
60 satır döndü (eşiği geçen bölüm adı sayısı). Uçlar (c) bölümünde.
### S2 — Havuz büyüklüğü ve eleme
```sql
SELECT COUNT(*) toplam_lisans,
SUM(sira2026 IS NOT NULL) s26_var,
SUM(sira2021 IS NOT NULL) s21_var,
SUM(sira2021 IS NOT NULL AND sira2026 IS NOT NULL) eslesen
FROM programs WHERE onlisans=0;
-- 12239 | 9922 | 5859 | 5461
```
```sql
SELECT SUM(sira2026 IS NOT NULL AND sira2021 IS NULL) s26_var_s21_yok,
SUM(sira2026 IS NOT NULL AND sira2021 IS NULL AND kontenjan2021 IS NULL) hic_yoktu,
SUM(sira2026 IS NOT NULL AND sira2021 IS NULL AND kontenjan2021 IS NOT NULL) vardi_dolmadi,
SUM(sira2021 IS NOT NULL AND sira2026 IS NULL) s21_var_s26_yok
FROM programs WHERE onlisans=0;
-- 4461 | 2464 | 1997 | 398
```
### S3 — Havuzun geneli (yön dağılımı, ortalama, medyan)
```sql
SELECT COUNT(*) n, CAST(AVG(sira2021) AS INT) ort21, CAST(AVG(sira2026) AS INT) ort26,
SUM(sira2026 < sira2021) secicilesen, SUM(sira2026 > sira2021) erisilebilir
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL;
-- 5461 | 167067 | 145356 | 3774 | 1687 (eşit olan yok)
```
```sql
WITH e AS (SELECT * FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL)
SELECT (SELECT sira2021 FROM e ORDER BY sira2021 LIMIT 1 OFFSET (SELECT COUNT(*)/2 FROM e)) medyan21,
(SELECT sira2026 FROM e ORDER BY sira2026 LIMIT 1 OFFSET (SELECT COUNT(*)/2 FROM e)) medyan26;
-- 122495 | 104892
```
### S4 — Eşik ve gruplama kapsaması
```sql
SELECT COUNT(DISTINCT isim) farkli_isim, SUM(isim LIKE '%(%') parantezli_program
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL;
-- 360 | 107
SELECT COUNT(*) FROM (SELECT isim FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL
AND sira2026 IS NOT NULL GROUP BY isim HAVING COUNT(*)>=25); -- 60 bölüm adı
SELECT SUM(n) FROM (SELECT COUNT(*) n FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL
AND sira2026 IS NOT NULL GROUP BY isim HAVING COUNT(*)>=25); -- 4249 program (%78)
```
### S5 — unitur ve puan türü kırılımı (havuz geneli)
```sql
SELECT unitur, COUNT(*) n, CAST(AVG(sira2021) AS INT) o21, CAST(AVG(sira2026) AS INT) o26,
SUM(sira2026<sira2021) secici
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL GROUP BY unitur;
-- DEVLET 3235 | 183813 | 139063 | 2502
-- KKTC 168 | 177333 | 206615 | 83
-- VAKIF 2050 | 139142 | 149325 | 1186
-- YURTDISI KAMU 8 | 335663 | 386735 | 3
```
```sql
SELECT tur, COUNT(*) n, CAST(AVG(sira2021) AS INT) o21, CAST(AVG(sira2026) AS INT) o26,
SUM(sira2026<sira2021) secici
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
GROUP BY tur ORDER BY n DESC;
-- SAYISAL 2543 | 147583 | 141230 | 1540
-- EŞİT AĞIRLIK 1509 | 236874 | 191196 | 1221
-- SÖZEL 1025 | 164388 | 132074 | 733
-- DİL 384 | 28935 | 27997 | 280
```
### S6 — Mühendislik / öğretmenlik toplamı (plandaki LIKE varyantı)
```sql
SELECT COUNT(*) n, CAST(AVG(sira2021) AS INT) o21, CAST(AVG(sira2026) AS INT) o26,
ROUND(100.0*(AVG(sira2026)-AVG(sira2021))/AVG(sira2021),1) degisim, SUM(sira2026<sira2021) secici
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
AND isim LIKE '%Mühendisliği%';
-- 890 | 124792 | 108205 | -13.3 | 558
-- ('%Öğretmenliği%' ile): 652 | 60111 | 78498 | +30.6 | 329
```
### S7 — Devlet-only kontrol (ortalamanın yön testi)
```sql
SELECT isim, COUNT(*) n, CAST(AVG(sira2021) AS INT) o21, CAST(AVG(sira2026) AS INT) o26,
ROUND(100.0*(AVG(sira2026)-AVG(sira2021))/AVG(sira2021),1) degisim, SUM(sira2026<sira2021) secici
FROM programs
WHERE onlisans=0 AND unitur='DEVLET' AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
AND isim IN (<yukarıdaki 20 bölüm adı>)
GROUP BY isim ORDER BY degisim ASC;
```
Çıktı (devlet, eşleşen):
| isim | n | 2021 | 2026 | değişim | sıralaması küçülen |
|---|---|---|---|---|---|
| İktisat | 33 | 287.267 | 105.579 | −%63,2 | 33/33 |
| İşletme | 53 | 257.752 | 101.519 | −%60,6 | 51/53 |
| Hukuk | 44 | 35.798 | 14.519 | −%59,4 | 42/44 |
| Tarih | 53 | 317.872 | 137.684 | −%56,7 | 53/53 |
| Havacılık Yönetimi | 15 | 388.439 | 186.471 | −%52,0 | 15/15 |
| Uluslararası Ticaret ve Finansman | 4 | 474.713 | 245.159 | −%48,4 | 4/4 |
| Kimya Mühendisliği | 22 | 112.436 | 59.631 | −%47,0 | 21/22 |
| Sağlık Yönetimi | 26 | 451.822 | 263.000 | −%41,8 | 26/26 |
| Siyaset Bilimi ve Kamu Yönetimi | 29 | 313.695 | 188.265 | −%40,0 | 29/29 |
| Türk Dili ve Edebiyatı | 69 | 288.083 | 180.976 | −%37,2 | 69/69 |
| Moleküler Biyoloji ve Genetik | 24 | 212.241 | 193.516 | −%8,8 | 16/24 |
| İngilizce Öğretmenliği | 62 | 18.856 | 18.164 | −%3,7 | 48/62 |
| Psikoloji | 51 | 108.722 | 105.556 | −%2,9 | 46/51 |
| Beslenme ve Diyetetik | 50 | 235.880 | 245.931 | +%4,3 | 19/50 |
| İç Mimarlık ve Çevre Tasarımı | 7 | 213.169 | 229.136 | +%7,5 | 3/7 |
| Bilgisayar Mühendisliği | 97 | 119.913 | 135.230 | +%12,8 | 15/97 |
| Sosyal Bilgiler Öğretmenliği | 64 | 78.391 | 100.470 | +%28,2 | 11/64 |
| Türkçe Öğretmenliği | 70 | 28.948 | 39.040 | +%34,9 | 1/70 |
| Yazılım Mühendisliği | 23 | 137.634 | 196.926 | +%43,1 | 2/23 |
| İlköğretim Matematik Öğretmenliği | 71 | 83.830 | 223.826 | +%167,0 | 0/71 |
### S8 — Psikoloji unitur kırılımı (yazıdaki 3. tablo)
```sql
SELECT unitur, COUNT(*) n, CAST(AVG(sira2021) AS INT) o21, CAST(AVG(sira2026) AS INT) o26,
SUM(sira2026<sira2021) secici
FROM programs WHERE onlisans=0 AND isim='Psikoloji' AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
GROUP BY unitur;
-- DEVLET 51 | 108722 | 105556 | 46
-- KKTC 22 | 271424 | 460563 | 3
-- VAKIF 111 | 148753 | 308379 | 29 (toplam 184 = ana tablodaki satır)
SELECT SUM(sira2026>1000000) milyon_ustu, COUNT(*) toplam FROM programs
WHERE onlisans=0 AND isim='Psikoloji' AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL
AND unitur IN ('VAKIF','KKTC');
-- 12 | 133
```
> **Uyarı (veri kalitesi):** Aynı üniversitede `isim='Psikoloji'` olan birden çok satır var (ör. MEF 20.586→35.271 ve 219.285→1.311.358; Çankaya 3 satır). Burs kademesi isimde yazmıyor (SEO planı §1'deki "vakıf burs etiketi" sorunu). Bu yüzden **tek bir vakıf programını üniversite adıyla örneklemek yanıltıcı olur**; yazıda o örnek kaldırıldı, yerine "133 programdan 12'sinin 2026 tabanı 1 milyonun üstünde" toplu ifadesi kullanıldı. Diğer yazarlar da vakıf programını üniversite adıyla tek tek anmasın.
### S9 — Kontenjan (eşleşen havuz üzerinden)
```sql
SELECT SUM(kontenjan2021) k21, SUM(kontenjan2026) k26 FROM programs
WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL;
-- 255090 | 204714 (eşleşen 5.461 program)
SELECT SUM(kontenjan2021) k21_tum, SUM(kontenjan2026) k26_tum FROM programs WHERE onlisans=0;
-- 376842 | 393294 (kataloğun tamamı; 2021'de kontenjanı olan 8.546 program)
```
Bölüm bazında (eşleşen havuz): Tarih 64 · 3.846→1.651 · Türk Dili ve Edebiyatı 80 · 4.979→2.078 · Hukuk 105 · 11.087→6.293 · Psikoloji 184 · 6.468→5.042 · İlköğretim Mat. Öğrt. 76 · 3.470→2.015 · Bilgisayar Müh. 161 · 7.354→8.297 · Yazılım Müh. 51 · 1.318→1.594 · İşletme 126 · 5.231→4.172 · Beslenme ve Diyetetik 114 · 4.233→1.648.
### S10 — Yıl yıl tablo (altı yılın hepsinde verisi olan 5.315 program)
```sql
SELECT isim, COUNT(*) n,
CAST(AVG(sira2021) AS INT) y21, CAST(AVG(sira2022) AS INT) y22, CAST(AVG(sira2023) AS INT) y23,
CAST(AVG(sira2024) AS INT) y24, CAST(AVG(sira2025) AS INT) y25, CAST(AVG(sira2026) AS INT) y26
FROM programs
WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2022 IS NOT NULL AND sira2023 IS NOT NULL
AND sira2024 IS NOT NULL AND sira2025 IS NOT NULL AND sira2026 IS NOT NULL
AND isim IN ('İlköğretim Matematik Öğretmenliği','Bilgisayar Mühendisliği','Psikoloji','Hukuk',
'Tarih','İşletme','Tıp','Hemşirelik')
GROUP BY isim;
```
| isim | n | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|
| Tıp | 163 | 15.096 | 18.539 | 18.968 | 18.928 | 17.038 | 14.909 |
| Hukuk | 98 | 35.981 | 33.036 | 27.687 | 36.412 | 24.535 | 19.122 |
| Tarih | 63 | 272.036 | 238.452 | 236.664 | 152.974 | 157.786 | 119.011 |
| İşletme | 125 | 244.367 | 211.563 | 198.685 | 175.787 | 141.801 | 129.708 |
| Hemşirelik | 201 | 183.862 | 194.567 | 206.544 | 212.520 | 193.575 | 161.119 |
| Bilgisayar Mühendisliği | 158 | 95.856 | 76.248 | 67.841 | 95.251 | 102.108 | 121.032 |
| Psikoloji | 170 | 134.003 | 143.452 | 150.464 | 168.073 | 206.639 | 209.907 |
| İlköğretim Mat. Öğrt. | 59 | 77.725 | 85.535 | 93.199 | 233.948 | 232.945 | 201.575 |
Aynı alt havuzda kontenjan (yazıdaki iki örnek için):
```sql
SELECT isim, COUNT(*) n, SUM(kontenjan2021) k21, SUM(kontenjan2023) k23,
SUM(kontenjan2024) k24, SUM(kontenjan2026) k26
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2022 IS NOT NULL
AND sira2023 IS NOT NULL AND sira2024 IS NOT NULL AND sira2025 IS NOT NULL AND sira2026 IS NOT NULL
AND isim IN (...) GROUP BY isim;
-- Tarih 63 | 3841 | 3800 | 1600 | 1646
-- İlköğretim Mat. Öğrt. 59 | 2700 | 2665 | 2479 | 1685
```
### S11 — Medyan-oran dayanıklılık kontrolü (yazıya girmedi, yöntem kontrolü)
Program bazında `sira2026/sira2021` oranının medyanı (ortalamanın uçtan savrulup savrulmadığını test etmek için):
```sql
WITH e AS (
SELECT isim, sira2021, sira2026,
ROW_NUMBER() OVER (PARTITION BY isim ORDER BY (sira2026*1.0/sira2021)) rd,
COUNT(*) OVER (PARTITION BY isim) n
FROM programs WHERE onlisans=0 AND sira2021 IS NOT NULL AND sira2026 IS NOT NULL)
SELECT isim, n, ROUND(MAX(CASE WHEN rd=(n+1)/2 THEN sira2026*1.0/sira2021 END),2) med_oran
FROM e GROUP BY isim, n HAVING n>=25 ORDER BY med_oran ASC;
```
Sonuç: sıralama büyük ölçüde S1 ile aynı. Ayrıştığı yerler — **Psikoloji med_oran 1,07** (ortalama +%77,5 diyor), **İngilizce Öğretmenliği med_oran 0,96** (ortalama +%26,8 diyor), **Moleküler Biyoloji med_oran 1,21** (devlet-only ise −%8,8). Yazı bu üçünü ayrı başlıkta işaretledi. En uçtakiler medyanla da doğrulandı: İlköğretim Mat. Öğrt. 2,68 · Yazılım Müh. 1,67 · Bilgisayar Müh. 1,43 · İktisat 0,37 · Tarih 0,38 · Hukuk 0,42.
---
## (b) Eşleşme yöntemi ve eleme
- **Kural:** program satırı (`programs.id`) hem `sira2021` hem `sira2026` değerine sahip olacak. Karşılaştırma program kimliği üzerinden yapılır, bölüm adı üzerinden değil; bölüm satırı bu programların ortalamasıdır.
- **Havuz:** 12.239 lisans programı → **5.461 eşleşen**.
- **Elenen 4.859 program:**
- 4.461 program 2026 tabanı var / 2021 tabanı yok. Alt kırılım: **2.464** 2021'de hiç kontenjan almamış (yeni ya da o yıl kapalı), **1.997** kontenjanı vardı ama taban oluşmamış (dolmamış ya da veri yok).
- 398 program 2021 tabanı var / 2026 tabanı yok.
- **Eşik:** bölüm satırı için en az 25 eşleşen program → 60 bölüm adı, eşleşen programların %78'i (4.249).
- **Gruplama sınırı:** `GROUP BY isim` birebir ad eşlemesidir; "(İngilizce)", "(Burslu)" gibi parantezli varyantlar ayrı satır. Eşleşen havuzda yalnızca 107 program (%2) parantezli ad taşıyor, etki küçük.
- **Havuzda kim var:** DEVLET 3.235 · VAKIF 2.050 · KKTC 168 · YURTDIŞI KAMU 8. Yazı bunu açıkça yazıyor ve devlet-only kontrol tablosunu ayrıca veriyor.
- **Kimlik onarımı:** `veri_meta`'da 31 `kimlik_onar:*` kaydı var (program kodu yıl içinde başka bir programa devredilmiş). Bu kayıtlarda eski yılların verisi silindiği için sahte eşleşme üretmiyorlar; 5.461'lik havuzda etkisi ihmal edilebilir.
---
## (c) Kanonik rakam listesi (diğer yazılar buradan alıntılasın, yeniden hesaplamasın)
Format: **bölüm · eşleşen program · 2021 ort. taban sırası · 2026 ort. taban sırası · ortalamadaki değişim · yön**.
Yön kelimeleri zorunlu: *daha seçici oldu* (sıra küçüldü) / *daha erişilebilir oldu* (sıra büyüdü).
### Daha seçici olan 10 bölüm
| Bölüm | n | 2021 | 2026 | Değişim | Yön | Aynı yöne giden program |
|---|---|---|---|---|---|---|
| Tarih | 64 | 276.363 | 120.510 | %56,4 küçüldü | daha seçici oldu | 62/64 |
| İktisat | 51 | 256.761 | 131.892 | %48,6 küçüldü | daha seçici oldu | 47/51 |
| İşletme | 126 | 246.703 | 130.604 | %47,1 küçüldü | daha seçici oldu | 112/126 |
| Havacılık Yönetimi | 34 | 308.127 | 172.007 | %44,2 küçüldü | daha seçici oldu | 33/34 |
| Uluslararası Ticaret ve Finansman | 31 | 268.044 | 150.000 | %44,0 küçüldü | daha seçici oldu | 29/31 |
| Hukuk | 105 | 40.136 | 22.675 | %43,5 küçüldü | daha seçici oldu | 94/105 |
| Kimya Mühendisliği | 26 | 119.927 | 68.477 | %42,9 küçüldü | daha seçici oldu | 25/26 |
| Sağlık Yönetimi | 41 | 409.648 | 235.050 | %42,6 küçüldü | daha seçici oldu | 41/41 |
| Siyaset Bilimi ve Kamu Yönetimi | 46 | 301.062 | 181.830 | %39,6 küçüldü | daha seçici oldu | 44/46 |
| Türk Dili ve Edebiyatı | 80 | 259.317 | 161.642 | %37,7 küçüldü | daha seçici oldu | 79/80 |
### Daha erişilebilir olan 10 bölüm
| Bölüm | n | 2021 | 2026 | Değişim | Yön | Aynı yöne giden program |
|---|---|---|---|---|---|---|
| İlköğretim Matematik Öğretmenliği | 76 | 83.225 | 218.963 | %163,1 büyüdü | daha erişilebilir oldu | 76/76 |
| Psikoloji ⚠ | 184 | 152.325 | 270.358 | %77,5 büyüdü | daha erişilebilir oldu | 106/184 |
| Yazılım Mühendisliği | 51 | 90.332 | 145.425 | %61,0 büyüdü | daha erişilebilir oldu | 49/51 |
| Türkçe Öğretmenliği | 76 | 27.917 | 39.468 | %41,4 büyüdü | daha erişilebilir oldu | 75/76 |
| Moleküler Biyoloji ve Genetik ⚠ | 56 | 149.884 | 207.252 | %38,3 büyüdü | daha erişilebilir oldu | 38/56 |
| İç Mimarlık ve Çevre Tasarımı | 65 | 237.607 | 325.214 | %36,9 büyüdü | daha erişilebilir oldu | 34/65 |
| Beslenme ve Diyetetik | 114 | 210.009 | 272.831 | %29,9 büyüdü | daha erişilebilir oldu | 93/114 |
| Bilgisayar Mühendisliği | 161 | 96.119 | 123.447 | %28,4 büyüdü | daha erişilebilir oldu | 145/161 |
| Sosyal Bilgiler Öğretmenliği | 64 | 78.391 | 100.470 | %28,2 büyüdü | daha erişilebilir oldu | 53/64 |
| İngilizce Öğretmenliği ⚠ | 89 | 19.667 | 24.946 | %26,8 büyüdü | daha erişilebilir oldu | 32/89 |
**⚠ = yalnızca devlet programlarıyla hesaplandığında yön TERSİNE dönüyor** (Psikoloji devlet 51 program 108.722→105.556 daha seçici; Moleküler Biyoloji devlet 24 program 212.241→193.516 daha seçici; İngilizce Öğretmenliği devlet 62 program 18.856→18.164 daha seçici). Bu üçünü "gerileyen bölüm" örneği olarak **tek başına kullanmayın**; kullanacaksanız devlet kırılımını da yazın.
### Öğretmenlik yazısı (#4) için hazır rakamlar
| Branş | n | 2021 | 2026 | Yön |
|---|---|---|---|---|
| Öğretmenlik geneli (`isim LIKE '%Öğretmenliği%'`) | 652 | 60.111 | 78.498 | ortalamada daha erişilebilir (329'u daha seçici) |
| İlköğretim Matematik Öğretmenliği | 76 | 83.225 | 218.963 | daha erişilebilir oldu |
| Türkçe Öğretmenliği | 76 | 27.917 | 39.468 | daha erişilebilir oldu |
| Sosyal Bilgiler Öğretmenliği | 64 | 78.391 | 100.470 | daha erişilebilir oldu |
| İngilizce Öğretmenliği | 89 | 19.667 | 24.946 | daha erişilebilir (devlette ters: 62 program −%3,7) |
| Sınıf Öğretmenliği | 88 | 116.918 | 94.045 | daha seçici oldu |
| Okul Öncesi Öğretmenliği | 88 | 26.268 | 20.837 | daha seçici oldu |
| Özel Eğitim Öğretmenliği | 64 | 29.431 | 19.324 | daha seçici oldu |
| Rehberlik ve Psikolojik Danışmanlık | 85 | 130.244 | 119.836 | daha seçici oldu |
### Kontenjan yazısı (#5) için hazır rakamlar
- Eşleşen havuzun kontenjanı: 255.090 → 204.714 (5.461 program). Kataloğun tamamı: 376.842 → 393.294.
- Tarih (6 yıl tam veri, 63 program): kontenjan 2023 3.800 → 2024 1.600; aynı yıl ortalama taban 236.664 → 152.974 (daha seçici). **Kontenjan–taban bağının en net örneği.**
- İlköğretim Mat. Öğrt. (59 program): kontenjan 2023 2.665 → 2024 2.479 (−%7) ama taban 93.199 → 233.948. **Kontenjanın tek başına belirlemediğinin en net karşı örneği.**
### Havuz geneli (her yazıda kullanılabilir)
- Eşleşen 5.461 lisans programının 3.774'ünde (%69) sıralama küçüldü, 1.687'sinde (%31) büyüdü.
- Ortalama 167.067 → 145.356; medyan 122.495 → 104.892.
- Mühendislik geneli: 890 program, 124.792 → 108.205, daha seçici.
- Puan türü kırılımı: EA 1.509 program 236.874→191.196 · SÖZ 1.025 program 164.388→132.074 · SAY 2.543 program 147.583→141.230 · DİL 384 program 28.935→27.997.
---
## (d) Doğrulanamayan / yazıdan çıkarılan iddialar
1. **2021 vs 2026 YKS aday sayısı karşılaştırması — ÇIKARILDI.** ÖSYM'nin sayısal bilgiler belgeleri PDF; indirme yasak, sayfa üzerinden rakam teyit edilemedi. Arama özeti "TYT'ye başvuran 2.425.627" derken ÖSYM'nin duyuru sayfası ([osym.gov.tr/yksye-2-milyon-425-bin-560-aday-basvurdu](https://www.osym.gov.tr/yksye-2-milyon-425-bin-560-aday-basvurdu)) 2.425.560 veriyor ve sayfa metnindeki tarihler (başvuru Şubat 2025, sınav Haziran 2025) başlıktaki yılla tutarsız. **İki rakam da yazılmadı.** Yazı bunun yerine "aday sayısındaki değişim bu veriden okunamaz" sınırını koyuyor. → [doğrulanmalı], gündüz vardiyasında PDF açılabilirse kullanılabilir.
2. **"YÖK şu gerekçeyle kontenjan kıstı" tipi cümle kurulmadı.** YÖK duyurusu açılmadı; yazı yalnızca ölçülen değişimi anlatıyor.
3. **İstihdam/atama/KPSS ile ilgili tek cümle yok.** Öğretmenlik ve mühendislik satırları yalnızca taban hareketi olarak yazıldı (SEO planı #4'teki YMYL uyarısı bu yazı için de uygulandı).
4. **"2027'de şu olur" tahmini yok.** Yazı yön okumayı öğretiyor, gelecek tabanı hakkında tahmin vermiyor; yerleşme olasılığı/garanti dili kullanılmadı.
5. **İlköğretim Matematik Öğretmenliği'ndeki 2023→2024 sıçramasının nedeni yazılmadı.** Kontenjan açıklamıyor (−%7), kural değişikliği iddiası resmî kaynakla doğrulanamadı; yazı "elimizdeki veri neyin değiştiğini söylemiyor" diyor. → [doğrulanmalı].
6. **Tek vakıf programının üniversite adıyla örneklenmesi kaldırıldı** (S8 altındaki uyarı; burs kademesi isimde yok, aynı ad altında birden çok satır var).
---
## (e) Yazının biçim kontrolü
- Frontmatter: `baslik`, `aciklama` (tırnaksız), `tarih: 2026-09-22`. `src/lib/rehber.ts` parse kurallarına uygun.
- İlk paragraf "Kısa cevap:" ile başlıyor, tek başına cevap veriyor.
- **1 adet** ```mermaid `flowchart TD`; `%% aria:` ve `%% altyazi:` satırları var (regex ile doğrulandı). Renkli düğümlerin (`garanti`/`uyari`/`hayal` classDef) hepsinde metin etiketi var, renk tek başına anlam taşımıyor.
- **5 tablo** (istenen asgari 2). 9 adet soru biçimli H2.
- Yön her tabloda ayrı kolonda kelimeyle; ok/renk kullanılmadı.
- "Bu yazıdaki tablolar nasıl hesaplandı" kutusu (§0 zorunluluğu) ve erişim tarihli Kaynaklar var.
- İç linkler: `/rehber/taban-siralamalar-nasil-degisir`, `/rehber/taban-puan-mi-siralama-mi`, `/rehber/hedef-siralama-nasil-belirlenir`, `/rehber/bos-kontenjanlar-ne-anlatiyor`, `/rehber/tercih-listesi-nasil-yapilir`, `/rehber/olu-tercih-nedir`, `/rehber/siralama-sartlari-2026`, `/rehber/en-secici-devlet-universiteleri`, `/bolumler`, `/` ve 24 ayrı `/bolum/<slug>` linki. **Tümü doğrulandı:** rehber dosyaları `content/rehber/` altında var; bölüm slug'ları `src/lib/slug.ts`'teki `turkishSlugify(bolumBazAdi(...))` kuralıyla üretilip DB'deki `DISTINCT isim` kümesine karşı kontrol edildi (24/24 eşleşti). `/tercih-robotu` linki **kullanılmadı** (§0).
---
## Editöre not (`rehber-editoru`, benim yazımın dışı — düzeltmedim)
1. `content/rehber/taban-siralamalar-nasil-degisir.md` (ve en az 9 yazı daha) `/tercih-robotu` linki veriyor; `next.config.ts:80` bunu `/#hero-form`'a kalıcı yönlendiriyor. Ölü link değil ama gereksiz 301 — SEO planı §0 yeni yazılarda yasaklamış, eskiler temizlenmemiş.
2. Aynı yazıda "Bölüm sayfalarımızdaki tablolarda ... değişim yönü işareti (▲/▼)" deniyor. Bu gecenin kural setinde yön işaretinin tek başına anlam taşımaması isteniyor; bölüm sayfasındaki işaretin metin etiketi olup olmadığı kontrol edilmeli (koda bakmadım).
3. Psikoloji'yi "tabanı gerileyen bölüm" diye anan mevcut/yeni yazı olursa devlet kırılımıyla düzeltilmeli (yukarıdaki ⚠ notu).
---
## Bilal'den istenen
1. **Yayın öncesi 3 satır gözle doğrulansın:** Tarih, İlköğretim Matematik Öğretmenliği ve Hukuk için 2021 ve 2026 tabanları YÖK Atlas'ta bir programda kontrol edilsin (~10 dk).
2. **Karar:** ÖSYM aday sayısı PDF'i (indirme yasak olduğu için açılamadı) gündüz açılıp yazıya eklensin mi? (~5 dk)
3. Yok.

View File

@@ -0,0 +1,292 @@
# 18 — Yazar raporu: `kac-net-ile-hangi-bolum`
**Rol:** rehber-yazari · **Tarih:** 22 Eylül 2026 (gece vardiyası) · **Şartname:** `02-seo-konu-plani.md` §0 + §2 Dalga A #2
**Yazılan tek dosya:** `content/rehber/kac-net-ile-hangi-bolum.md` · Commit atılmadı, `git add` yapılmadı, başka dosyaya dokunulmadı.
---
## Özet (5 madde)
1. **Şartnamedeki en temel iddia yanlıştı ve düzeltildi.** SEO planı (§2 #2) ve görev brief'i `netler` tablosunu "yerleşenlerin gerçekte yaptığı netlerin **ortalaması**" diye tanımlıyor. Veri bunu desteklemiyor: bu tablo YÖK Atlas'ın **"son yerleşen kişinin netleri"** (Net Sihirbazı) verisidir — tek bir öğrencinin, taban puanı yapan kişinin profili. Üç bağımsız kanıt aşağıda. Yazı bu doğru tanımla kuruldu; "yerleşenlerin ortalaması" cümlesi yazının içinde açıkça **yanlış okuma** olarak işaretlendi.
2. **Rakamlar YÖK Atlas'ın canlı servisinden 5 programda alan alan doğrulandı** (Hacettepe Tıp, ODTÜ Bilgisayar Müh., Boğaziçi Bilgisayar Müh., Ankara Ü. Hukuk, İstanbul Ü. Psikoloji, Ege Ü. Hemşirelik — 6 program, 6/6 birebir tuttu). **Yayımlanabilir.**
3. **"2026 net verisi yok" iddiası doğrudan kaynaktan teyit edildi:** canlı API `yil DESC` sıralandığında en yeni kayıt 2025 (22 Eyl 2026, 03:40 civarı). Yazıda her net rakamının yanında yıl etiketi var; ayrı bir H2 "Neden 2026 netleri yok?" bunu okura anlatıyor.
4. **Vaat dili yok.** "Şu kadar net yaparsan girersin" cümlesi kurulmadı; tersine, üç ayrı bölüm (OBP, puan türü ağırlıkları, yılın sınav zorluğu) neden kurulamayacağını anlatıyor. `/rehber/obp-nedir-nasil-hesaplanir` ve `/rehber/taban-puan-mi-siralama-mi` bağlantıları istenen yerde.
5. **40 iç linkin 40'ı doğrulandı** (bölüm slug'ları `turkishSlugify(bolumBazAdi(isim))` ile DB'deki 634 slug havuzuna karşı, rehber linkleri `content/rehber/` dosya listesine karşı, `#hero-form` `src/app/page.tsx:241`'e karşı). `/tercih-robotu` kullanılmadı.
---
## 1. Şartname düzeltmesi: `netler` ne değildir
SEO planı §2 #2: *"bu rakamlar hedef değil, **yerleşenlerin gerçekte yaptığı netlerin ortalaması**"*. Bu tanım yanlış. Kanıtlar:
**(a) Kod zaten doğrusunu yazıyor.** `src/features/katalog/components/program-netleri.tsx:3-4` — *"YÖK Atlas'ın **'yerleşen son kişinin netleri'** verisini … gösterir"*. Aynı ifade `scripts/detay.ts:5` başlığında: *"A) Yerleşen son kişinin netleri"*.
**(b) Değerler tek kişiye ait.** Net = doğru − yanlış/4 olduğu için tek bir kişinin neti daima 0,25'in katıdır; yüzlerce kişinin ortalaması neredeyse hiç tam çeyreğe oturmaz.
```sql
SELECT COUNT(*) toplam,
SUM(CASE WHEN ABS(tytMatNet*4 - ROUND(tytMatNet*4)) < 1e-9 THEN 1 ELSE 0 END) ceyrek_katlari
FROM netler WHERE yil=2025 AND tytMatNet IS NOT NULL;
-- çıktı: 20821 | 20820 (%99,995)
```
**(c) Satırın taban puanı = programın taban puanı.** Yani satırın sahibi, o programın taban puanını yapan kişi = en son yerleşen.
```sql
SELECT COUNT(*) FROM netler n JOIN programs p ON p.id=n.program_id
WHERE n.yil=2025 AND ABS(n.tabanPuan - p.puan2025) < 0.0001; -- 17265
SELECT COUNT(*) FROM netler n JOIN programs p ON p.id=n.program_id
WHERE n.yil=2025 AND n.tabanPuan IS NOT NULL AND p.puan2025 IS NOT NULL; -- 17301
-- %99,8
```
`scripts/detay.ts:158-183` bu eşitliği zaten bir emniyet kilidi olarak kullanıyor (≥%95 tutmazsa betik duruyor).
**Sonuç:** Veri aslında *daha* kullanışlı — "ortalama" bölümü tanıtır, "son yerleşen" ise o yıl o programa en düşük hangi profille girilebildiğini söyler. Ama "eşik/baraj" diye satılamaz, çünkü tek kişilik bir gözlem ve yıldan yıla çok oynuyor. Yazı tam olarak bunu anlatıyor.
**Editöre not:** `02-seo-konu-plani.md` §2 #2'deki tanım ve "İlk paragraf cevabı" cümlesi düzeltilmeli; ayrıca §2 #15 (veli yazısı) aynı yanlış tanımı devralmasın. Ben o dosyaya dokunmadım.
---
## 2. Kullanılan SQL sorguları (tam metin)
Hepsi `sqlite3 -readonly /Users/bilalgursen/Desktop/kolaytercih/data/yokatlas.db` ile koşuldu.
### 2.1 Kapsam / kapsama kontrolü
```sql
SELECT yil, COUNT(*) FROM netler GROUP BY yil;
-- 2023|21341 2024|20813 2025|20821
SELECT COUNT(*) FROM netler; -- 62975
SELECT COUNT(DISTINCT program_id) FROM netler; -- 25166
SELECT COUNT(*) FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.onlisans=0 AND p.unitur='DEVLET' AND p.sira2025 IS NOT NULL; -- 5801
SELECT COUNT(DISTINCT p.isim) FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.onlisans=0 AND p.unitur='DEVLET' AND p.sira2025 IS NOT NULL; -- 409
```
### 2.2 Tablo 2 — SAY bölüm ortalamaları (yazıdaki ana tablo)
```sql
SELECT p.isim, COUNT(*) n,
ROUND(AVG(x.tytTrkNet),1) tyt_trk, ROUND(AVG(x.tytMatNet),1) tyt_mat,
ROUND(AVG(x.aytMatNet),1) ayt_mat,
ROUND(AVG(x.aytFizNet + x.aytKimNet + x.aytBioNet),1) ayt_fen,
CAST(AVG(p.sira2025) AS INT) s25
FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.onlisans=0 AND p.unitur='DEVLET' AND p.tur='SAYISAL'
AND p.sira2025 IS NOT NULL
AND p.isim IN ('Tıp','Diş Hekimliği','Eczacılık','Endüstri Mühendisliği',
'Bilgisayar Mühendisliği','Hemşirelik','Elektrik-Elektronik Mühendisliği',
'Yazılım Mühendisliği','Makine Mühendisliği','Veteriner','Mimarlık',
'İnşaat Mühendisliği','Beslenme ve Diyetetik','Fizyoterapi ve Rehabilitasyon',
'Moleküler Biyoloji ve Genetik')
GROUP BY p.isim ORDER BY s25 ASC;
```
Çıktı (yazıdaki tabloyla birebir):
```
isim n tyt_trk tyt_mat ayt_mat ayt_fen s25
Tıp 106 31.5 28.2 33.8 34.5 17237
Diş Hekimliği 75 30.2 25.5 30.9 31.9 31607
Eczacılık 36 29.1 24.4 29.2 29.6 44463
Endüstri Mühendisliği 64 28.6 21.0 22.0 23.8 111114
Bilgisayar Mühendisliği 114 27.9 19.4 20.7 23.2 120182
Hemşirelik 116 26.6 16.1 17.2 19.9 143896
Elektrik-Elektronik Mühendisliği 110 27.0 18.3 17.9 21.4 147235
Yazılım Mühendisliği 37 26.3 17.6 17.1 20.1 152171
Makine Mühendisliği 101 26.0 16.9 18.1 19.4 163481
Veteriner 34 26.7 16.0 17.1 21.4 164612
Mimarlık 57 27.3 16.3 15.9 18.2 165879
İnşaat Mühendisliği 95 25.8 14.9 14.3 16.1 206016
Fizyoterapi ve Rehabilitasyon 63 24.8 11.3 11.0 13.1 260335
Beslenme ve Diyetetik 65 25.5 12.8 10.5 11.3 271607
Moleküler Biyoloji ve Genetik 43 25.0 12.2 9.6 13.3 327838
```
### 2.3 Tablo 3 — EA / SÖZ / DİL
```sql
SELECT p.tur, p.isim, COUNT(*) n,
ROUND(AVG(x.tytTrkNet),1) tyt_trk, ROUND(AVG(x.tytMatNet),1) tyt_mat,
ROUND(AVG(x.aytMatNet),1) ayt_mat, ROUND(AVG(x.aytTdeNet),1) tde,
ROUND(AVG(x.aytTrh1Net + x.aytCog1Net),1) sos1,
ROUND(AVG(x.ydtYdilNet),1) ydt,
CAST(AVG(p.sira2025) AS INT) s25
FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.onlisans=0 AND p.unitur='DEVLET' AND p.sira2025 IS NOT NULL
AND p.isim IN ('Hukuk','Psikoloji','Rehberlik ve Psikolojik Danışmanlık',
'Sınıf Öğretmenliği','İşletme','İktisat','Uluslararası İlişkiler',
'Özel Eğitim Öğretmenliği','Okul Öncesi Öğretmenliği','Türkçe Öğretmenliği',
'Tarih','Türk Dili ve Edebiyatı','İngilizce Öğretmenliği',
'İngiliz Dili ve Edebiyatı','İlahiyat','Sosyal Hizmet')
GROUP BY p.tur, p.isim ORDER BY p.tur, s25 ASC;
```
Çıktı:
```
tur isim n trk tmat amat tde sos1 ydt s25
DİL İngilizce Öğretmenliği 66 29.3 8.2 - - - 64.5 20078
DİL İngiliz Dili ve Edebiyatı 60 28.0 4.8 - - - 56.7 32283
EA Hukuk 51 30.1 19.4 21.9 17.6 11.5 - 22999
EA Sınıf Öğretmenliği 75 28.0 13.8 12.8 16.3 9.1 - 94565
EA Psikoloji 72 28.8 12.8 12.0 16.7 9.0 - 126270
EA Rehberlik ve Psikolojik Danışmanlık 72 27.4 12.1 10.0 15.8 8.8 - 133579
EA Uluslararası İlişkiler 61 23.9 7.6 7.1 11.8 6.8 - 425022
EA İşletme 146 24.0 8.4 7.5 11.6 6.4 - 441022
EA Sosyal Hizmet 61 24.4 4.3 3.0 12.9 5.9 - 449096
EA İktisat 120 23.2 6.6 6.3 10.5 5.3 - 549489
SÖZ Özel Eğitim Öğretmenliği 54 29.4 5.3 - 18.4 12.4 - 9538
SÖZ Okul Öncesi Öğretmenliği 69 26.6 5.2 - 16.5 11.4 - 18849
SÖZ Türkçe Öğretmenliği 71 25.3 4.6 - 13.4 9.0 - 73366
SÖZ Türk Dili ve Edebiyatı 100 21.0 2.3 - 9.8 5.0 - 330169
SÖZ Tarih 107 20.1 2.6 - 8.2 6.4 - 365385
SÖZ İlahiyat 164 18.1 1.8 - 6.9 4.2 - 478545
```
### 2.4 Tablo 4 — aynı bölüm içinde bant dağılımı
```sql
SELECT CASE WHEN p.sira2025<=10000 THEN 'ilk 10 bin'
WHEN p.sira2025<=50000 THEN '10-50 bin'
WHEN p.sira2025<=150000 THEN '50-150 bin'
ELSE '150 bin ustu' END bant,
COUNT(*) n, ROUND(AVG(x.tytTrkNet),1), ROUND(AVG(x.tytMatNet),1),
ROUND(AVG(x.aytMatNet),1), ROUND(AVG(x.aytFizNet),1),
ROUND(AVG(x.aytKimNet),1), ROUND(AVG(x.aytBioNet),1)
FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.isim='Bilgisayar Mühendisliği' AND p.unitur='DEVLET'
AND p.onlisans=0 AND p.sira2025 IS NOT NULL
GROUP BY bant;
-- ilk 10 bin | 5 | 33.3 | 31.8 | 39.5 | 12.5 | 12.0 | 12.0
-- 10-50 bin | 18 | 31.9 | 25.4 | 31.1 | 10.6 | 11.3 | 10.0
-- 50-150 bin | 52 | 28.2 | 20.2 | 21.3 | 8.3 | 8.3 | 7.6
-- 150 bin ustu | 39 | 25.0 | 13.9 | 12.8 | 6.1 | 4.4 | 5.5
```
### 2.5 Tablo 5 — üç yıl eşleşmeli karşılaştırma
```sql
WITH uc AS (
SELECT program_id FROM netler WHERE yil IN (2023,2024,2025)
GROUP BY program_id HAVING COUNT(DISTINCT yil)=3
)
SELECT p.isim, COUNT(DISTINCT p.id) n,
ROUND(AVG(CASE WHEN x.yil=2023 THEN x.tytMatNet END),1) tm23,
ROUND(AVG(CASE WHEN x.yil=2024 THEN x.tytMatNet END),1) tm24,
ROUND(AVG(CASE WHEN x.yil=2025 THEN x.tytMatNet END),1) tm25,
ROUND(AVG(CASE WHEN x.yil=2023 THEN x.aytMatNet END),1) am23,
ROUND(AVG(CASE WHEN x.yil=2024 THEN x.aytMatNet END),1) am24,
ROUND(AVG(CASE WHEN x.yil=2025 THEN x.aytMatNet END),1) am25
FROM netler x JOIN programs p ON p.id=x.program_id JOIN uc ON uc.program_id=x.program_id
WHERE p.onlisans=0 AND p.unitur='DEVLET'
AND p.isim IN ('Tıp','Hukuk','Bilgisayar Mühendisliği','Psikoloji','Hemşirelik')
GROUP BY p.isim;
-- Tıp 102 | 34.6 34.9 28.4 | 35.1 29.6 33.8
-- Bilgisayar Mühendisliği 111 | 27.1 24.2 19.3 | 26.4 17.9 20.6
-- Hukuk 50 | 24.8 23.4 19.3 | 23.8 17.4 21.9
-- Hemşirelik 110 | 19.2 19.5 16.2 | 18.5 12.4 17.3
-- Psikoloji 62 | 17.8 15.7 12.5 | 15.7 9.9 12.0
```
Aynı CTE ile tüm devlet lisans kesiti (yazının en güçlü tek bulgusu):
```sql
-- ... aynı uc CTE ...
SELECT COUNT(DISTINCT p.id) n,
ROUND(AVG(CASE WHEN x.yil=2023 THEN x.tytMatNet END),1),
ROUND(AVG(CASE WHEN x.yil=2024 THEN x.tytMatNet END),1),
ROUND(AVG(CASE WHEN x.yil=2025 THEN x.tytMatNet END),1),
ROUND(AVG(CASE WHEN x.yil=2023 THEN x.tytTrkNet END),1),
ROUND(AVG(CASE WHEN x.yil=2024 THEN x.tytTrkNet END),1),
ROUND(AVG(CASE WHEN x.yil=2025 THEN x.tytTrkNet END),1)
FROM netler x JOIN programs p ON p.id=x.program_id JOIN uc ON uc.program_id=x.program_id
WHERE p.onlisans=0 AND p.unitur='DEVLET';
-- n=5213 | TYT Mat 13.6 → 12.5 → 9.9 | TYT Türkçe 24.0 → 24.3 → 24.6
```
### 2.6 OBP rakamları
```sql
SELECT COUNT(*), ROUND(AVG(x.obp),0) FROM netler x JOIN programs p ON p.id=x.program_id
WHERE x.yil=2025 AND p.onlisans=0 AND p.unitur='DEVLET' AND p.sira2025 IS NOT NULL;
-- 5801 | 411
-- aynı filtreyle: Tıp (n=106) 478 · Psikoloji (n=72) 433
```
### 2.7 Adlandırma kontrolü (tabloya girmeyen varyantlar)
```sql
SELECT isim, COUNT(*) FROM programs
WHERE unitur='DEVLET' AND onlisans=0 AND isim LIKE 'Bilgisayar Mühendisliği%' GROUP BY isim;
-- Bilgisayar Mühendisliği 125
-- Bilgisayar Mühendisliği (KKTC Uyruklu) 2
-- Bilgisayar Mühendisliği (İngilizce) 5
-- (İngilizce) (%50 İndirimli) 1
-- (İngilizce) (KKTC Uyruklu) 1
-- (İngilizce) (UOLP-Saraybosna) (%25 İndirimli) 3
```
`programs.isim` 2026 kılavuzundaki adı taşıyor (2.537 programın adında parantez var). ODTÜ ve Boğaziçi Bilgisayar Mühendisliği 2026'da düz adla geçiyor, bu yüzden tabloya giriyorlar. Bu kısıt yazının "nasıl hesaplandı" kutusunda açıkça yazılı.
---
## 3. YÖK Atlas gözle doğrulaması
YÖK Atlas 2026'da SPA'ya geçtiği için eski `lisans-panel.php` / `content/lisans-dynamic/*.php` panelleri artık HTML dönmüyor (hepsi boş React kabuğu; `scripts/detay.ts:27` bunu zaten not etmiş). `netler-tablo.php` ve `net-sihirbazi` sayfaları da SPA. Bu yüzden doğrulama **sitenin kendi canlı servisinden** (`POST /api/netler/search`, tarayıcıdaki Net Sihirbazı'nın çağırdığı uç) program program yapıldı. Değerler bugün (22 Eyl 2026) canlıdan çekildi ve `data/yokatlas.db` ile alan alan karşılaştırıldı.
| # | Program (kılavuz kodu) | Alan | Canlı YÖK Atlas (2025) | Bizim DB | Sonuç |
|---|---|---|---|---|---|
| 1 | Hacettepe Ü. Tıp (104810617) | tabanPuan / obp / TYT Trk / TYT Mat / AYT Mat / Fiz / Kim / Biyo | 530.58733 / 483.88 / 35,25 / 36,25 / 37,5 / 14,0 / 13,0 / 11,75 | aynı | ✅ birebir |
| 2 | ODTÜ Bilgisayar Müh. (İng.) (108410336) | tabanPuan / TYT Trk / TYT Mat / AYT Mat | 534.56656 / 32,25 / 32,25 / 40,0 | aynı | ✅ birebir |
| 3 | Boğaziçi Bilgisayar Müh. (İng.) (102210277) | tabanPuan / obp / TYT Trk / TYT Mat / AYT Mat / Fiz / Kim / Biyo | 533.05003 / 473.958 / 33,75 / 38,75 / 38,75 / 12,75 / 11,75 / 13,0 | aynı | ✅ birebir |
| 4 | Ankara Ü. Hukuk (101110518) | tabanPuan / obp / TYT Trk / TYT Mat / AYT Mat / TDE / Trh1 / Coğ1 | 461.84071 / 459.008 / 34,25 / 26,75 / 27,25 / 19,0 / 10,0 / 4,75 | aynı | ✅ birebir |
| 5 | İstanbul Ü. Psikoloji (105610255) | tabanPuan / obp / TYT Trk / TYT Mat / AYT Mat / TDE / Trh1 / Coğ1 | 417.22453 / 433.971 / 28,25 / 9,25 / 27,0 / 19,0 / 8,75 / 2,25 | aynı | ✅ birebir |
| 6 | Ege Ü. Hemşirelik (103410793) | tabanPuan / obp / TYT Trk / TYT Mat / AYT Mat / Fiz / Kim / Biyo | 400.41912 / 398.02 / 17,5 / 16,5 / 24,25 / 10,25 / 10,5 / 11,75 | aynı | ✅ birebir |
Ek olarak filtresiz ilk sayfadaki 4 kayıt (Medipol Tıp İng. Burslu 203110477, Koç Tıp İng. Burslu 203910699, Koç Tarih 203910187, Koç Ekonomi 203910275) da alan alan tuttu — **10/10**.
**2026 verisinin yokluğu doğrudan teyit edildi:**
```
POST /api/netler/search {"filters":{},"page":0,"size":3,"sortBy":"yil","direction":"DESC"}
→ totalElements: 63063 ; ilk 3 kaydın hepsi yil=2025
```
Yani canlı serviste en yeni net yılı 2025. (Bizde 62.975 satır var; canlıda 63.063 → %99,86 kapsama. Fark küçük, yazının hiçbir iddiasını etkilemiyor, ama veri mühendisine not.)
**Hüküm: YAYIMLANABİLİR.** Veri doğrulandı, editör notuna gerek yok.
---
## 4. Çıkarılan / yazılmayan iddialar
| İddia | Neden yazılmadı |
|---|---|
| "Şu kadar net yaparsan X bölümüne girersin" | Veri tek kişilik gözlem; ÖSYM net barajı yayımlamıyor. Yazı bunun yerine "en son yerleşenin profili" dilini kullanıyor. |
| "Yerleşenlerin ortalama neti" | Veri ortalama değil (bkz. §1). Yazıda bilerek **yanlış okuma** olarak işaretlendi. |
| 2026 net rakamı | YÖK Atlas yayımlamamış (canlı API ile teyit). "Açıklanmadı" diye yazıldı. |
| Vakıf üniversitesi net tablosu | Burslu/İndirimli/Ücretli varyantları bölüm adında ayrışıyor ve karşılaştırma yanıltıcı olurdu; SEO planı §1 bu kesiti zaten ayrı yazıya bırakmış. Kapsam DEVLET ile sınırlandı. |
| Önlisans (TYT) net tablosu | Kapsam dışı bırakıldı (yazı lisans odaklı); ayrı yazı konusu. |
| n < 10 olan bölümler | Tabloya alınmadı. Brief "5'ten az" diyordu, eşik 10'a çekildi (daha muhafazakâr). Tek istisna görünürdeki bant tablosunun "ilk 10 bin" satırı: n=5, satırın yanında açıkça yazıyor. |
| "Net → sıralama" dönüşüm tablosu | Resmî bir dönüşüm tablosu yok; kurumların tahmini tabloları kaynak gösterilemezdi. Yazı yalnızca "denemeni sıralamaya çevir" diyor, rakam vermiyor. |
---
## 5. Engeller ve veri kalitesi notları (editör / veri mühendisi için)
1. **SEO planı §2 #2'deki tanım hatalı** (bkz. §1). `02-seo-konu-plani.md` düzeltilmeli; aynı hatayı devralabilecek konu: §2 #15 (veli yazısı, "net tablosu tekrarlamaz ama tek örnek verir").
2. **Brief'in "netler tablosu sitede hiçbir yerde kullanılmadı" varsayımı yanlış.** Tablo zaten katalogda ve liste ekranında kullanılıyor: `src/app/api/netler/route.ts`, `src/features/katalog/components/program-netleri.tsx` (program satırındaki "netler" butonu → modal), `universite-program-tablosu.tsx:114`, `bolum-program-listesi.tsx:262`, `liste/components/program-tablosu.tsx:387`. **Yazıda kullanılmamıştı**, doğrusu bu. Fark önemli, çünkü modal zaten "son yerleşen kişi" dilini kullanıyor; yazı onunla tutarlı.
3. **Şüpheli program kayıtları (veri kalitesi).** Bölüm içi uç değer taramasında `fakulte` alanı bölümle uyuşmayan kayıtlar çıktı — ör. `108411025` ORTA DOĞU TEKNİK ÜNİVERSİTESİ / isim "Psikoloji" / fakülte **"Mühendislik Fakültesi"** / `sira2025 = 750343`; benzer şekilde `108410857` ODTÜ "Bilgisayar Mühendisliği" / Mühendislik Fakültesi / `sira2025 = 252139`. Bunlar büyük olasılıkla KKTC uyruklu / özel kontenjan satırları ama adlarında ek taşımıyor. **Yazıda hiçbiri tek tek anılmadı**; yalnızca 72 ve 114 programlık ortalamaların içinde kaldılar (etkileri ihmal edilebilir). `veri-muhendisi`'ne bakması için not.
4. **Kapsama farkı:** canlı API 63.063 satır, bizde 62.975 (88 satır eksik, %0,14). Sebebi incelenmedi.
5. **Disk:** vardiya sırasında makinenin kök diski doldu (`/` %100, ~117 MB boş); iki komut `ENOSPC` ile düştü ve tekrar denenerek aşıldı. Orkestratöre not.
---
## Bilal'den istenen (yayın öncesi kontrol)
1. **Terminoloji onayı:** Yazı, YÖK Atlas net verisini "yerleşenlerin ortalaması" değil **"o programa en son yerleşen kişinin neti"** diye anlatıyor (kanıtlar raporda). Bu dil ürünün her yerinde aynı kalmalı — onaylıyor musun? (~5 dk)
2. **Tablo genişliği:** Sayısal tablosu 7, EA/SÖZ/DİL tablosu 10 kolon. Mobilde yatay kayan `rehber-tablo` sarmalayıcısına giriyor ama bir göz atman iyi olur. (~3 dk)
3. **Güncelleme tetiği:** YÖK Atlas 2026 netlerini yayımladığında bu yazı ve tabloları yenilenmeli; backlog'a "2026 netleri gelince `kac-net-ile-hangi-bolum` güncelle" kalemi açılsın mı? (~2 dk)

View File

@@ -0,0 +1,115 @@
# 19 — Rehber yazarı: `yapay-zekaya-tercih-sordum-guvenilir-mi`
**Rol:** rehber-yazari · **Şartname:** `02-seo-konu-plani.md` §0 + §2 Dalga E konu 19 · **Dosya:** `content/rehber/yapay-zekaya-tercih-sordum-guvenilir-mi.md` (2.851 kelime, commit'lenmedi)
## Özet (5 madde)
1. Yazı iddia etmiyor, **gösteriyor**: genel sohbet botunun dört yapısal hata mekanizması (kesme tarihi, olmayan program–üniversite eşleşmesi, kapanmış/kod değişmiş program, eskimiş kontenjan-koşul) her biri kendi DB rakamıyla kanıtlanmış hâlde anlatıldı. "Yapay zekâ yanlış yapar" cümlesi tek başına hiçbir yerde geçmiyor.
2. **Kendi testimiz yapıldı ve yazıya girdi** ama bir sohbet botuna değil, botun okuduğu kaynağa: 22 Eyl 2026'da "Boğaziçi Bilgisayar Mühendisliği 2026 taban puanı" araması yapıldı; başlığında 2026 yazan sayfalar taban sırası **1.448** / puan **533,05003** gösteriyordu — bunlar bizim DB'mizdeki **2025** değerleriyle birebir aynı. DB'deki gerçek 2026: **4.560 / 526,75435**. Rakip/site adı verilmedi, gözlem "sayfa türü"ne bağlandı.
3. `/meraklisina` şemasıyla **satır satır** eşleştirildi (aşağıda tablo). Çelişen tek cümle bulunmadı; yazıdaki "Bizim yaklaşımımız" bölümü şemanın altı düğümünü sırasıyla tekrarlıyor, fazladan hiçbir yetenek iddia etmiyor.
4. Marka bölümü **ölçülü**: "kapattığı 3 hata türü" ve "kapatmadığı 4 şey" ayrı ayrı listelendi; `riskHesapla`'nın determinist olduğu ve **yerleşme olasılığı hesaplanmadığı** açıkça yazıldı (`src/lib/risk.ts:71-76` yorumuyla uyumlu). Vaat dili yok.
5. Üç iddia kanıtlanamadığı için **çıkarıldı** (madde "Yazılmayan iddialar").
## /meraklisina şemasıyla uyum doğrulaması (satır satır)
Kaynak: `src/features/pazarlama/components/huni-semasi.tsx` `SEMA` + `src/features/pazarlama/components/meraklisina-icerik.tsx` §4 + `src/lib/risk.ts`.
| Şema düğümü / kural | Yazıdaki karşılığı | Durum |
|---|---|---|
| `T` "Sıralamanla açılan tüm programlar" | Madde 1: "Sıralamanı girdiğinde o sıralamayla açılan gerçek programlar listelenir" | uyumlu |
| `A` alan — "adına ve bağlı olduğu fakülteye göre" | Madde 2, aynı ifadeyle | uyumlu |
| `B` il — "programı olan tüm iller, seçtiğin alanlardaki program sayısına göre yeniden sayılır" | Madde 2, aynı ifadeyle | uyumlu |
| `C` devlet/vakıf — "sayılar hem alanı hem ili hesaba katar" | Madde 2, aynı ifadeyle | uyumlu |
| `H` havuz — "yalnızca en son tercih kılavuzunda yer alanlar; kapanan ya da kodu değişip eski kaydı kalan önerilmez" | Madde 3, aynı ifadeyle | uyumlu |
| `S`/`G` — 24'ün altına düşerse "önce il, sonra alan" gevşetilir, listede belirtilir | Madde 4, sıra dahil aynı | uyumlu |
| `U` — havuz dar kalırsa liste eldekiyle kurulur, dağılım uyarlanır, açıkça söylenir | Madde 4, ikinci cümle | uyumlu |
| `Y` — "en fazla 24 tercih seçer, havuzda olmayan bölümü yazamaz, her satıra gerekçe yazar" | Madde 5, aynı üç unsur | uyumlu |
| `R` — "risk notu ve trend gerçek sıralama geçmişinden, yapay zekâ yorumu değildir" | Madde 6 + "kapattığı hatalar" 3. madde | uyumlu |
| `L1/L2/L3` — hayal 5 / dengeli 13 / **güvenli** 6, "havuz elverdiğince" | Madde 6: "5 / 13 / 6, havuz elverdiğince"; görünen ad **Güvenli** (`DILIM_ETIKET`), "garanti" kelimesi yazıda hiç geçmiyor | uyumlu |
| `riskHesapla` determinist, olasılık yok (`src/lib/risk.ts:71`) | Tablonun "Olasılık" satırı + "Kapatmadığı şeyler" 1. maddesi: "ürün yerleşme olasılığı hesaplamaz" | uyumlu |
| Koşul filtresi **yok** (koddan çıkarım: `risk.ts`/`rapor` içinde koşul geçmiyor) | "Kapatmadığı şeyler" 2. maddesi: özel koşulları senin durumunla eşleştirmiyoruz | uyumlu, eksiklik açıkça yazıldı |
Biçim kontrolü: 1 `flowchart TD`, `%% aria:` + `%% altyazi:` var, 2 tablo, H2'ler soru biçiminde, "Kaynaklar" + erişim tarihi (22 Eyl 2026), slug'da yıl yok, frontmatter yalnız `baslik`/`aciklama`/`tarih`, `aciklama` tırnaksız. Renk sınıfları ürünün risk diliyle aynı; **her düğümün ilk satırında büyük harfli metin etiketi** var, renk tek başına anlam taşımıyor. `/tercih-robotu`'na link verilmedi.
## Kullanılan SQL sorguları (hepsi `sqlite3 -readonly data/yokatlas.db`)
```sql
-- 1) Bir yıllık taban oynaması (9.160 program, medyan %14,9; >%20: 2.877; >%50: 297)
WITH t AS (SELECT ABS(sira2026-sira2025)*100.0/sira2025 d FROM programs
WHERE onlisans=0 AND sira2025 IS NOT NULL AND sira2025>0 AND sira2026 IS NOT NULL)
SELECT COUNT(*), ROUND((SELECT d FROM t ORDER BY d LIMIT 1 OFFSET (SELECT COUNT(*)/2 FROM t)),1),
SUM(CASE WHEN d>20 THEN 1 ELSE 0 END), SUM(CASE WHEN d>50 THEN 1 ELSE 0 END) FROM t;
-- 2) İlk 100 bin bandı (3.034 program, medyan 4.014 sıra; >10.000: 686)
WITH t AS (SELECT ABS(sira2026-sira2025) d FROM programs
WHERE onlisans=0 AND sira2025 IS NOT NULL AND sira2025<=100000 AND sira2026 IS NOT NULL)
SELECT COUNT(*), (SELECT d FROM t ORDER BY d LIMIT 1 OFFSET (SELECT COUNT(*)/2 FROM t)),
SUM(CASE WHEN d>10000 THEN 1 ELSE 0 END) FROM t;
-- 3) Kılavuzdan düşen lisans programları (572 program, 11.587 yerleşen)
SELECT COUNT(*), SUM(yerlesen2025) FROM programs_arsiv
WHERE onlisans=0 AND yerlesen2025>0
AND id NOT IN (SELECT eski_kod FROM programs WHERE eski_kod IS NOT NULL);
-- 4) Kodu değişen program sayısı (466)
SELECT COUNT(*) FROM programs WHERE eski_kod IS NOT NULL;
-- 5) Kontenjan değişimi (11.540 karşılaştırılabilir; 5.192 değişti, 3.907 azaldı)
SELECT COUNT(*), SUM(kontenjan2026<>kontenjan2025), SUM(kontenjan2026<kontenjan2025)
FROM programs WHERE onlisans=0 AND kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL;
-- 6) Envanter (21.493 = 12.239 lisans + 9.254 önlisans) ve kapsama
SELECT onlisans, son_kilavuz_yili, COUNT(*) FROM programs GROUP BY 1,2;
SELECT COUNT(*) FROM programs WHERE onlisans=0 AND isim LIKE 'Psikoloji%'; -- 355
SELECT COUNT(DISTINCT universite) FROM programs WHERE onlisans=0 AND isim LIKE 'Psikoloji%'; -- 155
SELECT COUNT(DISTINCT universite) FROM programs; -- 322
-- 7) Boğaziçi Bilgisayar Mühendisliği (tek satır, id 102210277)
SELECT sira2023, sira2024, sira2025, sira2026, puan2026 FROM programs
WHERE universite='BOĞAZİÇİ ÜNİVERSİTESİ' AND isim LIKE '%Bilgisayar Mühendisliği%' AND onlisans=0;
-- 775 | 1006 | 1448 | 4560 | 526.75435
```
Veri tarihi: `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z`, `refresh_2026_api_toplam = 21493`, `refresh_2026_atlanan = 0`. `programs_arsiv` semantiği `scripts/eski-arsivle.ts:1-6` başlığından doğrulandı (güncel kılavuzda olmayan programlar taşınıyor, silinmiyor).
## Doğrulanan bilgiler + kaynak URL'leri (erişim 22 Eyl 2026)
- ÖSYM 2026 kılavuz sayfası, **Tablo-3 (önlisans) ve Tablo-4 (lisans)** ayrı indirilebilir dosyalar olarak listeleniyor — https://www.osym.gov.tr/2026-yuksekogretim-kurumlari-sinavi-yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzu (sayfa açıldı, bağlantı adları teyit edildi)
- Kılavuz duyurusu **21 Temmuz 2026**, "21–28 Temmuz 2026 arasında yayımlanacaktır" ve "tercihten önce nihai kılavuzu kontrol edin" uyarısı — https://www.osym.gov.tr/2026yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzunun-yayimlanmasi
- 2026-YKS yerleştirme sonuçları **18 Ağustos 2026** — https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi (aynı kaynak `en-secici-devlet-universiteleri.md` yazısında da kullanılmış, tutarlı)
- YÖK Atlas ve tercih sihirbazı adresleri — https://yokatlas.yok.gov.tr , `tercih-sihirbazi-t4.php`, `tercih-sihirbazi-t3.php` (bağlantılar arama sonucundan teyit; sayfa JS ile render olduğu için içerik WebFetch ile okunamadı)
- **Kendi testimiz:** "Boğaziçi Üniversitesi Bilgisayar Mühendisliği 2026 taban puan başarı sıralaması" araması — başlığı 2026 olan sayfalarda 1.448 / 533,05003; DB'mizdeki `sira2025` ile birebir aynı. Bağımsız bir kaynak (2026 verisi olan bir sayfa) 1.448 → 4.560 geçişini doğruluyor, bizim `sira2026` ile örtüşüyor. **Kanıt seviyesi:** DB tarafı [D], arama tarafı [A] (arama özeti üzerinden; sayfalar tek tek açılmadı).
## Çıkarılan / yazılmayan iddialar
1. **Adı verilen bir sohbet botuna yapılan test.** Ortamda üçüncü taraf sohbet botuna erişim yok; "X modeli şu sayıyı verdi" tipi hiçbir cümle yazılmadı. Şartnamedeki "test yapılamazsa bu bölüm yazıdan çıkar" kuralı yerine, **kanıtlanabilir** bir ikame test yapıldı (botların okuduğu kaynak). Bu, yazıda da açıkça söyleniyor: "Bir sohbet botunu adıyla test edip aktarmadık."
2. **"Model şöyle der" tahmini.** İlk taslakta "eğitim verisi 2023'te biten bir model 'yaklaşık 800' der" cümlesi vardı; test edilemediği için mekanizmaya çevrildi ("elindeki en yeni sayı 775 olur").
3. **"572 program kapandı."** Arşiv tablosu "bu yılın kılavuzunda aynı kodla bulunmayan" demek; kod değişip eşleşmesi kurulamayan programlar da içinde olabilir. Yazıda "kapanan program sayısı değildir" uyarısıyla birlikte verildi.
4. **Aynı üniversitede aynı bölümün birden çok satırı.** Hacettepe Tıp örneği (3 satır: 1.586 / 965 / 34.181) güçlü bir örnekti ama açıklaması SEO planı §3'te "şimdi yazılmaz" (veri sorusu `veri-muhendisi`'nde açık). Örnek **kullanılmadı**, tek satırlı Boğaziçi programıyla değiştirildi.
5. **Özel koşulu ürünün süzdüğü iddiası.** `src/lib/risk.ts` ve rapor tarafında koşul filtresi yok [koddan çıkarım]; yazı bunu eksiklik olarak açıkça yazıyor ve kullanıcıyı kılavuza + `siralama-sartlari-2026`'ya yolluyor.
6. **Yerleşme olasılığı / garanti dili.** Hiç kullanılmadı; tabloda "Olasılık: kimse yapamaz" satırı var ve altında "bu yazının sahibi olan ürün de dahil" deniyor.
## İç linkler (hepsi hedefi doğrulanarak eklendi)
`/meraklisina` (`src/app/meraklisina`) · `/bolumler` · `/bolum/bilgisayar-muhendisligi` (3 mevcut yazıda kullanımda) · `/` · `/rehber/tercih-robotu-nedir-yok-atlas-nasil-kullanilir` · `/rehber/tercih-listesi-nasil-yapilir` · `/rehber/taban-siralamalar-nasil-degisir` · `/rehber/olu-tercih-nedir` · `/rehber/taban-puan-mi-siralama-mi` · `/rehber/siralama-sartlari-2026` — hepsinin `content/rehber/*.md` ya da `src/app` karşılığı var. `/tercih-robotu` (301) **kullanılmadı**.
## Engeller
- **Sohbet botu testi yapılamadı** (ortamda üçüncü taraf model erişimi yok) → ikame test uygulandı, yazıda şeffaf.
- **YÖK Atlas program sayfası WebFetch ile okunamadı** (JS render). 2026 rakamı yalnızca kendi DB'mizden + arama sonucu çapraz kontrolünden doğrulandı.
- **Mermaid şeması tarayıcıda render edilmedi** (AGENTS.md: tarayıcı/dev sunucu açma yasak). `mermaid.parse` Node'da DOM olmadığı için çalışmadı. Sözdizimi mevcut çalışan yazılarla (ör. `kyk-burs-mu-kredi-mi.md`) **biçimsel olarak birebir** aynı kalıpta — düğüm/kenar/`classDef` formları eşleştirilerek doğrulandı [koddan çıkarım].
- Çalışma ağacında 9 paralel yazar dosyası daha var; hiçbirine dokunulmadı.
## Diğer yazarlara / editöre not
- **Tutarlılık riski:** `kapanan/kod değişen program` rakamları (572 / 11.587 / 466) bu yazıda ilk kez kullanıldı. `yeni-acilan-bolumler-nasil-degerlendirilir` ve `olu-tercih-nedir` aynı kesite dokunursa `rehber-editoru` iki yazıyı aynı sorgudan hizalasın.
- `tercih-robotu-nedir-yok-atlas-nasil-kullanilir` yazısında "Kılavuzdaki özel koşulları ve sıralama şartlarını süzgece dahil etmek" bir *iyi robot özelliği* olarak sayılıyor. Bizim ürünümüzde koşul filtresi yok; o cümle "iyi robot" genel tanımı olduğu için doğrudan çelişki değil ama **okur ürünün koşul süzdüğünü sanabilir**. Editör o paragrafa "KolayTercih'te koşulu sen okursun" notu düşmeyi değerlendirsin — ben o dosyaya dokunmadım.
## Marka / CEO'ya not
Kurucunun "yapay zekâ ile insan arasında" çerçevesi yazının **kapanış bölümünde üç merciye** çevrildi: veriye sor (sayı) · yapay zekâya sor (yorum) · insana sor (istek, bütçe, hayat). Bu üçlü, `/meraklisina`'daki "sihirbaz süzer, yapay zekâ kurar, karar senin" anlatısının rehber tarafındaki karşılığı ve reklam yapmadan konumu gösteriyor. Ürün tarafında bunu güçlendirecek ucuz bir hamle var: **liste çıktısının altına "bu satırları kılavuzdan doğrula" 4 maddelik mikro kontrol listesi** koymak — yazıdaki tabloyla birebir aynı, ürün içinde hiç yok. Backlog önerisi olarak `urun-yoneticisi`'ne bırakıyorum.
## Bilal'den istenen
1. Yazının marka bölümündeki "kapatır / kapatmaz" ayrımının tonunu onayla — dürüstlük dozu bilerek yüksek tutuldu (5 dk okuma).
2. Karar: liste çıktısının altına "kılavuzdan doğrula" 4 maddelik mikro kontrol listesi eklensin mi? (2 dk karar)

View File

@@ -0,0 +1,438 @@
# 20 — Rehber editör denetimi: 10 yeni yazı (gece vardiyası, 22 Eylül 2026)
Rol: `rehber-editoru` · Kapsam: `content/rehber/` altındaki 10 yeni yazı. `src/` altına, `veliler-icin-tercih-rehberi.md`'ye ve Bilal'in commit'lenmemiş dosyalarına **dokunulmadı**. Commit atılmadı, `git add` yapılmadı.
Ölçü: `05-ceo-kararlari.md` §C(d) — altı maddelik "yayımlanmaz" eşiği.
İşaret: **[D]** bu gece kendim koştum · **[A]** yalnız ikincil kaynak/arama özeti · **[K]** kaynak açılamadı.
---
## Özet (5 madde)
1. **CEO'nun dört "tutmuyor" bulgusunun üçü aslında yazarın haklı olduğu, ama yöntem cümlesinin rakamı üretmeye yetmediği durumlardı.** `bilgisayar…` 56/54 ✔ (ODTÜ hariç sayım — yazı bunu rakamın yanında söylemiyordu), `siralama-bandlari…` 9.304/271/81 ✔ (kirli `il` filtresi yazılı değildi), `kac-net…` Hukuk 30,1 (51) ve Psikoloji 28,8 (72) ✔ (CEO `sira2025 IS NOT NULL` koşulunu uygulamamış — koşul yazının yöntem kutusunda zaten yazılıydı). Üçünde de **rakam değil yöntem cümlesi düzeltildi**, farkın kaynağı ve alternatif sayım yazıya kondu.
2. **`kktc…` gerçek bir düzeltme aldı:** "toplamlarımız ÖSYM ile birebir aynı" iddiası **çıkarıldı** (ÖSYM'nin sayısal bilgiler PDF'ini açamadım, dosya indirme yasak — doğrulayamadığım iddia daha iddialı hâlde bırakılamaz), yerine KKTC havuzunun tam tanımı ve CEO'nun gördüğü 12.912/7.849 · 4.637/3.537 farkının kaynağı (Kıbrıs Amerikan Ü.'nün `unitur='DEVLET'` etiketli 42 satırı) yazıldı. 16 ↔ 25 ayrı `universite` değeri ayrımı da kutuya girdi.
3. **Kimsenin yakalamadığı iki hata bulundu ve düzeltildi:** (a) `kktc…`'de çeyreklik yönü ters yazılmıştı ("dörtte biri 143.099'un üstünde" → doğrusu "143.099'dan daha sıkı"); (b) aynı yazıda bölüm medyanı tablosunun altyazısı havuzu **yanlış** tarif ediyordu ("kontenjanı dolan programlar" → gerçek filtre "2026 tabanı oluşan programlar"; doluluk koşulu uygulansa Psikoloji devlet medyanı 97.977 değil 102.614 çıkıyordu).
4. **Kalan altı yazıda örnekleme değil, bulabildiğim her DB rakamını yeniden koştum: 60'tan fazla rakamın tamamı tuttu.** `taban-siralamalari-alti-yilda` ve `siralama-bandlari`'nın iki tam tablosu hücre hücre birebir çıktı. Tek düzeltme yöntem kutularına eklenen filtre netliği (`unitur` değerleri, `onlisans=0`).
5. **Ölü link taraması: 42 yazının tamamında 682 iç link tarandı, 0 kırık hedef.** Tek sorun `/tercih-robotu` (301 kalıcı yönlendirme) — 32 geçişin 4'ü benim 10 yazımdaydı, düzeltildi; **kalan 28'i mevcut yazılarda ve kapsamım dışında** (aşağıda Bilal'e istenen). Ayrıca 10 yazı arasında **sıfır** çapraz link vardı; 13 doğal çapraz link eklendi.
---
## (a) Düzeltilen / doğrulanan rakamlar
Tüm sorgular `sqlite3 -readonly data/yokatlas.db` ile bu gece koşuldu (`veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z`).
### A1. Rakamı doğru çıkan ama yöntemi rakamı üretmeyen üç satır (CEO'nun listesi)
| Yazı | Yazıdaki değer | Benim koşum | Hüküm | Yapılan |
|---|---|---|---|---|
| `bilgisayar-mi-yazilim…:7,14,20,66,120` | 56 üniversitenin 54'ü | **56/54** (ODTÜ hariç) · **57/55** (ODTÜ dahil) | Yazı **doğru**, filtre eksik yazılmış | Rakamın geçtiği 4 yere ODTÜ istisnası kondu + yöntem kutusu eklendi |
| `siralama-bandlari…:7,66` | 9.304 program / 271 üni / 81 il | **9.304 / 271 / 81** (kirli `il` hariç) · **9.408 / 276 / 84** (`il` filtresi yok) | Yazı **doğru**, `il` temizliği yazılı değildi | "Dışarıda" listesine 104 satırlık fark satır satır yazıldı |
| `kac-net…:7` Hukuk | 30,1 / 19,4 / 21,9 (51) | **30,1 / 19,4 / 21,9 (51)** | Yazı **doğru** | Yöntem kutusuna "bu koşulu atlarsan 52 program ve 29,9 çıkar" notu |
| `kac-net…:7` Psikoloji | 28,8 / 12,8 / 12,0 (72) | **28,8 / 12,8 / 12,0 (72)** | Yazı **doğru** | (aynı kutu) |
**`bilgisayar…` sorgusu** (ODTÜ satırı çıkarılınca 56, çıkarılmayınca 57):
```sql
WITH t AS (SELECT universite, unitur,
CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'bm' ELSE 'ym' END b, sira2026
FROM programs
WHERE (isim LIKE 'Bilgisayar Mühendisliği%' OR isim LIKE 'Yazılım Mühendisliği%')
AND onlisans=0 AND unitur IN ('DEVLET','VAKIF')
AND isim NOT LIKE '%KKTC Uyruklu%' AND sira2026 IS NOT NULL
AND universite <> 'ORTA DOĞU TEKNİK ÜNİVERSİTESİ'), -- bu satır 57→56 yapıyor
u AS (SELECT universite, unitur, MIN(CASE WHEN b='bm' THEN sira2026 END) bm,
MIN(CASE WHEN b='ym' THEN sira2026 END) ym FROM t GROUP BY universite, unitur)
SELECT unitur, COUNT(*), SUM(bm<ym), SUM(ym<bm) FROM u WHERE bm IS NOT NULL AND ym IS NOT NULL GROUP BY unitur;
-- ODTÜ hariç: DEVLET 23/21/2 · VAKIF 33/33/0 → 56/54 ✔ (ortanca fark 19.550 ✔)
-- ODTÜ dahil: DEVLET 24/22/2 · VAKIF 33/33/0 → 57/55
```
ODTÜ'nün neden sayılamadığı doğrulandı: aynı `universite` adı altında BM (2.989) + BM (96.050) + YM (299.241/293.024) duruyor, yani Ankara ve Kuzey Kıbrıs kampüsleri ayrışmıyor. [D]
**`siralama-bandlari` sorgusu** (fark 104 satır = 61 açıköğretim + 9 boş `il` + 34 KKTC/Bosna `il`):
```sql
WITH baz AS (SELECT *, lower(COALESCE(fakulte,'')) fk, lower(isim) ik FROM programs
WHERE onlisans=0 AND unitur IN ('DEVLET','VAKIF') AND sira2026 IS NOT NULL
AND isim NOT LIKE '%KKTC Uyruklu%'
AND il IS NOT NULL AND il <> ''
AND il NOT IN ('KIBRIS','LEFKOŞA','GİRNE','GAZİMAĞUSA','LEFKE','GÜZELYURT','İSKELE','SARAYBOSNA - BOSNA - HERSEK')),
p AS (SELECT * FROM baz WHERE NOT (fk LIKE '%açık%' OR fk LIKE '%uzaktan%' OR ik LIKE '%açıköğretim%' OR ik LIKE '%uzaktan%'))
SELECT COUNT(*), COUNT(DISTINCT universite), COUNT(DISTINCT il), SUM(unitur='DEVLET'), SUM(unitur='VAKIF'), SUM(COALESCE(kontenjan2026,0)) FROM p;
-- 9304 | 271 | 81 | 5865 | 3439 | 312283 ✔ (yazının toplam satırıyla birebir)
```
Sekiz bandın **her hücresi** ayrıca yeniden koşuldu (program/üni/il/devlet/vakıf/kontenjan + 3 büyük şehir yüzdesi): 8×7 = 56 hücre, **tamamı tuttu**. Kapı sayıları da: `sira2026>=100000` → 6.076 ✔, `>=500000` → 1.489 ✔. Açıköğretim satırı: 61 program / 5 üniversite / 22.484–1.202.899 ✔. "81 ilin tamamı" iddiası da doğrulandı — havuzdaki 81 `il` değeri Türkiye'nin 81 ilinin tamamı. [D]
**`kac-net` sorgusu** (CEO'nun sapmasının tek kaynağı `sira2025 IS NOT NULL`):
```sql
SELECT p.isim, COUNT(*) n, ROUND(AVG(n2.tytTrkNet),1), ROUND(AVG(n2.tytMatNet),1), ROUND(AVG(n2.aytMatNet),1)
FROM programs p JOIN netler n2 ON n2.program_id=p.id AND n2.yil=2025
WHERE p.unitur='DEVLET' AND p.onlisans=0 AND p.sira2025 IS NOT NULL
AND p.isim IN ('Tıp','Diş Hekimliği','Hukuk','Bilgisayar Mühendisliği','Hemşirelik','Psikoloji') GROUP BY 1;
-- Tıp 106|31,5|28,2|33,8 ✔ · Diş 75|30,2|25,5|30,9 ✔ · Hukuk 51|30,1|19,4|21,9 ✔
-- Bilg.Müh. 114|27,9|19,4|20,7 ✔ · Hemşirelik 116|26,6|16,1|17,2 ✔ · Psikoloji 72|28,8|12,8|12,0 ✔
-- sira2025 koşulu kaldırılırsa: Hukuk 52|29,9|19,2|21,8 · Psikoloji 75|28,0|12,2|11,5 ← CEO'nun koşumu
```
Ayrıca doğrulandı: 3 yıllık kohort 5.213 program, TYT Mat 13,6→12,5→9,9, TYT Türkçe 24,0→24,3→24,6 ✔; 2025 `netler` 20.821 satırın 20.820'si çeyrek katı ✔; OBP 411 / Tıp 478 / Psikoloji 433 ✔; kesit 5.801 program, 409 bölüm adı ✔. [D]
Not: 3 yıllık tabloda `sira2025` koşulu **aranmıyor** (5.213 ≠ 5.068). Yöntem kutusu bunu artık açıkça söylüyor.
### A2. Gerçekten düzeltilen rakamlar ve iddialar
| Yazı:satır | Eski | Yeni | Sorgu / gerekçe |
|---|---|---|---|
| `kktc…` Kaynaklar | "Lisans ve önlisans toplamlarımız ÖSYM'nin kurum grubu rakamlarıyla **birebir aynı**" | İddia **çıkarıldı**; yerine havuz tanımı | ÖSYM'nin sayısal bilgiler dosyası PDF; sayfada rakam yok, indirme yasak → **teyit edilemedi** [K] |
| `kktc…` taban bandı | "Dörtte biri 143.099'un **üstünde**, dörtte biri 774.369'un **altında**" | "143.099'dan daha **sıkı**, 774.369'dan daha **geniş**" | Q1=143.099, Q3=774.369 (n=395, medyan 339.153) — cümle çeyrekleri ters okuyordu [D] |
| `kktc…` medyan tablosu altyazısı | "(2026, **kontenjanı dolan** programlar)" | "(2026'da **taban sıralaması oluşan** lisans programları; burs/dil varyantları aynı ad altında)" | Doluluk koşulu eklenince Psikoloji devlet 97.977 → **102.614** çıkıyor; yazının rakamı doluluk **koşulsuz** sorgudan geliyor [D] |
| `kktc…:75` | "katalog verimizde de 2026'da kontenjan açan üniversite sayısı 16" | "…ad temizliğinden sonra 16" + kutuda ham 25 / normalize 16 ayrımı | `SELECT COUNT(DISTINCT universite) …` → ham **25**; `(KKTC-ŞEHİR)` ekleri atılınca **16** [D] |
| `kktc…:7` | "aynı ekranda **yerleşirsin**" | "aynı ekranda **yerleştirme yapılır**" | CEO eşiği md. 4 — vaat dili tek geçişte bile çıkar |
| `yeni-acilan…` yöntem | "devlet ve vakıf üniversitelerinin programları" | `unitur` değerleri açık: DEVLET, VAKIF, **VAKIF MYO** | Yalnız ilk ikisiyle yeni program 930 değil **895**, tabanlı 697 değil **673** çıkıyor [D] |
### A3. Örnekleme ile doğrulanan, düzeltme gerektirmeyen rakamlar
| Yazı | Yeniden koşulan | Sonuç |
|---|---|---|
| `taban-siralamalari-alti-yilda` | 12.239 lisans / 5.461 eşleşen / 4.461 / 398; 3.774 küçüldü, 1.687 büyüdü; ort. 167.067→145.356; kontenjan 255.090→204.714 ve 376.842→393.294; Tarih 64 (276.363→120.510), İktisat 51, İşletme 126, İlk.Mat.Öğrt. 76, Psikoloji 184, Yazılım Müh. 51 + "aynı yöne giden program" kolonları | **hepsi birebir** [D] |
| `yeni-acilan-bolumler` | yeni 930 / mevcut 19.099; kontenjan 26.837/702.576; doluluk %88,2 / %98,5; tam dolan %74,9 / %88,2; tabanı oluşan 697; Psikoloji yerleşik 72 medyan 101.050 | **hepsi birebir** [D] |
| `yapay-zekaya-tercih-sordum` | 9.160 program, medyan oynama %14,9, >%20: 2.877, >%50: 297; ilk 100 bin 3.034 / 4.014 / 686; 21.493 = 12.239+9.254; arşiv 572 program / 11.587 yerleşen; kod değişen 466; kontenjan 11.540 / 5.192 / 3.907; Psikoloji 355 program 155 üni, toplam 322 üni; Boğaziçi BM 775/1.006/1.448/4.560 + puan 526,75435 | **hepsi birebir** (hepsi `onlisans=0` havuzunda; yazının yöntem kutusu bunu zaten söylüyor) [D] |
| `bilgisayar-mi-yazilim` | 303/133, 134/169 ve 44/89, 173/74 üni, 12.993/4.274 kontenjan, 11.285/2.894 yerleşen, %86,9/%67,7, ilk 50k 33/1, ilk 100k 98/24, iki yıllık 202/185 ve 81/79 | **hepsi birebir** [D] |
| `kktc…` | lisans 873 prg / 13.162 / 7.923 / %60,2; önlisans 314 / 4.851 / 3.632; taban bandı 395 / 339.153 / 9.061 / 1.420.970; 5 bölüm × 3 evren = **15 medyan hücresinin 15'i** | **birebir** (havuz = `unitur='KKTC'` + Kıbrıs Amerikan) [D] |
| `ek-madde-1` | Marmara BM 521,30/499,01/486,37/483,05 · Ankara Hukuk 471,29/456,38/461,84/475,14 · Hacettepe Psikoloji 461,76/444,25/441,11/449,13 · Ege Makine 460,94/437,19/453,61/471,97 + "38/13/11 puan" farkları | **birebir** [D] |
| `siralama-bandlari` | 2 tam tablo (8 band × 7 kolon) + kapı sayıları + açıköğretim satırı | **birebir** [D] |
---
## (b) Çıkarılan / zayıflatılan cümleler ve gerekçeleri
1. **`kktc-universiteleri-okunur-mu.md`** — *"Lisans ve önlisans toplamlarımız ÖSYM'nin kurum grubu rakamlarıyla birebir aynı (13.162 / 7.923 ve 4.851 / 3.632)."* → **çıkarıldı.** Gerekçe: ÖSYM'nin `2026-YKS Yerleştirme Sonuçlarına İlişkin Sayısal Bilgiler` sayfasını açtım; rakamlar sayfada değil, yalnızca indirilebilir PDF/Excel'de ve **dosya indirmek yasak**. Kendi toplamımızı doğrulayabildim, ÖSYM'nin satırını doğrulayamadım — "birebir aynı" doğrulanamayan bir eşitlik iddiası. Yerine kendi havuzumuzun tam tanımı kondu. (CEO eşiği md. 3)
2. **`kktc…`** — Devlet/vakıf/KKTC tablosunun giriş cümlesine, **KKTC satırının bizim sayımımız** olduğu eklendi. Tablo kaynak karıştırıyordu: devlet (265.356/263.101) ve vakıf (99.638/77.827) satırları ÖSYM yayınından, KKTC satırı DB'den. Bizim DB'mizde devlet 280.131/286.150 ve vakıf yerleşen 78.475 çıkıyor — yani ilk iki satır DB ile **üretilemez**, ÖSYM'den gelmek zorunda. Satırın kaynağı artık yazıda.
3. **`kktc…:7`** — "yerleşirsin" → "yerleştirme yapılır". Tek geçişti; CEO eşiği md. 4 istisnasız.
4. **Hiçbir yazıdan başka cümle çıkarılmadı.** "garanti" kelimesinin 10 yazıdaki bütün düz metin geçişleri olumsuzlama ("garanti demek değil", "garantisi yok", "garanti bir sonuç anlamına gelmez") — bunlar kalıyor, doğru kullanım. Mermaid `classDef garanti` iç anahtarı `AGENTS.md` gereği aynen korundu; görünen dilim adı olarak hiçbir yazıda "garanti" geçmiyor (10 dosyada grep = 0).
---
## (c) Yayımlanabilir / yayımlanmaz hükmü — yazı yazı
CEO'nun altı maddesi: **1** rakam yeniden üretilebilir · **2** yöntem kutusu · **3** açılamayan kaynak yok · **4** vaat dili yok · **5** ayrım cümlesi ilk 200 kelimede · **6** teknik (3 frontmatter alanı, 1 mermaid + `%% aria:`, ≥1 tablo, ölü link yok).
| # | Yazı | 1 | 2 | 3 | 4 | 5 | 6 | Hüküm |
|---|---|---|---|---|---|---|---|---|
| 1 | `taban-siralamalari-alti-yilda-nasil-degisti` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 2 | `kac-net-ile-hangi-bolum` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 3 | `siralama-bandlari-hangi-kapilar-acilir` | ✔ (düzeltildi) | ✔ | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 4 | `yeni-acilan-bolumler-nasil-degerlendirilir` | ✔ (düzeltildi) | ✔ | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 5 | `bilgisayar-mi-yazilim-muhendisligi-mi` | ✔ (düzeltildi) | ✔ (eklendi) | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 6 | `kktc-universiteleri-okunur-mu` | ✔ (düzeltildi) | ✔ (eklendi) | ✔ (iddia çıkarıldı) | ✔ (düzeltildi) | ✔ | ✔ | **Yayımlanabilir** |
| 7 | `yapay-zekaya-tercih-sordum-guvenilir-mi` | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 8 | `ek-madde-1-puanim-yetiyor-mu` | ✔ | — DB tablosu yok, puan örnekleri tek tek doğrulandı | **kısmi** (aşağı bak) | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 9 | `universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma` | — DB rakamı yok | — | **kısmi** (aşağı bak) | ✔ | ✔ | ✔ | **Yayımlanabilir** |
| 10 | `yks-2027-takvimi` | — DB rakamı yok | — | ✔ | ✔ | ✔ | ✔ | **Yayımlanabilir** |
**Onunun da hükmü: yayımlanabilir.** Kesilmesi gereken bir yazı çıkmadı; kesilmesi gereken bir *cümle* çıktı (yukarıda b.1) ve kesildi.
### 8 ve 9'un "kısmi" işareti ne demek
İkisi de mevzuat yazısı ve ikisinin de birincil kaynağı bu ortamdan **benim** tarafımdan açılamadı:
- `mevzuat.gov.tr` ve `resmigazete.gov.tr` WebFetch'te TLS hatası veriyor (`unable to verify the first certificate`); ÖSYM ve YÖK alan adları açılıyor. [K]
- Resmî Gazete'nin 11625 sayılı Karar PDF'i **taranmış görüntü** (metin katmanı yok) ve dosya indirmek yasak.
Yazarların raporları her iki kaynağı da **açtıklarını ve madde madde okuduklarını** yazıyor (`10-yazar-ilk-hafta.md:8,19,28,29`, `12-yazar-ek-madde-1.md`). Ben ne çürütebildim ne teyit edebildim; onun yerine **çapraz kontrol** yaptım:
- 11625 sayılı Karar / 15.08.2026 / RG 33341 / "birinci öğretim katkı payı devletçe karşılanır" → bağımsız ikincil kaynaklarla doğrulandı [A].
- Yatay geçiş yönetmeliğinin 28.02.2026 tarihli (RG 33182) değişikliği ve "alt sınıfa başvuru yapılamaz" hükmü → doğrulandı [A]; yazı zaten "okulunun duyurusunu teyit et" diye hedge ediyor.
- ÖSYM'nin 2027 takvimini yayımlamadığı → doğrulandı [A]; `yks-2027-takvimi`'nin tezi ayakta, 2027 sütununda tek uydurma tarih yok.
**Yayımlanabilir diyorum**, ama (II) sayılı cetvelin 8 rakamı sitede yayımlanmadan önce Bilal'in 2 satırlık göz teyidini istiyorum (aşağıda, yazarın kendi isteğiyle aynı).
---
## (d) Ölü link taraması — yöntem ve sonuç
**Yöntem.** `content/rehber/*.md` içindeki bütün `](/…)` bağlantıları satır numarasıyla çıkarıldı ve dört kümeye karşı doğrulandı (betik: scratchpad, `linkcheck.mjs`):
- `/rehber/<slug>` → `content/rehber/` dosya listesi;
- `/bolum/<slug>` → DB'deki tüm `isim` değerlerinden `turkishSlugify(bolumBazAdi(isim))` (`src/lib/slug.ts:29,41` kuralının birebir kopyası);
- `/universite/<slug>` → DB'deki tüm `universite` değerlerinden `uniSayfaSlug` (sondaki `(İL)` eki atılarak);
- statik yollar → `src/app/` altındaki gerçek route klasörleri; ayrıca `next.config.ts:75-80` redirect tablosu ayrı bir küme olarak işaretlendi (redirect'e düşen link "kırık değil ama kullanılmamalı" sayıldı).
**Sonuç.**
| Kapsam | İç link | Kırık hedef | Redirect'e düşen |
|---|---|---|---|
| 42 yazının tamamı (ilk tarama) | 682 | **0** | 32 (hepsi `/tercih-robotu`) |
| Benim 10 yazım (son tarama) | 298 | **0** | **0** |
- `/il/*` kullanımı **yok** (T7 tuzağına düşen yazı çıkmadı).
- `/bolum/*` ve `/universite/*` slug'larının tamamı DB'den üretilebilen gerçek sayfalara çıkıyor — ODTÜ, Koç, Bahçeşehir gibi elle yazılmış onlarca üniversite linki dahil.
- 10 yazıdaki 4 `/tercih-robotu` geçişi `/#hero-form`'a çevrildi (`src/app/page.tsx:241`'deki gerçek çapa). **Bağlantı metni değiştirilmedi** ("tercih robotuna" ifadesi marka terimi — [BİLAL]).
- **Kalan 28 geçiş mevcut 28 yazıda** ve benim kapsamım dışında. Her biri 301 kalıcı yönlendirmeye gidiyor: gereksiz sıçrama, link eşitliği kaybı ve `/meraklisina`-öncesi eski akış izi. Mekanik bir `sed` işi.
---
## (e) İç link örgüsü — 10 yazı birbirine bağlandı
Denetime başlarken 10 yeni yazının birbirine **sıfır** linki vardı (hepsi yalnız eski 32 yazıya bağlanıyordu). Bu, CEO'nun G4 paketinin çözmeye çalıştığı "iç link grafiği çöküyor" sorununu yeni yazılarda baştan üretiyordu. 13 çapraz link eklendi — hepsi mevcut bir cümlenin içine, konu gerçekten örtüştüğü yere:
| Kaynak | Hedef | Bağlam |
|---|---|---|
| `siralama-bandlari` ↔ `kac-net` | karşılıklı | "elinde sıralama değil net varsa" / "netin sıralamaya dönüşür" |
| `siralama-bandlari` ↔ `taban-siralamalari-alti-yilda` | karşılıklı | envanter (2026 fotoğrafı) ↔ yön (altı yıl) |
| `kac-net` → `taban-siralamalari-alti-yilda` | tek yön | "tabanların yıllar içinde kayması"nın ölçümü |
| `bilgisayar-mi-yazilim` → `taban-siralamalari-alti-yilda` | tek yön | Yazılım Müh. altı yılda en çok gerileyen 3. bölüm — yazının kendi "tabanlar gevşedi" cümlesinin devamı |
| `yapay-zekaya-tercih-sordum` ↔ `yeni-acilan-bolumler` | karşılıklı | kılavuzdan düşen / kılavuza yeni giren satırlar; havuz kuralı |
| `yapay-zekaya-tercih-sordum` → `kac-net` | tek yön | "kaç netle girilir" veriye sorulacak sorular listesinde |
| `ek-madde-1` ↔ `universitede-ilk-hafta` | karşılıklı | ilk haftada atılacak geri dönüşü olan adımlar |
| `yks-2027-takvimi` → `taban-siralamalari-alti-yilda`, `kac-net` | tek yön | 2027'ye hazırlananın "bugünden ne yaparım" listesi |
Bağlam bulamadığım çiftlere (ör. `kktc` ↔ `bilgisayar-mi-yazilim`) **link uydurmadım**.
---
## (f) Kanibalizasyon denetimi
| Çift | Ayrım cümlesi ilk 200 kelimede? | Not |
|---|---|---|
| `siralama-bandlari` ↔ `kac-siralama-ile-hangi-bolume-girebilirim` ↔ `hedef-siralama-nasil-belirlenir` | **Evet** — ikisine de link, 2. paragrafta | "Bu yazı iki kardeş yazının arasını dolduruyor… Burada ise tek bir soruya sayım yaparak cevap veriyoruz." Yazı bölüm adı listesi vermiyor, 1,4 katı dilim kuralını tekrar etmiyor. SEO planı §1'deki kural karşılanıyor. |
| `taban-siralamalari-alti-yilda` ↔ `taban-siralamalar-nasil-degisir` | **Evet** — 3. paragrafta | "orada mekanizmalar var, burada altı yılda gerçekte ne olduğunun ölçümü." |
| `kac-net` ↔ `siralama-bandlari` | **Evet** (yeni eklendi) | Net cetveli ↔ sıralama cetveli ayrımı ikisinin de girişinde. |
| `yeni-acilan-bolumler` ↔ `yapay-zekaya-tercih-sordum` | **Evet** (yeni eklendi) | Biri havuzun **içeriğini**, diğeri havuzun **kuralını** anlatıyor. |
---
## (g) Tutarlılık denetimi
- **Kapanan / kod değişen program sayısı** (`yapay-zeka` 572 + 466 ↔ `yeni-acilan` %8,0 ve 475/2.004): **çelişki yok**, üç farklı kesit. Doğrulandı: arşivde 2025 yerleşeni >0 ve kodu eşleşmeyen **572** lisans programı, 11.587 yerleşen; `eski_kod` dolu **466** satır; 2025'te kontenjanı olan satırların 1.745/21.986 = **%7,9** düşmüş. [D] İki yazı da sayıyı "kapanan program sayısı" diye satmıyor — `yapay-zeka:158` bunu açıkça uyarıyor.
- **Psikoloji trendi (`17-yazar-alti-yil-trend.md`'deki ⚠ üç satır):** `taban-siralamalari-alti-yilda` zaten ⚠ uyarısına uymuş — ortalamanın yanına "184 programın 78'inde sıralama küçüldü" kolonu, ardından **ayrı bir devlet kırılımı tablosu** (devlet 51 program 108.722→105.556, "ters" etiketli) ve Hacettepe örneği koymuş. Başka hiçbir yeni yazı Psikoloji'yi "gerileyen bölüm" diye tek başına anmıyor. **Düzeltme gerekmedi.**
- **Devlet Psikoloji 2026 medyanı** iki yazıda iki farklı sayı: `kktc` 97.977 (74 program, hepsi) ↔ `yeni-acilan` 101.050 (72 program, yalnız yerleşik). İkisi de kendi havuzunda doğru [D]. Okuyucu iki sayıyı yan yana görürse şaşırmasın diye `kktc`'nin yöntem kutusuna **ikisi arasındaki farkı açıklayan satır** eklendi.
- **Veri tarihi:** 10 yazının hepsinde 21 Eylül 2026 ✔. **Yıl etiketi:** `kac-net`'in bütün net rakamları 2025 etiketli ✔ (CEO'nun §C koşulu). **Çerçeve:** "son yerleşen kişinin netleri" ✔, "yerleşenlerin ortalaması" ifadesi hiçbir yazıda yok ✔.
- **Frontmatter:** 10 dosyanın hepsinde tam 3 alan (`baslik`, `aciklama`, `tarih`), düz `anahtar: değer` ✔. `guncelleme` alanı eklenmedi — hepsi bugün doğdu, içerik düzeltmesi yayın öncesi yapıldı.
- **Teknik:** her dosyada tam 1 `flowchart TD` + `%% aria:` + ≥1 tablo ✔. Renk kutularının hepsinde metin etiketi var; renk tek başına anlam taşımıyor ✔.
- **Ürün davranışı ↔ kod:** `yeni-acilan:157` ("efektif taban sıralaması = 2026, yoksa 2025"), `yapay-zeka:118` ve `siralama-bandlari` ("ürün yerleşme olasılığı hesaplamaz; yalnızca son tabanı senin sıranla kıyaslar") — `src/lib/risk.ts:70-76` yorumu ve `riskHesapla` ile **birebir uyumlu** ✔. Görünen dilim adları "Hayal / Dengeli / Güvenli" ✔ (`DILIM_ETIKET`).
---
## (h) Altyapı borcu (raporluk — `src/` altına dokunulmadı)
1. **`/tercih-robotu` 28 mevcut yazıda.** Hepsi 301'e gidiyor. `sed -i 's#](/tercih-robotu)#](/#hero-form)#g'` düzeyinde mekanik iş; bağlantı metni korunmalı.
2. **`unitur` veri kalitesi (KKTC).** Kıbrıs Amerikan Üniversitesi'nin 42 satırı `unitur='DEVLET'` — bu yüzden sihirbazın "devlet" adımında KKTC programı çıkıyor ve `/universite/kibris-amerikan-universitesi` sayfasında `stats.devletMi` true dönüyor. Yazarın raporu (`14-yazar-kktc.md:187`) bunu `src/lib/db.ts:79` ve `src/lib/katalog.ts:402`'ye kadar izlemiş. **Veri işi, editör işi değil** — bu yazı artık düzeltmeyi beklemeden doğru sayıyor, ama ürün hâlâ yanlış gruplandırıyor.
3. **`il` alanı kirli:** 2026 lisans havuzunda 9 satırın `il`'i boş, 34 satırınki "KIBRIS"/"LEFKOŞA"/"SARAYBOSNA - BOSNA - HERSEK". SEO planının T34'ü; `/il/[slug]` sayfası açılmadan önce temizlenmeli.
4. **10 KKTC üniversitesi katalogda iki adla duruyor** (`X` ve `X (KKTC-ŞEHİR)`), bu yüzden `/universiteler` listesinde ikişer kez görünüyorlar.
---
## Bilal'den istenen (3 madde)
1. **Harç cetvelinden 2 rakamı göz kararı teyit et.** `resmigazete.gov.tr/eskiler/2026/08/20260815-7.pdf` sayfa 14–15, (II) sayılı cetvel (A): mühendislik-mimarlık **11.348 TL** ve veteriner **15.844 TL**. PDF taranmış görüntü olduğu için yazar rakamları görselden okudu, ben bu ortamdan açamadım (TLS + indirme yasağı). Tutuyorsa `universitede-ilk-hafta` bu haliyle çıkar — **~3 dk**.
2. **"Tercih robotu" marka terimi.** Yeni yazılardaki linkleri `/#hero-form`'a çevirdim ama **metni değiştirmedim** ("tercih robotuna sıralamanı gir"). Ürün içinde artık ayrı bir robot sayfası yok; bu ifade yazılarda kalsın mı, yoksa 42 yazıda topluca mı değişsin? Tek cümlelik karar — **~2 dk**.
3. **Mevcut 28 yazıdaki `/tercih-robotu` linkini tek commit'te düzelteyim mi?** Benim kapsamım bu gece 10 yazıydı; onay verirsen ayrı `fix(rehber): ölü CTA linki` commit'i olarak hazırlarım (içerik değişmez, yalnız href) — **~1 dk karar**.
---
# EK — Doluluk paydası sapması (veri mühendisi bulgusu, aynı gece)
Tetikleyen: `26-veri-kalitesi.md` §1.5 / K13-K14. Bu benim denetimimin kaçırdığı bir yöntem hatası değil, **şemadan gelen bir sapma**: rakam yazının filtresiyle yeniden üretiliyor ama paydanın kendisi eksik tanımlı.
## Bulguyu kendim doğruladım
```sql
-- Payda yalnız genel kontenjan
SELECT COUNT(*), SUM(kontenjan2025 <> gk2025) FROM programs
WHERE kontenjan2025 IS NOT NULL AND gk2025 IS NOT NULL; -- 19.857 | 0 → kontenjan = gk, istisnasız
```
`scripts/refresh.ts:211-217` — `yerlesen()` fonksiyonu `gkY + sgyY + dprmY + obkY` topluyor. Yani **pay dört kota türü, payda tek kota türü.** [D]
```sql
SELECT COUNT(*), SUM(onlisans=0 AND unitur='DEVLET'), SUM(unitur='VAKIF'), SUM(unitur='KKTC')
FROM programs WHERE yerlesen2026 > kontenjan2026; -- 11.964 | 5.618 | 840 | 0
```
2026 için **doğru payda yeniden kurulamıyor** — `gk/obk/sgy/dprm/y34k` kolonları yalnız 2025 yılı için var. 2025 üzerinden etkiyi ölçtüm: devlet Bilgisayar Müh. %101,6 → %99,0, devlet Yazılım Müh. %103,2 → **%102,0** — yani tam payda ile bile %100'ün üstünde kalıyor. Bu, "açıklayıp bırakmak" seçeneğini devlet tarafında savunulamaz kıldı. [D]
## Ne değiştirdim
### 1. `bilgisayar-mi-yazilim-muhendisligi-mi.md` — devlet doluluk **çıkarıldı**
| Eski | Yeni |
|---|---|
| `\| Devlet programlarında doluluk \| %99,8 \| %102,1 \|` | **satır silindi** |
| — | `\| Kontenjanını doldurup taban sırası oluşan devlet programı \| 120 / 134 (%89,6) \| 40 / 44 (%90,9) \|` |
| — | `\| … vakıf programı \| 94 / 169 (%55,6) \| 43 / 89 (%48,3) \|` |
| `\| Doluluk \| …` | `\| Doluluk (yerleşen ÷ ilan edilen **genel** kontenjan) \| …` |
**Neden çıkardım, açıklamadım:** %102,1'in yanına "payda eksik" notu düşmek, okuyucuya yeniden üretemeyeceği ve düzeltemeyeceği bir sayı bırakırdı (2026 için doğru payda elimizde yok). Onun yerine **aynı şeyi söyleyen, üretilebilir** bir ölçüye geçtim: ÖSYM en küçük puanı ve başarı sırasını yalnız **kontenjanını tamamen dolduran** programlar için yayımlar, dolayısıyla `sira2026 IS NOT NULL` "program doldu mu" sorusunun bozulmamış göstergesi.
```sql
SELECT CASE WHEN isim LIKE 'Bilgisayar Mühendisliği%' THEN 'BM' ELSE 'YM' END b, unitur,
COUNT(*), SUM(sira2026 IS NOT NULL), ROUND(100.0*SUM(sira2026 IS NOT NULL)/COUNT(*),1)
FROM programs
WHERE (isim LIKE 'Bilgisayar Mühendisliği%' OR isim LIKE 'Yazılım Mühendisliği%')
AND onlisans=0 AND unitur IN ('DEVLET','VAKIF') AND isim NOT LIKE '%KKTC Uyruklu%'
GROUP BY b, unitur;
-- BM DEVLET 134|120|89,6 · BM VAKIF 169|94|55,6 · YM DEVLET 44|40|90,9 · YM VAKIF 89|43|48,3 [D]
```
Yan fayda: tablodaki "medyan taban sırası **120 program** / **40 program**" hücreleri artık yeni satırlarla birebir eşleşiyor — yazı kendi içinde kapanıyor.
**Ayrıca düzeltilen bir yanlış açıklama:** okuma notu "%100'ü aşması hata değil: **ek kontenjan** ve benzeri düzeltmelerle yerleşen sayısı ilan edilen kontenjanı geçebilir" diyordu. Bu **ters** — ek kontenjan paydaya eklense oran düşerdi. Gerçek sebep (kota kontenjanlarının paydada olmaması) yazıldı.
**Vakıf satırlarına dokunmadım**, ama yöntem kutusuna şunu ekledim: vakıf oranları (%60,7 · %32,9) sapma nedeniyle **üst sınırdır** — gerçek doluluk bundan yüksek olamaz. Yazının argümanı ("vakıfta kontenjanın büyük kısmı boş kaldı") bu yönde zaten muhafazakâr, yani sapma argümanı güçlendiriyor, zayıflatmıyor.
### 2. `yeni-acilan-bolumler-nasil-degerlendirilir.md` — aynı sapmanın ikinci yeri
Tarama bu yazıda da iki yer buldu; **ikisini de yazar zaten fark etmiş ama sebebi yanlış yazmıştı.**
- `:74` — *"Devlet önlisansta doluluğun %100'ü aşmasının sebebi, YÖK Atlas kontenjan sütununun **yerleştirme sonrası eklenen kontenjanları da içermesi**"* → **yanlış ve ters yönlü**. Gerçek sebep yazıldı: kontenjan alanı yalnız genel kontenjanı tutuyor, yerleşen dört kotanın toplamı. Devlet satırlarının (`%105,2`, `%96,5`) kesin yüzde değil gösterge olarak okunması gerektiği, vakıf satırlarının etkilenmediği eklendi.
- `:139` — ikinci yıl tablosundaki **%102,8** satırına aynı uyarı tek parantezle kondu; okunacak şeyin iki satır arasındaki uçurum (%102,8 ↔ %39,7) olduğu söylendi.
- Yöntem kutusuna: doluluk paydasının eksikliği + yazının asıl argümanının **"kontenjanı tam dolan program payı"** ve **"hiç yerleşen olmayan program payı"** kolonlarına dayandığı, bu iki kolonun sapmadan çok daha az etkilendiği notu.
Rakamlar (%88,2 / %98,5 / %74,9 / %105,2 …) **değiştirilmedi** — hepsi yazının kendi filtresiyle yeniden üretiliyor, sorun üretilebilirlik değil paydanın tanımı.
## Taranan ve temiz çıkanlar
`yerlesen ÷ kontenjan` oranı kullanan **her** yazı tarandı (`grep -nE "[Dd]oluluk|yerleşen ÷|÷ kontenjan|%[0-9]+,[0-9]+ (doldu|dolarken)"`).
| Yazı | Doluluk oranı var mı | Hüküm |
|---|---|---|
| `bilgisayar-mi-yazilim-muhendisligi-mi` | **Evet, devlet dahil** | **Düzeltildi** (yukarıda) |
| `yeni-acilan-bolumler-nasil-degerlendirilir` | **Evet, devlet dahil** | **Düzeltildi** (yukarıda) |
| `kktc-universiteleri-okunur-mu` | Evet, ama yalnız KKTC | **Dokunulmadı.** Veri mühendisinin "KKTC'de aşan satır 0" bulgusunu dört yıl için ayrı ayrı doğruladım: `SUM(yerlesen20YY>kontenjan20YY)` → 2023: 0 · 2024: 0 · 2025: 0 · 2026: 0 [D]. Yazıdaki devlet %99,2 ve vakıf %78,1 satırları **bizim DB'mizden değil ÖSYM yayınından** geliyor (DB'de devlet 280.131/286.150 çıkıyor) — sapma taşımıyorlar |
| `siralama-bandlari-hangi-kapilar-acilir` | Hayır — yalnız kontenjan **toplamı** ve program sayısı | temiz |
| `taban-siralamalari-alti-yilda-nasil-degisti` | Hayır — kontenjan toplamı (255.090 → 204.714) | temiz |
| `kac-net-ile-hangi-bolum` | Hayır | temiz |
| `yapay-zekaya-tercih-sordum-guvenilir-mi` | Hayır — kontenjan **değişimi** (5.192 değişti / 3.907 azaldı), oran değil | temiz |
| `ek-madde-1-puanim-yetiyor-mu` | Hayır | temiz |
| `universitede-ilk-hafta-…` | Hayır (DB rakamı yok) | temiz |
| `yks-2027-takvimi` | Hayır (DB rakamı yok) | temiz |
**Kapsamım dışındaki bu geceki iki yazıyı da taradım, ikisi de temiz:** `bolumumu-sevmedim-hangi-kapilar-var.md` ve `rehber-ogretmenler-icin-veri-kaynaklari.md` doluluk oranı kullanmıyor (tek geçiş, YÖK Atlas'ın ne sunduğunu anlatan bir tablo hücresi). `veliler-icin-tercih-rehberi.md` başka ajanda — **açılmadı**, yalnız grep'lendi: temiz.
## Hükümde değişiklik yok
İki yazı da hâlâ **yayımlanabilir**; düzeltmeler yayın öncesi yapıldı. Yeniden doğrulandı: `bilgisayar-mi-yazilim` 67 iç link · 0 kırık · 3 frontmatter alanı · 1 mermaid + `%% aria:` · tablolar sağlam; `yeni-acilan` aynı.
## Bilal'den istenen — ek 1 madde (toplam 4)
4. **`kontenjan` kolonunun anlamı ürün genelinde bir borç.** Rehber yazıları artık doğru; ama aynı payda `/bolum` ve `/universite` sayfalarında bir doluluk göstergesi olarak kullanılıyorsa aynı sapmayı taşır. Bunu `veri-muhendisi`/`cto` kuyruğuna bir satır olarak açmak yeterli (şema işi, editör işi değil) — **~1 dk karar**.
---
# EK 2 — Dalga 3 denetimi (4 yazı, aynı gece, ikinci editör kopyası)
Kapsam: `rehber-ogretmenler-icin-veri-kaynaklari`, `bolumumu-sevmedim-hangi-kapilar-var`, `ayni-bolum-farkli-universite-siralama-farki`, `hangi-bolumlerin-kontenjani-azaldi`. Artı, orkestratörün ÖNCELİKLİ KONTROL §4'ünde adıyla verdiği tek cümle için **canlıdaki** `bos-kontenjanlar-ne-anlatiyor.md`.
`src/` altına, Bilal'in commit'lenmemiş dosyalarına ve diğer 11 yeni yazıya **dokunulmadı**. Commit yok, `git add` yok, yıkıcı git komutu koşulmadı.
İşaret: **[D]** bu sabah kendim koştum/açtım · **[A]** ikincil · **[K]** açılamadı.
## Özet (5 madde)
1. **Dört yazının bulabildiğim her DB rakamını yeniden koştum: 120'den fazla hücrenin tamamı tuttu, tek bir rakam düzeltilmedi.** `ayni-bolum`'un 8 tablosu (7 bölüm × 7 kolon, %10/medyan/%90 yayılımı, 73 bölümlük yayılım sıralaması, Psikoloji merdiveni, 6 devlet programı, devlet/vakıf medyanları, şehir kırılımı, program yaşı, 20 dil çifti) ve `hangi-bolumlerin-kontenjani-azaldi`'nın 7 tablosu (denge, kurum, 15 azalan, 4 artan, korelasyon bantları, bölüm medyanları, YÖK'ün beş programı) **hücre hücre birebir** çıktı [D].
2. **Havuz çapraz kontrolü temiz: `ayni-bolum` ile `siralama-bandlari` tek sayıda bile ayrışmıyor.** 9.304 program / 271 üniversite / 81 il / 351 bölüm adı / 5.865 devlet / 3.439 vakıf / 312.283 kontenjan — yedisi de benim koşumumda aynı çıktı; `ayni-bolum`'un 7 adımlık eleme merdiveni (21.493 → 12.239 → 11.280 → 9.482 → 9.408 → 9.365 → 9.304) adım adım yeniden üretildi. İki yazının **ortak** altı bölümünde (İşletme, Psikoloji, BM, Hemşirelik, Hukuk, Tıp) program sayısı, en sıkı, medyan ve en geniş **dört değerin dördü de** aynı; Yeditepe Psikoloji üçlüsü (4.034 / 239.840 / 708.709) iki yazıda da aynı ve DB'de de aynı [D].
3. **Açıköğretim tuzağı doğrulandı ve manşet gerçekten değişiyor.** Açık/uzaktan satırlar havuza katılırsa "en çok kısılan" listesinin 3. sırasına Görsel İletişim Tasarımı giriyor (90 program, 5.422 → 4.288, **−1.134**) ve bu düşüşün **1.000'i tek satır**: Anadolu Ü. Açıköğretim Fakültesi 3.000 → 2.000. Örgün bakılınca 89 program, 2.422 → 2.288, −134 [D]. Yazının kararı doğru, rakamı da doğru. (Brief'teki −1.084 SEO planının farklı havuzundan; yazının kendi havuzunda karşılığı −1.134 ve yazı bu sayıyı tutarlı kullanıyor.)
4. **Tek gerçek düzeltme, önceki kopyanın bulduğu payda sapmasının üçüncü tekrarıydı** — ve bu kez yanlış açıklamayla birlikte: `hangi-bolumlerin…:20` "yerleşen kontenjandan büyük, çünkü **yerleştirme sırasında eklenen kontenjanlar** bu kolona yansıyor" diyordu. **Ters ve yanlış.** Gerçek sebep yazıldı, "boş kontenjan" sayıları **alt sınır** olarak etiketlendi. Aynı yanlış açıklama canlıdaki `bos-kontenjanlar-ne-anlatiyor`'un kaynak satırında da duruyordu; orası da düzeltildi (aynı satırdaki "birkaç yüz kişilik fark" ifadesi de devlet kontenjan toplamı için **~9 bin**, düzeltildi).
5. **Ölü link: 46 yazının tamamında 829 iç link, 187 benzersiz hedef, 0 kırık.** Dört yazının hiçbirinde `/tercih-robotu` ya da `/il/*` yok. Dörtten diğer 14 yeni yazıya **sıfır** çapraz link vardı; **10 doğal çapraz link** eklendi. Dört yazının dördü de **yayımlanabilir**.
## (a) Düzeltilen rakam ve ifadeler
| Yazı:yer | Eski | Yeni | Sorgu / gerekçe |
|---|---|---|---|
| `hangi-bolumlerin…` yöntem kutusu | "`yerlesen2026` bazı programlarda `kontenjan2026`'dan büyük (**yerleştirme sırasında eklenen kontenjanlar** bu kolona yansıyor)" | Gerçek sebep: `kontenjan` = yalnız **genel kontenjan**, `yerlesen` = dört kotanın **toplamı**; doluluk oranı verilmiyor, yerleşen yalnız **alt sınır** göstergesi | `SELECT COUNT(*), SUM(kontenjan2025<>gk2025) FROM programs WHERE kontenjan2025 IS NOT NULL AND gk2025 IS NOT NULL;` → **19.857 \| 0** · `scripts/refresh.ts` `yerlesen()` = `gkY+sgyY+dprmY+obkY` · 2026'da aşan satır **11.964** [D] |
| `hangi-bolumlerin…` Diş Hekimliği (2 yer) | "164 programın **28'inde** kontenjan boş kaldı (**410** kişilik boşluk)" | "**en az** 28'inde (**en az** 410 kişilik; bu bir alt sınırdır)" | Pay şişkin olduğu için `yerlesen<kontenjan` koşulunu sağlayan satır kesinlikle boş; sağlamayan satır **boş olmayabilir de olabilir** → sayım alt sınır [D] |
| `hangi-bolumlerin…` yöntem kutusu | (bant sınırı yazılı değildi) | Bant sınırları açık yazıldı: `≤−%25`, `−%25<x<−%10`, `−%10≤x<0`, `0`, `0<x≤%10`, `%10<x≤%25`, `>%25`; medyan `ROW_NUMBER()`, çift gözlemde iki ortanın ortalaması | Yazının verdiği filtreyle 7×3 = **21 hücrenin 21'i** ancak bu sınırlarla birebir çıkıyor; başka bir okumayla 1.520/353/121/249/389 çıkıp tablo tutmuyor. CEO eşiği md. 1 ⇒ **rakam değil yöntem cümlesi** düzeltildi [D] |
| `hangi-bolumlerin…:19` | "425'i … gerçekten yeni programlar" | + "[yeni açılan bölümler yazısındaki] 930 rakamı aynı tanımın önlisansı ve vakıf MYO'ları da kapsayan hâlidir, 425 onun örgün lisans alt kümesidir" | İki yazı aynı tanımı iki farklı evrende sayıyor; ikisini de koştum: **930** (tüm düzey + VAKIF MYO) ve **425** (örgün lisans, DEVLET/VAKIF) [D] |
| `hangi-bolumlerin…:192` | `[ana sayfadaki sıra formunu](/)` | `(/#hero-form)` | Diğer 14 yeni yazının tamamı `/#hero-form` çapasını kullanıyor (`src/app/page.tsx:241`); tek başına `/` sayfanın tepesine düşüyordu |
| `bos-kontenjanlar-ne-anlatiyor:131` **(canlı)** | "devlet tarafında YÖK Atlas kontenjanları **yerleştirme sonrası eklenen kontenjanları da içerdiği için birkaç yüz kişilik fark** oluşuyor" | Devlet lisans kontenjan toplamımız ÖSYM'ninkinden **~9 bin kişi düşük** (265.356 ↔ 256,5 bin civarı); kurum grubu tablosunun tamamının ÖSYM'den alındığı ve `kontenjan`/`yerleşen` payda sapması yazıldı | ÖSYM 265.356; `SUM(kontenjan2026)` örgün devlet lisans = **256.532** [D]. "Birkaç yüz" yalnız boş toplamı için doğru (29.985 ↔ 29.882), kontenjan toplamı için **değil**. Yazarın `30-yazar-kontenjan-azalan.md:265`'te açtığı bulgu |
**Rakamı değiştirmedim, çünkü değiştirilecek rakam çıkmadı.** Yeniden koşulup **birebir** tutanlar:
| Yazı | Yeniden koşulan | Sonuç |
|---|---|---|
| `ayni-bolum` | 7 adımlık eleme merdiveni (21.493→9.304); 9.304/271/81/351/5.865/3.439/312.283; 7 bölüm × (program, üniversite, min, medyan, max, devlet, vakıf) = 49 hücre; %10/medyan/%90 + kat oranı 7×4; 73 bölümlük yayılım listesi (Ekonomi 269,9 · Yeni Medya 219,4 · GİT 192,4 · İlk.Mat.Öğrt. 2,1 · Sınıf 2,2 · Eczacılık 2,3); Psikoloji merdiveni 5×4; 6 devlet programının adı-ili-sırası-kontenjanı; devlet/vakıf medyanı 7×2; şehir kırılımı 6×4; program yaşı 391/109.331 ↔ 170/246.689; 20 dil çifti 9/11; kontenjan bandı 315/146/100 ve 108.326/152.945/152.671; ikinci öğretim = 0; ODTÜ 65 satır + İşletme 6 satır (1.585…800.853) + Psikoloji 2 satır (2.443, 141.555); Bosna iki satırı (114.116, 795.314); vakıf burs etiketi 339/203/117 = 659 / 2.780; Psikoloji vakıf 32 etiketli / 138 etiketsiz; Mimarlık devlet en sıkı 39.128 = ODTÜ; 110 boş `il` (tablo geneli) ve havuzda 9 | **hepsi birebir** [D] |
| `hangi-bolumlerin…` | 10.534 eşleşen / 301 kod değişen / 505 yeni (14.244) / 425 gerçekten yeni; denge 3.698-1.056-5.780 ve 130.690→102.930, 25.332→32.058, 206.750, 362.772→341.738; devlet 6.107/1.738/266.665→252.916, vakıf 4.427/1.960/96.107→88.822; bölüm adı dengesi 354/235/27/92; arşiv 938 = 352 (5.824) + 586 (17.660); 15 azalan bölümün 9 kolonu = **135 hücre**; 4 artan + Metalurji +35; Pearson **0,192**, Spearman **0,153**, n **8.681**; bant tablosu 7×3; bölüm medyan tablosu 10×4; Hacettepe Diş 90→81 / 15.895→24.599 ve Sivas Cumhuriyet Hemşirelik 80→90 / 191.920→151.729; Diş Hek. 164/5.569/5.294/28/410; açık blok 61 prg / 5 üni / 24.525→23.349 | **hepsi birebir** [D] |
| `rehber-ogretmenler…` | Psikoloji **234** program, **329 – 1.402.765** (yazının verdiği SQL'le, kelimesi kelimesine) | **birebir** [D] |
| `bolumumu-sevmedim…` | DB rakamı yok | — |
## (b) Çıkarılan / zayıflatılan cümleler
1. **`hangi-bolumlerin…:20`** — "yerleştirme sırasında eklenen kontenjanlar bu kolona yansıyor" **çıkarıldı**. Bu açıklama yalnız eksik değil, **ters**: ek kontenjan paydaya eklenseydi oran düşerdi. Yerine ölçülmüş sebep kondu ve yazıya "bu yazıda hiçbir yerde `yerleşen ÷ kontenjan` doluluk oranı vermiyoruz" kuralı yazıldı.
2. **`hangi-bolumlerin…`** — "28 programda boş kaldı / 410 kişilik boşluk" kesin sayı olmaktan çıkarıldı, **alt sınır** olarak etiketlendi. Sayı değişmedi; iddia zayıflatıldı (CEO eşiği md. 1 — okuyucu yeniden üretebildiği şeyi görmeli).
3. **`bos-kontenjanlar-ne-anlatiyor:131` (canlı)** — "birkaç yüz kişilik fark" ifadesi devlet **kontenjan** toplamı için yanlıştı (gerçek fark ~9 bin), aynı cümledeki sebep de yanlıştı. İkisi de düzeltildi; doğrulanmış olan (vakıf 99.638 birebir, boş 29.985 ↔ 29.882) korundu.
4. **Başka cümle çıkarılmadı.** Vaat dili taraması dört yazıda da **temiz** (`yerleşirsin|kesinlikle girer|garanti bir|atanırsın|kazanırsın|girersin` → 0 eşleşme). "garanti" kelimesi yalnız `hangi-bolumlerin…` mermaid'inde `classDef garanti` iç anahtarı olarak geçiyor; `AGENTS.md` gereği **aynen korundu**, görünen etiketler "Hayal / Dengeli / Güvenli" [`src/lib/risk.ts:21-25`].
## (c) Tutarlılık: iki yazıdaki iki Psikoloji sayısı
`rehber-ogretmenler…` Psikoloji'yi **234** program diye sayıyor (`isim = 'Psikoloji'` tam eşleşme, `son_kilavuz_yili = 2026`), `ayni-bolum` **243** diyor (parantezli varyantlar aynı başlık altında, Türkiye kampüsleri). **İkisi de kendi filtresiyle birebir üretiliyor** [D] ve taban aralığı ikisinde de 329 – 1.402.765. Okuyucu iki sayıyı yan yana görürse çelişki sanmasın diye `rehber-ogretmenler…`'e farkı açıklayan ve ikinci havuza bağlanan iki cümle eklendi. `ayni-bolum` tarafına dokunulmadı — orada tanım zaten yazılı.
Diğer tutarlılık kontrolleri: veri tarihi dört yazıda da **21 Eylül 2026** ✔ · yıl etiketi her rakamda var ✔ · "son yerleşen kişinin sırası" çerçevesi ✔ ("yerleşenlerin ortalaması" hiçbirinde yok) · frontmatter dördünde de tam 3 alan, düz `anahtar: değer` ✔ · `guncelleme` eklenmedi (dördü de bugün doğdu; `bos-kontenjanlar` da bugün tarihli, aynı gün düzeltildi) · her dosyada tam 1 `flowchart TD` + `%% aria:` + `%% altyazi:` ✔ · tablo sayısı 3 / 1 / 8 / 7 ✔ · renk kutularının hepsinde metin etiketi var ✔.
**Ürün davranışı ↔ kod:** üç yazıdaki "ürün yerleşme olasılığı hesaplamaz; son taban sıralamasını (2026, yoksa 2025) senin sıranla kıyaslar ve satırı Hayal/Dengeli/Güvenli dilimine koyar" cümlesi `src/lib/risk.ts:21-25` (`DILIM_ETIKET`) ve `:73-79` (`riskNotuMetni` yorumu) ile **birebir uyumlu** ✔.
## (d) Kanibalizasyon denetimi
| Çift | Ayrım cümlesi ilk 200 kelimede? | Aynı kesit farklı rakamla anılıyor mu? |
|---|---|---|
| `hangi-bolumlerin…` ↔ `bos-kontenjanlar…` ↔ `yeni-acilan…` | **Evet** — 114. kelimede, üç yazıyı da adıyla ayıran tek paragraf ("açılan ama dolmayan" / "ilk kez giren" / "kılavuzda duran ama küçülen") | **Hayır.** `hangi-bolumlerin…` Türkiye geneli resmî toplam **vermiyor**, ÖSYM toplamları için `bos-kontenjanlar`'a gönderiyor; tek çakışma adayı olan "yeni program" sayısı (425 ↔ 930) artık yazıda açıkça uzlaştırılıyor |
| `ayni-bolum` ↔ `siralama-bandlari` ↔ `kac-siralama-ile-hangi-bolume-girebilirim` | **Evet** — 102. kelimede, üçünü de ayırıyor (dağılım / envanter / kaba harita) | **Hayır.** Ortak altı bölümün dört değeri de iki yazıda **aynı**; havuzun aynı olduğu iki yazıda da yazılı |
| `rehber-ogretmenler…` ↔ `tercih-robotu-nedir-yok-atlas-nasil-kullanilir` | **Evet** — giriş paragrafında "bu yazı bir kaynak haritası", Atlas'ın adım adım kullanımı için diğerine bağlanıyor | Hayır |
| `bolumumu-sevmedim…` ↔ 7 kapı yazısı | **Evet** — 9. satır: "Bu yazı bir harita: her kapıyı tek cümleyle tanıtır, ayrıntıyı kendi yazısına bırakır" | Hayır — hub hiçbir kapının rakamını tekrar etmiyor |
## (e) Eklenen çapraz linkler (10)
Denetime başlarken bu dört yazının diğer 14 yeni yazıya **sıfır** linki vardı (`bolumumu-sevmedim`'in `universitede-ilk-hafta` ve `ek-madde-1` bağları ile `hangi-bolumlerin…`'in `yeni-acilan`/`yks-2027`/`taban-…-alti-yilda` bağları dışında) ve **dördü birbirine hiç bağlı değildi**. Hepsi mevcut bir cümlenin içine kondu:
| Kaynak | Hedef | Bağlam |
|---|---|---|
| `hangi-bolumlerin…` | `ayni-bolum…` | "Bölüm adına değil, programa bak" maddesinin devamı |
| `hangi-bolumlerin…` | `yeni-acilan…` (2. geçiş) | 425 ↔ 930 uzlaştırması |
| `ayni-bolum…` | `hangi-bolumlerin…` | "Ölçemediğimiz iki şey → kontenjan büyüklüğü": aynı soru 2025→2026 değişimiyle ayrıca ölçüldü |
| `ayni-bolum…` | `bilgisayar-mi-yazilim…` | Aynı yayılım sorusu iki **komşu bölüm adı** arasında |
| `ayni-bolum…` | `kac-net-ile-hangi-bolum` | "Sıralaman 150.000 ise" merdiveninin girişi: elinde net varsa |
| `rehber-ogretmenler…` | `ayni-bolum…` | "Aynı bölüm adı" tuzağı paragrafı + 234/243 uzlaştırması |
| `rehber-ogretmenler…` | `hangi-bolumlerin…` | YÖK duyuruları bölümü: kontenjan politikasının veri karşılığı |
| `rehber-ogretmenler…` | `bolumumu-sevmedim…` | Kapanış: tercih haftasından sonra gelen soru |
| `bolumumu-sevmedim…` | `ayni-bolum…` | 2. kapı: yatay geçişte hedef programı seçerken |
| `bolumumu-sevmedim…` | `siralama-bandlari…` | 4. kapı: yeni bir sıralamanın kaç kapı açtığını önden görmek |
Bağlam bulamadığım çiftlere (ör. `bolumumu-sevmedim` ↔ `kktc…`, `rehber-ogretmenler` ↔ `yks-2027-takvimi`) **link uydurmadım**. Dört yazıya diğer 11 yeni yazıdan **gelen** link hâlâ yok — o dosyalar kapsamım dışında (aşağıda, Bilal'den istenen md. 3).
## (f) Ölü link taraması — yöntem ve sonuç
**Yöntem** (önceki taramayla aynı, düzeltmelerden sonra yeniden koşuldu): `content/rehber/*.md` içindeki tüm `](/…)` bağlantıları çıkarıldı, `#` çapası atıldı, dört kümeye karşı doğrulandı — (1) `/rehber/<slug>` ↔ `content/rehber/` dosya listesi; (2) `/bolum/<slug>` ↔ DB'deki tüm `isim` değerlerinden `turkishSlugify(bolumBazAdi(isim))` (`src/lib/slug.ts:6,25,45` kuralının birebir kopyası, `node` ile); (3) `/universite/<slug>` ↔ DB'deki tüm `universite` değerlerinden `uniSayfaSlug`; (4) statik yollar ↔ `src/app/` route klasörleri + `next.config.ts:76-80` redirect tablosu (redirect'e düşen "kırık değil ama kullanılmamalı" sayıldı).
| Kapsam | İç link (geçiş) | Benzersiz hedef | Kırık | Redirect'e düşen |
|---|---|---|---|---|
| 46 yazının tamamı | **829** | **187** | **0** | 27 yazıda `/tercih-robotu` |
| Denetlediğim 5 dosya | 27 + 17 + 53 + 37 + (canlı yazı) | — | **0** | **0** |
- `/bolum/*` (68 benzersiz) ve `/universite/*` (69 benzersiz) hedeflerinin tamamı DB'den üretilebilen gerçek sayfalara çıkıyor.
- `/il/*` kullanımı yok (T7 tuzağı).
- Dış kaynak adreslerinden dördü bu sabah tek tek açıldı (aşağıda) — hepsi 200.
## (g) Teyitler (kaynak URL + ne doğrulandı)
| İddia (yazı) | Kaynak | Sonuç |
|---|---|---|
| YÖK 17 Şub 2026: 2023–2025'te 1.090.014 → 843.547, −246.467 (−%23); "aşırı kalabalık sınıflar…" cümlesi; "**2026 yılından itibaren vakıf üniversitelerimiz için de geçerli olacaktır**"; "başta hukuk, psikoloji, eczacılık, diş hekimliği ve mimarlık…" (`hangi-bolumlerin…`) | [yok.gov.tr/tr/news/…-OlqxR](https://www.yok.gov.tr/tr/news/yuksekogretim-kurulu-baskani-ozvar-stratejik-kontenjan-donusumunu-acikladi-OlqxR) | **Dördü de sayfada, birebir** [D] — yazının omurgası ayakta |
| 2547 s.k. md. 7: program açma / öğrenci alma / **öğrenci alımını durdurma** YÖK kararıdır; kontenjan değerlendirmesi **Yükseköğretim Genel Kurulu**'nda; lisansta ilgili alandan **kadrolu en az 3 öğretim üyesi ve 1 araştırma görevlisi (vakıf için)** (`hangi-bolumlerin…`) | [egitim.yok.gov.tr/tr/page/491](https://egitim.yok.gov.tr/tr/page/491) | **Üçü de sayfada, birebir** [D]. Yazının parantezlemesi ("araştırma görevlisi şartı vakıflarda") kaynağın parantezine uyuyor |
| ÖSYM kılavuzu tercih süresi içinde **yeniden yayımlanır**, ilk hâli "ön bilgi" (`rehber-ogretmenler…`) | [osym.gov.tr/2026yks-…-kilavuzunun-yayimlanmasi](https://www.osym.gov.tr/2026yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzunun-yayimlanmasi) | **Açıldı, 21 Temmuz 2026 tarihli, cümle yerinde** [D] |
| 2026-YKS yerleştirme sonuçları **18 Ağustos 2026** (iki yazı) | [osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi](https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi) | **Açıldı, tarih teyit** [D] |
| YÖK 1 Tem 2026: 2026-2027'de "**7'si lisans, 9'u ön lisans olmak üzere toplam 16 yeni program**" (`rehber-ogretmenler…`) | [yok.gov.tr/tr/news/…-ADkaS](https://www.yok.gov.tr/tr/news/yuksekogretim-kurulu-gelecegin-mesleklerine-gore-yuksekogretimi-yeniden-yapilandiriyor-ADkaS) | **Açıldı, cümle birebir** [D] |
| YÖK Atlas sunucudan **945 bayt** boş iskelet döndürüyor (`rehber-ogretmenler…`) | `curl -s -o /dev/null -w "%{size_download}" https://yokatlas.yok.gov.tr/` | **945** [D] — yazının ölçümü birebir doğru |
**Prompt injection kontrolü:** açılan beş sayfanın hiçbirinde bana yönelik talimat yok; hepsi veri olarak kullanıldı.
## (h) Teyit edilemeyen / genellenen / dokunulmayan
1. **Kılavuz PDF'lerinin sunucu damgaları** (`rehber-ogretmenler…:60`: 4 Ağustos 2026 / ~10,2 MB ↔ 21 Temmuz 2026 / ~12,2 MB). Dosya indirmek yasak, bu ortamdan başlık bilgisini okuyamadım [K]. **Dokunmadım** — yazı zaten "22 Eylül 2026'da ölçtük" diyerek iddiayı kendi ölçümüne ve tarihe bağlıyor, daha iddialı hâle getirilmedi. Yazının **tezi** (kılavuz yeniden yayımlanır) ÖSYM duyurusuyla bağımsız olarak teyit edildi [D], yani tez damgalara bağlı değil.
2. **`resmigazete.gov.tr` ve `mevzuat.gov.tr`** bu ortamdan yine açılamadı (TLS zinciri) [K]. `rehber-ogretmenler…` bu iki kaynağın **içeriğine dayanan tek bir rakam ya da madde vermiyor** ve bunu yazıda açıkça söylüyor — CEO eşiği md. 3 karşılanıyor, düzeltme gerekmedi.
3. **`bolumumu-sevmedim…`'in tek kaynağı** (`egitim.yok.gov.tr/tr/page/492`) açılmadı denenmedi — yazı o sayfadan **hiçbir madde ya da rakam alıntılamıyor**, yalnız "hangi yönetmelikte aranacağını" söylüyor ve ayrıntıyı yedi kapı yazısına bırakıyor. Yönetmelik maddelerinin denetimi önceki kopyanın `ek-madde-1` / `universitede-ilk-hafta` geçişinde yapıldı (EK'ten önceki (c) bölümü).
4. **ÖSYM'nin kurum grubu toplamları ile kendi havuzumuz arasındaki ~9 bin kişilik devlet lisans farkının sebebi çözülemedi** [D: fark ölçüldü, sebep ölçülemedi]. Açıköğretim eklenince toplam 279.693 olup bu kez ÖSYM'yi aşıyor. Bu yüzden `hangi-bolumlerin…`'in "Türkiye geneli resmî toplamlar bu yazıda yok" kararı **doğru karardır**, dokunulmadı; `bos-kontenjanlar`'ın kaynak satırına ise farkın **büyüklüğü** yazıldı, sebebi yazılmadı.
5. **Diğer 11 yeni yazıya ve `veliler-icin-tercih-rehberi`'ye dokunulmadı** (başka ajanın/Bilal'in kapsamı). `AGENTS.md`, `docs/ekip/KARARLAR.md` ve `src/` yalnızca **okundu**.
## (i) Yayımlanabilir / yayımlanmaz hükmü — yazı yazı
CEO'nun altı maddesi: **1** rakam yeniden üretilebilir · **2** yöntem kutusu (rakamdan önce) · **3** açılamayan kaynağa dayanan cümle yok · **4** vaat dili yok · **5** ayrım cümlesi ilk 200 kelimede · **6** teknik (3 frontmatter alanı, 1 mermaid + `%% aria:`, ≥1 tablo, ölü link yok).
| # | Yazı | 1 | 2 | 3 | 4 | 5 | 6 | Hüküm |
|---|---|---|---|---|---|---|---|---|
| 12 | `ayni-bolum-farkli-universite-siralama-farki` | ✔ (120+ hücre birebir) | ✔ (7 adımlık eleme tablosu + dört zayıf nokta, rakamdan önce) | ✔ | ✔ | ✔ (102. kelime) | ✔ (8 tablo, 53 link, 0 kırık) | **Yayımlanabilir** |
| 13 | `hangi-bolumlerin-kontenjani-azaldi` | ✔ (bant sınırı + payda cümlesi düzeltildi) | ✔ (genişletildi) | ✔ | ✔ | ✔ (114. kelime) | ✔ (7 tablo, 37 link, 0 kırık) | **Yayımlanabilir** |
| 14 | `rehber-ogretmenler-icin-veri-kaynaklari` | ✔ (tek DB rakamı birebir; 234↔243 uzlaştırıldı) | ✔ (ayrı "Bu yazıdaki rakam nasıl hesaplandı?" bölümü + tam SQL) | **kısmi** — PDF damgaları doğrulanamadı ama iddia tarihli/ölçüme bağlı ve tez bağımsız teyitli | ✔ | ✔ | ✔ (3 tablo + kaynak durumu tablosu, 27 link, 0 kırık) | **Yayımlanabilir** |
| 15 | `bolumumu-sevmedim-hangi-kapilar-var` | — DB rakamı yok | — gerekmiyor | ✔ (kaynaktan alıntı yok) | ✔ | ✔ (9. satır) | ✔ (1 tablo, 17 link, 0 kırık) | **Yayımlanabilir** |
**Dördünün de hükmü: yayımlanabilir.** Kesilmesi gereken yazı çıkmadı; kesilmesi gereken **bir açıklama cümlesi** çıktı (b.1) ve kesildi. Ayrıca canlıdaki `bos-kontenjanlar-ne-anlatiyor`'da **yayımlanmış** bir yanlış açıklama bulundu ve düzeltildi (b.3).
## Bilal'den istenen (3 madde)
1. **Canlı yazıya dokundum, gözden geçir.** `content/rehber/bos-kontenjanlar-ne-anlatiyor.md` kaynak satırındaki yanlış açıklama ("YÖK Atlas kontenjanları yerleştirme sonrası eklenen kontenjanları da içerir") ve "birkaç yüz kişilik fark" ifadesi düzeltildi; değişiklik **commit edilmedi**, çalışma ağacında duruyor. Tek paragraf, tek okuma — **~2 dk**.
2. **`kontenjan` kolonu artık üç yazıda üç kez düzeltildi; şema tarafında bir kez düzeltilsin.** Payda (`kontenjan` = yalnız genel kontenjan) ile pay (`yerlesen` = dört kota) uyuşmuyor ve 2026 için doğru payda veride **yok** (`gk/obk/sgy/dprm` kolonları yalnız 2025). Rehber yazıları artık doğru anlatıyor; `veri-muhendisi`/`cto` kuyruğuna tek satır açman yeter — **~1 dk karar**.
3. **Kalan çapraz link işine onay.** Bu dört yazıya diğer 11 yeni yazıdan **gelen** link hâlâ yok (kapsam dışıydılar) ve 27 mevcut yazıda `/tercih-robotu` 301'e gidiyor. İkisi de tek geçişlik mekanik iş; onay verirsen tek `fix(rehber): iç link örgüsü` commit'i olarak hazırlarım (içerik değişmez) — **~1 dk karar**.

View File

@@ -0,0 +1,67 @@
# Veli yazısının kapanışı — `veliler-icin-tercih-rehberi.md`
**Kapsam:** tek dosya (`content/rehber/veliler-icin-tercih-rehberi.md`). CEO kararı §3 "Kodsuz içerik işi (1)", marka raporu §2.4 (envanter satırı: "Veli rehber yazısı → CTA'sı öğrencinin → veli için ölü uç"). Commit atılmadı, `git add` yapılmadı; dosya çalışma ağacında değiştirilmiş hâlde bırakıldı.
## Özet (5 madde)
1. Yazının **sonuna** tek bir H2 bölümü eklendi: "Listeyi çocuğunuzla birlikte nasıl okursunuz?" (içinde iki H3). Mevcut şema, başlıklar, paragraflar ve kapanış cümlesi **hiç değiştirilmedi**.
2. Frontmatter'a yalnızca `guncelleme: 2026-09-22` eklendi (`baslik`/`aciklama`/`tarih` aynen duruyor; `src/lib/rehber.ts:167-176` bu alanı doğruluyor ve `guncelleme >= tarih` koşulu sağlanıyor).
3. Yazının altına **otomatik** basılan `CtaSiraForm` (`rehber-makale.tsx:112-116`) artık gövdede açıkça anlamlandırılıyor: kutu veliden kendi sıralamasını istemiyor, çocukla birlikte doldurulacak yer olarak tarif ediliyor. Kod tarafına dokunulmadı.
4. Yazıya bugüne kadar olmayan **bir karşılaştırma tablosu** girdi: hangi soruyu araç, hangisini velinin kendisi cevaplayabilir (dürüst konumlandırma; ürünün cevaplamadıkları açıkça "Yok" yazıyor).
5. Garanti/vaat dili yok: eklenen bölümde "yerleşir", "kazanır", "garanti", "kesinlikle" geçmiyor (tarama temiz). Dilim adı `src/lib/risk.ts:21-25` `DILIM_ETIKET` ile uyumlu → **Güvenli** (ham `garanti` anahtarı kullanıcıya basılmadı).
## Otomatik CTA'yı anlamlandıran cümle
> "Bu yüzden yazının hemen altında sıralama soran bir kutu göreceksiniz — o kutu sizden kendi sıralamanızı istemiyor; çocuğunuzun yanına oturduğunuzda **birlikte doldurmanız** için orada. Sıralamayı o yazsın, listeyi beraber okuyun."
Bileşenin ekranda yazdığı metin ("Sıralamana yakın programlar hangileri? Saniyede gör." + buton "Sıralamanı gir, programları gör", `src/features/sihirbaz/components/cta-sira-form.tsx:418-432`) öğrenciye "sen" diye hitap ediyor. Gövde cümlesi bunu **çelişki değil, davet** hâline getiriyor: metin veliye "sen" denen kutunun muhatabının çocuğu olduğunu söylüyor, dolayısıyla kod değişmeden ölü uç kapanıyor.
## Eklenen bölümün iskeleti
- **Açılış paragrafı** — ürün veli için değil, öğrenciyle veli için birlikte; sıralamayı giren çocuk, listeyi okuyan ikisi + yukarıdaki CTA cümlesi.
- **Fayda paragrafı** — tartışmanın "bence şu bölüm daha iyi"den satır satır konuşulabilir hâle gelmesi; hayal/dengeli/güvenli dağılımının ekranda görülmesi; `/meraklisina` linki; "ekran ne yapacağınızı söylemez, masaya ortak metin koyar" sınırı.
- **Tablo (H3)** — "Hangi soruyu ekran, hangisini siz cevaplarsınız?" 6 satır; 2'si Araç, 4'ü Siz/Çocuğunuz/İkiniz.
- **Dört iyi soru (H3)** — dört yıllık toplam maliyet · barınma · "bu bölümü neden istiyorsun" · "bölüm mü, üniversite mi, şehir mi". Hepsi ürünün cevaplamadığı, velinin cevaplayabileceği sorular.
## Doğrulanan ürün iddiaları (kod kanıtı)
| Yazıdaki ifade | Kanıt | Not |
|---|---|---|
| "24 satırlık liste" | `src/lib/rapor-havuzu.ts:25,30` (`HEDEF = 24`; 5 hayal / 13 dengeli / 6 garanti) | Tam |
| "hayal, dengeli ya da güvenli dilimlerinden birinde" | `src/lib/risk.ts:21-25` | Görünen ad tek kaynaktan |
| "gerekçe … ücretsiz denemede ilk üç satırda açık, kişisel analizin tamamı pakette" | `src/lib/rapor-maske.ts:12` (`ACIK_SATIR = 3`), `rapor-listesi.tsx:300-330` (`gerekce` satır detayında, kilitliyken "Kişisel analiz pakette") | **İlk taslakta "her satırın gerekçesi listede yazılı" yazmıştım; maske nedeniyle bu paketsiz kullanıcı için yanlıştı, düzeltildi.** |
| "geçmiş yıl taban sıralamalarıyla" | `src/lib/risk.ts:33-49` (efektif sıra = son yıl, yoksa bir önceki yıl) | Kontenjan iddiası **çıkarıldı** — rapor tablosunda kontenjan sütunu yok (`grep "kontenjan" rapor-listesi.tsx` = 0) |
## Link doğrulaması (hepsi mevcut)
`/rehber/yurt-burs-ve-yillik-maliyet` · `/rehber/kyk-burs-mu-kredi-mi` · `/rehber/bolum-mu-universite-mi-sehir-mi` · `/rehber/devlet-mi-vakif-mi` → dosyalar `content/rehber/` altında var. `/meraklisina` → `src/app/meraklisina/page.tsx`. Tablo GFM ile basılıyor (`src/lib/rehber.ts:114-123`), H3 kullanımının yazıda öncülü var (`content/rehber/ek-yerlestirme-sonuclari-ve-kayit.md`).
## Çıkarılan / yazılmayan iddialar
- **Yerleşme olasılığı/garantisi:** hiç geçmiyor; "birlikte okursunuz", "konuşursunuz" fiilleriyle kalındı.
- **"Veliye özel bir yüzey/PDF var"** demedim — `/paket` özellik listesindeki "Veliyle paylaşılabilir PDF rapor" vaadini bu yazıda tekrarlamadım; paylaşma düğmesi henüz yok (marka Ö1 ertelendi), olmayan akışı tarif etmek olurdu.
- **Kontenjan verisi** iddiası (yukarıda).
- **Fiyat/paket adı** hiç geçmiyor; yalnızca "kişisel analizin tamamı pakette" denerek maskenin gerçeği söylendi.
## Bu yazıda gördüğüm, dokunmadığım sorunlar (rehber-editörü işi)
1. Yazı **"Kısa cevap:" ile başlamıyor** (standart bunu istiyor) ve **kaynaklar listesi yok**. Yapı bozulmasın diye elleşmedim.
2. İlk H2 "Görev dağılımı" **soru biçiminde değil**.
3. Son paragraftaki link `/tercih-robotu` — sayfa yok, `next.config.ts:80` kalıcı yönlendirmeyle `/#hero-form`'a gidiyor. Çalışıyor ama iki adım; editör doğrudan hedefe çevirebilir.
4. `## Listeyi neden öğrenci doldurmalı?` bölümü veliye yazılmış bir yazının içinde **öğrenciye "sen" diye hitap ediyor** ("ÖSYM **seni** yerleşebildiğin en üst tercihe koyar"). Benim eklediğim bölüm yazının hâkim "siz" hitabını izledi; bu eski tutarsızlık editöre kalıyor.
5. Yazı `/rehber/yks-tercih-takvimi-2026` ve `/rehber/universite-kayit-rehberi-2026` linklerini "tarihleri takvime işleyin" diyerek veriyor — sezon bitti; G4/sezon-dışı bant çalışmasıyla birlikte gözden geçirilmeli.
## Marka ajanına notum
- §2.4'teki H4 maddesi ("CTA'yı veliye çevir") **kod tarafında hâlâ açık**; ben yalnızca metinle köprü kurdum. Kod işi yapılacaksa artık seçenek şu: CTA'yı veliye çevirmek yerine **olduğu gibi bırakıp** gövde cümlesini kanon kabul etmek daha ucuz — çünkü aynı bileşen 40+ öğrenci yazısında da basılıyor (`rehber-makale.tsx:113`), veli için özelleştirmek yazı başına CTA seçimi gerektirir (CEO bunu G4 kapsamı dışında bıraktı).
- Bu yazı artık ürünün **"kullanan öğrenci, birlikte okuyan veli"** konumunu sitede açıkça söyleyen tek yüzey. Ö1 ("Listeyi veline gönder" düğmesi) hayata geçtiğinde bu bölüme tek cümlelik bir bağlantı eklenmeli — şimdiden yazmadım, olmayan düğmeyi tarif etmemek için.
- Tablodaki "Yok" satırları bilinçli bir zayıflık beyanı. Marka dili "her şeyi biz çözeriz"e kayarsa bu tablo ilk çelişecek yer olur; bilerek böyle bırakıldı.
## Bilal'den istenen
1. Eklenen bölümü bir kez oku, özellikle CTA'yı tarif eden cümlenin sende "kutu benden sıralama istiyor" hissini kaldırıp kaldırmadığına bak (3 dk).
2. Karar: veli yazısının altındaki CTA kod tarafında veliye özelleştirilsin mi, yoksa bu metin köprüsü kalıcı çözüm mü sayılsın (2 dk).
---
22 Eyl 02:32 — bölüm başka bir ajanın `git reset`i sonrası kaybolmuştu; aynı metinle birebir yeniden yazıldı (frontmatter `guncelleme` dâhil, dosya 89 satır).

View File

@@ -0,0 +1,127 @@
# 22 — Yazar raporu: `rehber-ogretmenler-icin-veri-kaynaklari`
**Rol:** rehber-yazari · **Tarih:** 22 Eylül 2026 gece vardiyası · **Şartname:** `02-seo-konu-plani.md` §2 konu #17 · **Kalite eşiği:** `05-ceo-kararlari.md` §C(d)
**Dokunulan tek dosya:** `content/rehber/rehber-ogretmenler-icin-veri-kaynaklari.md` (yeni). Commit atılmadı, `git add` yapılmadı, `src/` altına dokunulmadı, editördeki 10 yazı açılmadı.
## Özet (5 madde)
1. **Yazı teslim edildi:** ~3.450 kelime, 1 `flowchart TD` (`%% aria:` + `%% altyazi:` var), **3 tablo** (kaynak haritası · rakam türü × sınıfta nasıl söylenir · erişim durumu tablosu), 8 soru biçimli H2, "Kısa cevap:" ile başlayan tek paragraflık cevap, sonda yöntem kutusu + kaynaklar.
2. **Yazının namus noktası tutturuldu:** 16 adres 22 Eylül 2026'da tek tek açıldı. 13'ü açıldı, **3'ü açılmadı** (Resmî Gazete, mevzuat.gov.tr, eski ÖSYM `TR,NNNN/...` sayfaları) ve açılmayanların içeriğine dayanan **hiçbir iddia yazılmadı** — yazıda açıkça "erişilemedi" diye duruyor.
3. **Yazının en güçlü, rakiplerde olmayan iki bulgusu ölçülerek elde edildi:** (a) ÖSYM tercih kılavuzunun temmuz ve ağustos sürümleri **iki ayrı dosya** ve ikisi de hâlâ 200 dönüyor; (b) YÖK Atlas'ın sunucudan gelen HTML'i **945 bayt** ve dört farklı adres aynı boş iskeleti veriyor. İkisi de `curl` ile doğrulandı, kanıtı aşağıda.
4. **Tek DB rakamı var** (Psikoloji: 234 program, taban sırası 329–1.402.765) ve yazının içindeki **tam SQL ile bağımsız yeniden üretildi** — CEO §C(d).1 kapısı geçildi. Yöntem kutusu yazıda (§"Bu yazıdaki rakam nasıl hesaplandı").
5. **Ürün bahsi tek paragraf** ve MEB'in ücretsiz danışmanlık birimleriyle rekabet etmediğimizi açıkça yazıyor; CTA yok, "bizi kullanın" yok, yerleşme vaadi/olasılığı yok.
---
## 1. Açıp doğruladığım adresler (22 Eylül 2026)
### Açıldı
| Kaynak | Adres | Ne doğrulandı |
|---|---|---|
| ÖSYM tercih kılavuzu sayfası | `osym.gov.tr/2026-yuksekogretim-kurumlari-sinavi-yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzu` | HTTP 200. Sayfadaki bağlantı başlıkları ham HTML'den çekildi: "2026-Yükseköğretim Programları ve Kontenjanları Kılavuzu" (PDF), "Tablo-3" (XLS), "Tablo-4" (XLS) |
| ÖSYM kılavuz yayım duyurusu | `osym.gov.tr/2026yks-yuksekogretim-programlari-ve-kontenjanlari-kilavuzunun-yayimlanmasi` | 21 Temmuz 2026 tarihli; kılavuzun ön bilgi olduğunu ve tercih süresi içinde **yeniden yayımlanacağını** söylüyor |
| ÖSYM yerleştirme sayısal bilgileri | `osym.gov.tr/2026-yks-yerlestirme-sonuclarina-iliskin-sayisal-bilgiler` | HTTP 200. Bağlantılar: sayısal bilgiler PDF'i + "En Küçük ve En Büyük Puanlar (TABLO-3)" / "(TABLO-4)" XLSX |
| ÖSYM tablo adlandırmaları | `osym.gov.tr/2022yks-ek-yerlestirme-kilavuz-ve-tablolar` | HTTP 200. **Tablo-3 = "Merkezi Yerleştirme İle Öğrenci Alan Yükseköğretim Ön Lisans Programları"**, **Tablo-4 = "… Lisans Programları"**, ek belge "Tablo-3 ve Tablo-4'te Yer Alan Yükseköğretim Programlarının Koşul ve Açıklamaları" — ÖSYM'nin kendi bağlantı başlıklarından |
| YÖK Atlas | `yokatlas.yok.gov.tr` (+ `/lisans.php`, `/onlisans.php`, `/tercih-sihirbazi-t4.php`, `/tercih-sihirbazi-t3.php`) | Hepsi 200 ve hepsi **aynı 945 baytlık SPA iskeleti**; `<div id="root">` + `<noscript>Bu uygulamayı kullanabilmek için Javascript çalıştırılmasına izin vermelisiniz.` Resmî ad: "Yükseköğretim Program Atlası" |
| YÖK kurumsal | `yok.gov.tr` | 200 (`/tr`'ye yönleniyor) |
| YÖK yeni program haberi | `yok.gov.tr/tr/news/…-yeniden-yapilandiriyor-ADkaS` | 1 Temmuz 2026 tarihli; 16 yeni program = 7 lisans + 9 önlisans |
| YÖK Eğitim-Öğretim Dairesi duyuruları | `egitim.yok.gov.tr/tr/announcements-all` | 200; en yeni duyurular 18 ve 16 Eylül 2026 tarihli |
| MEB ÖERHGM 2026 kılavuz duyurusu | `orgm.meb.gov.tr/www/yks-tercih-surecine-rehberlik-edecek-yeni-kilavuz/icerik/3642/tr` | 21 Temmuz 2026; "YKS Tercih Süreci Öğrenci ve Veli Bilgilendirme Kılavuzu"; PDF `…2026_07/…yks_kilavuz_2026.pdf` → 200 |
| MEB il örneği | `istanbul.meb.gov.tr/www/yks-tercih-danismanligi/icerik/3297` | 200 |
| MEBBİS | `mebbis.meb.gov.tr` | 200 (`/Default.aspx` giriş ekranı). **Oturum açılmadı** (protokol: hesap/şifre girme yasak) |
| KYGM | `kygm.gsb.gov.tr` | 200; ana sayfada eylül 2026 tarihli yurt/yedek yerleştirme duyuruları |
| Genç Bilgi Sistemi | `gencbis.gsb.gov.tr` | 200 → `/Account/EDevletLogin` |
### Açılmadı — ve bu yüzden içeriğine dayanan hiçbir cümle yazılmadı
| Kaynak | Ne oldu |
|---|---|
| `resmigazete.gov.tr` | DNS çözülüyor (212.174.186.1) ama bağlantı kurulmuyor: `curl` 25 sn zaman aşımı, `openssl s_client` hiç bağlanamadı, WebFetch "unable to verify the first certificate". **Harç/öğrenim ücreti cetveline dair hiçbir rakam yazılmadı.** |
| `mevzuat.gov.tr` | Aynı tablo (212.174.186.3). **Hiçbir yönetmelik maddesi alıntılanmadı;** yalnızca "yürürlükteki metin oradadır, üniversite CDN'indeki PDF eski olabilir" şeklindeki yöntem uyarısı kaldı. |
| `osym.gov.tr/TR,1900/tablo-4-…html` ve `osym.gov.tr/TR,2673/tablo-3-ve-tablo-4te-…html` | **HTTP 404.** Arama motoru hâlâ listeliyor. Yazıda "adres kırılır" bölümünün kanıtı olarak kullanıldı. |
| `yurtkur.gsb.gov.tr/…` ve `www.kyk.gov.tr/…` (KYGM **ana sayfasındaki** bağlantılar) | DNS çözülmüyor / bağlantı kurulmuyor. Yazıda "kurumun kendi sayfasındaki bağlantı bile kırılabiliyor" örneği olarak, "bizim bağlantımızdan açılmadı" kaydıyla kullanıldı. |
### Ölçülen kanıt (kopyalanabilir)
```
$ curl -sI -L https://cdn.osym.gov.tr/pdfdokuman/2026/YKS/TERCIH/kontkilavuz_yktd21072026.pdf
HTTP/2 200 · content-length: 12214577 · last-modified: Tue, 21 Jul 2026 14:01:13 GMT
$ curl -sI -L https://dokuman.osym.gov.tr/web/2026/8/2026-yuksekogretim-programlari-ve-kontenjanlari-kilavuzu-90wzzd-04155310.pdf
HTTP/1.1 200 OK · Content-Length: 10185420 · Last-Modified: Tue, 04 Aug 2026 12:53:10 GMT
$ curl -sI -L https://cdn.osym.gov.tr/2026-yks-yerlestirme-sonuclarina-liskin-sayisal-bilgiler-bxo4wg-18092428.pdf
HTTP/2 200 · content-length: 279499 · last-modified: Tue, 18 Aug 2026 06:55:13 GMT
$ curl -s https://yokatlas.yok.gov.tr/ | wc -c
945 # /lisans.php, /onlisans.php, /tercih-sihirbazi-t3.php, /tercih-sihirbazi-t4.php de aynı
```
Kılavuzun iki sürümünün **aynı anda ayakta olması** yazının en somut "tuzak" iddiasının dayanağı: temmuzda indirilen dosya tercih haftasında bağlayıcı belge değil.
---
## 2. Kullanılan SQL (yazının içindekiyle birebir aynı)
```sql
SELECT isim,
COUNT(*) AS program_sayisi,
MIN(sira2026) AS en_kucuk_taban_sirasi,
MAX(sira2026) AS en_buyuk_taban_sirasi
FROM programs
WHERE onlisans = 0
AND son_kilavuz_yili = 2026
AND sira2026 IS NOT NULL
AND isim = 'Psikoloji';
```
`sqlite3 -readonly data/yokatlas.db` → `Psikoloji | 234 | 329 | 1402765`. İki kez koşuldu, aynı sonuç.
Kontrol amaçlı koşulan (yazıya girmeyen) geniş sürüm, aynı filtreyle `isim IN ('Psikoloji','Hukuk','Tıp','İşletme','Hemşirelik')`: İşletme 277 / 128 / 1.414.685 · Hemşirelik 270 / 55.118 / 1.090.898 · Psikoloji 234 / 329 / 1.402.765 · Tıp 206 / 1 / 49.623 · Hukuk 127 / 105 / 99.505. Yazıda yalnız Psikoloji kullanıldı.
Veri tarihi: `KATALOG_VERI_TARIHI = "2026-09-21"` (`src/lib/seo.tsx:24`); `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z`. İkisi de yazıda geçiyor.
---
## 3. Çıkardığım / yazmadığım iddialar
1. **"19.566 Üniversite Tercih Danışmanlığı Birimi."** Arama özetlerinde 2026 bilgisi gibi dolaşıyor; kaynağını açtığımda **20 Temmuz 2025** tarihli MEB duyurusuna dayanıyordu (2023 duyurusunda aynı rakam 11.181). 2026 için doğrulanmış birim sayısı bulamadım → **sayı yazılmadı**, yerine "birim sayıları yıldan yıla değişir, o yılın duyurusundan alın" uyarısı kondu.
2. **Harç/öğrenim ücreti cetvelinin içeriği.** Resmî Gazete açılmadığı için hiçbir rakam, hiçbir karar numarası, hiçbir tarih yazılmadı.
3. **Üniversite yönetmeliklerine dair somut madde.** mevzuat.gov.tr açılmadığı için tek bir madde bile alıntılanmadı; yalnızca "yürürlükteki metin orada, CDN'deki PDF eski olabilir" yöntem uyarısı kaldı.
4. **Tablo-3/Tablo-4 tanımını kılavuz PDF'inin kendi metninden** alamadım — bu makinede PDF metin çıkarıcı yok (`pdftotext`/`mutool`/`qpdf` kurulu değil), `Read` aracı da poppler olmadığı için PDF açamadı. Tanımlar ÖSYM'nin **kendi canlı sayfasındaki bağlantı başlıklarından** alındı (2022 ek yerleştirme sayfası) ve kaynak tablosunda bu şekilde belirtildi. *Yayın öncesi kılavuz PDF'inin ilk sayfalarından gözle teyit edilirse daha sağlam olur — editöre not.*
5. **YÖK Atlas'ta yıl seçicinin nasıl çalıştığı.** Sayfa JS ile çizildiği için arayüzü göremedim; "yıl seçiciyi şuradan değiştirirsiniz" gibi bir cümle **yazılmadı**. Yalnızca ölçtüğüm şey yazıldı: HTML'de veri yok, dört adres aynı iskeleti dönüyor, dolayısıyla adres/ekran görüntüsü yıl bilgisini taşımaz.
6. **"2026-YKS Ek Yerleştirme: Kılavuz ve Tablolar" sayfası** (`osym.gov.tr/2026yks-ek-yerlestirme-kilavuz-ve-tablolar`) 200 dönüyor ama ham HTML'inde YKS ek yerleştirme tablolarına değil, e-YDS / HMGS-İYÖS gibi alakasız belgelere bağlantı veriyor. Neden olduğunu çözemedim → **yazıda bu sayfaya hiç atıf yapılmadı**. (2022 karşılığı düzgün çalışıyor.)
7. **Yerleşen/kontenjan toplam rakamları** (730 bin yerleşen, 45.033 boş kontenjan vb.) arama özetlerinde geçiyordu; PDF'i açamadığım için **hiçbiri yazıya alınmadı**. Yazı bu belgenin *ne verdiğini* anlatıyor, rakamını vermiyor.
---
## 4. Şartnameden sapmalar (bilerek, gerekçeli)
- **Hitap "siz".** Standart ton öğrenciye "sen" diyor; bu yazının okuru meslektaş konumundaki rehber öğretmen. `veliler-icin-tercih-rehberi` yazısındaki "siz" hattını izledim. Editör aksini isterse tek geçişte dönüştürülebilir.
- **Plan §17'nin "5 slaytlık sunum iskeleti" maddesini yazmadım.** Yerine "20 dakikada bir öğrenciye nasıl yardım edilir" protokolü (orkestratörün açıkça istediği bölüm) ve öğrenciye bırakılacak üç bilgilik kontrol listesi kondu. Sunum iskeleti ayrı bir yazı/indirilebilir olarak daha değerli — backlog önerisi.
- **Plan §17'deki "atıf/link rica eden kapanış"** yumuşatıldı: reklam gibi durmasın diye tek cümle ("bağlantı vermeniz yeterli, izin almanıza gerek yok").
- Planın istediği `/bolumler` ve `/universiteler` iç linkleri ürün paragrafında var; `#1` ve `#6`'ya link **verilmedi** çünkü bu yazının konusu kaynak metodolojisi, taban trendi değil — kanibalizasyon yaratmıyor.
## 5. Teknik kontrol (CEO §C(d) 6 maddesi)
| Kriter | Durum |
|---|---|
| 1 · Rakam kendi filtresiyle yeniden üretilebiliyor | ✅ tek DB rakamı, SQL yazıda, iki kez koşuldu |
| 2 · Yöntem kutusu | ✅ tablo, yıl kolonu, filtre, satır sayısı, veri tarihi |
| 3 · Açılamayan kaynağa dayanan cümle yok | ✅ 3 kaynak "erişilemedi" diye işaretli, içerik iddiası sıfır |
| 4 · Vaat dili yok | ✅ `yerleşirsin/garanti/kesin/atanırsın` grep'i temiz; istihdam iddiası yok |
| 5 · Ayrım cümlesi | ✅ ilk 200 kelimede "bu yazı bir kaynak haritası ve kullanım kılavuzu"; mevcut hiçbir yazıyla aynı niyeti hedeflemiyor |
| 6 · Teknik | ✅ 3 frontmatter alanı, 1 mermaid + `%% aria:` + `%% altyazi:`, 3 tablo, 17 iç linkin tamamı dosya/route olarak doğrulandı, `/tercih-robotu` ve `/il/*` yok |
**İç link doğrulaması:** 17 hedefin 17'si var (`content/rehber/*.md` ya da `src/app/*`). Bunlardan ikisi bu geceki dalganın yazıları: `/rehber/universitede-ilk-hafta-…` ve `/rehber/yeni-acilan-bolumler-nasil-degerlendirilir`. Benim yazım **bir sonraki dalgada** yayımlanacağı için sıra doğru; yine de o iki yazı yayından düşerse bu iki link ölür — editör kontrol etsin.
## 6. Engeller
- Resmî Gazete ve mevzuat.gov.tr bu ağdan erişilemiyor (muhtemelen coğrafi/IP kısıtı). Yazının iki satırı bu yüzden "teyit edilmedi" durumunda.
- PDF metin çıkarma aracı yok (`poppler` kurulu değil) → ÖSYM kılavuz metninden doğrudan alıntı yapılamıyor. Gelecek yazılar için de darboğaz.
- Web sayfalarında bana yönelik talimat görülmedi. Hiçbir dosya indirilmedi; `WebFetch` bir PDF'i kendi önbelleğine aldı, okunmadı ve kullanılmadı.
## Bilal'den istenen
1. **Yok.** Yazı editör kuyruğuna hazır; yayın kararı zaten `rehber-editoru` + orkestratör hattında.

View File

@@ -0,0 +1,63 @@
# 23 — Yazar raporu: `bolumumu-sevmedim-hangi-kapilar-var` (hub yazısı)
**Rol:** rehber-yazari · **Dosya:** `content/rehber/bolumumu-sevmedim-hangi-kapilar-var.md` (tek dokunulan dosya) · **Commit atılmadı, `git add` yapılmadı.**
**Şartname:** `02-seo-konu-plani.md` §0 + §2 #11 · `05-ceo-kararlari.md` §C(d) · `00-kurucu-brief.md` · `PROTOKOL.md`
## Özet (5 madde)
1. Yazı yazıldı ve **uzunluk sınırı tutuyor: 539 kelime** (gövde, mermaid bloğu ve "Kaynaklar" hariç; kaynaklar dahil 606, mermaid dahil değil). SEO planının koyduğu tavan 600 kelimeydi — hub, bağladığı beş yazıyı kanibalize etmeyecek genişlikte kaldı.
2. **Hiçbir tarih, süre, yüzde, kontenjan ya da mevzuat maddesi yazılmadı.** Yatay geçiş pencereleri, Ek Madde-1 koşulları, kayıt sildirme/OBP mekaniği, kayıt dondurma gerekçeleri — hepsi bilerek linke bırakıldı (aşağıda liste). Böylece hem kanibalizasyon hem hatalı kural riski sıfırlandı.
3. **Yedi kapı**, biri mermaid karar şemasında (7 çıkış düğümü), biri tabloda (kapı × kimin için uygun × kimin için değil × nereye bak), biri de tek cümlelik tanıtım paragraflarında olmak üzere üç kez, çelişmeden anlatıldı. Şemada renk kullanılmadı; her çıkış düğümü **büyük harfli metin etiketiyle** başlıyor (BEKLE / ROTA / GEÇİŞ / EK MADDE-1 / SINAV / ARAŞTIR) — renk tek başına anlam taşımıyor kuralı fazlasıyla karşılanıyor.
4. **DB kullanılmadı, tek bir rakam verilmedi** — bu yazıda sorgu yok, dolayısıyla CEO'nun §C(d).1–2 kriterleri (rakamın yeniden üretilmesi, yöntem kutusu) devreye girmiyor. Vaat dili taraması temiz: "garanti", "kesin", "yerleşirsin", "atanırsın" geçmiyor (0 eşleşme).
5. **Engel:** `mevzuat.gov.tr` ve `resmigazete.gov.tr` bu ortamdan açılamadı (sertifika hatası / bağlantı zaman aşımı). Bu yüzden yönetmelik maddesi numarası **verilmedi**; kaynak olarak yalnızca açabildiğim YÖK sayfası kullanıldı.
## Doğrulanan bilgiler + kaynak URL'leri
| İddia | Nasıl doğrulandı | Hüküm |
|---|---|---|
| Yatay geçiş, ÇAP, yandal ve Ek Madde-1 aynı YÖK mevzuat çerçevesinde düzenleniyor; YÖK bunları "Yatay Geçişler ve Özel Öğrencilik" ve "Merkezi Yerleştirme Puanı İle Yatay Geçiş (Ek Madde 1)" başlıklarıyla yayımlıyor | Sayfa açıldı, 22 Eyl 2026: <https://egitim.yok.gov.tr/tr/page/492> | **[D]** — yazıdaki tek resmî atıf bu |
| Yönetmeliğin tam adı: "Yükseköğretim Kurumlarında Ön Lisans ve Lisans Düzeyindeki Programlar Arasında Geçiş, Çift Anadal, Yan Dal ile Kurumlararası Kredi Transferi Yapılması Esaslarına İlişkin Yönetmelik" | Aynı YÖK sayfasında bu yazımla geçiyor | **[D]** — ad yazıldı, **madde numarası yazılmadı** |
| Yönetmeliğin RG tarihi/sayısı (24.04.2010 / 27561) | Yalnızca arama özeti ve üniversite PDF kopyaları [A]; birincil kaynak açılamadı | **Yazıya alınmadı** |
| Ek Madde-1'in içeriği (not şartı yok, hak 1 kez, takvimi üniversite belirler) | `egitim.yok.gov.tr/tr/document/2853` PDF olarak geldi, metni okunamadı | **Yazıya alınmadı** — bu gece yazılan `ek-madde-1-puanim-yetiyor-mu` yazısına link verildi |
**Kullanılan SQL sorguları:** yok. Bu yazı `data/yokatlas.db`'ye dokunmuyor; içinde tek bir sayısal iddia yok ("yedi kapı" ifadesi hariç, o da yazının kendi yapısı). Risk dilimi terimi de geçmiyor, dolayısıyla `src/lib/risk.ts` ile çelişme yüzeyi yok.
## Bilerek yazılmayıp linke bırakılan ayrıntılar
| Ayrıntı | Nereye bırakıldı |
|---|---|
| Ek Madde-1'in koşulları, puan türü şartı, hakkın kaç kez kullanıldığı | `/rehber/ek-madde-1-puanim-yetiyor-mu` |
| Not ortalamasıyla yatay geçişin yarıyılları, kontenjan mantığı, ÇAP/yandal başarı şartları | `/rehber/yatay-gecis-cap-yandal` |
| Kayıtlıyken sınava girmenin kuralları, "kayıtlıyım" beyanı, ilişik kesme anı | `/rehber/universite-okurken-tekrar-yks` |
| OBP/kırık OBP mekaniği, kaydı sildirmenin bedeli | `/rehber/mezuna-kalmak-mi-kayit-olmak-mi` |
| Önlisans–lisans karşılaştırması ve DGS köprüsü | `/rehber/onlisans-mi-lisans-mi` |
| Ders kaydı, muafiyet, kayıt dondurma işlemleri | `/rehber/universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma` |
| Mezuniyet sonrası/iş araştırma yöntemi | `/rehber/bolumun-is-imkanini-nasil-arastirirsin` |
| **Her türlü başvuru tarihi** (yatay geçiş, kayıt dondurma, sınav başvurusu) | Hiçbiri yazılmadı; yazı "tarihler üniversiteden üniversiteye değişir, kendi akademik takvimine bak" diyor |
| DGS (#12) | Bu gece o slug (`onlisanstan-lisansa-dgs-yol-haritasi`) yazılmadı → **link verilmedi**, ölü link yok. Yazı yayına girerse editör 6. kapıya tek cümle ekleyebilir |
## İç link denetimi (hepsi doğrulandı, ölü link yok)
`content/rehber/` altında dosya varlığı ve route kontrolü yapıldı:
- `/rehber/universitede-ilk-hafta-ders-kaydi-muafiyet-kayit-dondurma` ✅ · `/rehber/yatay-gecis-cap-yandal` ✅ · `/rehber/ek-madde-1-puanim-yetiyor-mu` ✅ · `/rehber/universite-okurken-tekrar-yks` ✅ · `/rehber/mezuna-kalmak-mi-kayit-olmak-mi` ✅ · `/rehber/onlisans-mi-lisans-mi` ✅ · `/rehber/bolumun-is-imkanini-nasil-arastirirsin` ✅ (route: `src/app/rehber/[slug]`)
- `/bolumler` ✅ (`src/app/bolumler`)
- `/tercih-robotu` **kullanılmadı** (301), `/il/*` **kullanılmadı** (sayfa yok).
Teknik kontrol: frontmatter 3 zorunlu alan ✅ · 1 adet ```mermaid `flowchart TD` ✅ · `%% aria:` ✅ · `%% altyazi:` ✅ · 1 tablo (7 satır) ✅ · "Kısa cevap:" açılışı ✅ · H2'lerin üçü de soru biçimi ✅ · sonda erişim tarihli "Kaynaklar" ✅.
## Başka yazılarda gördüğüm, dokunmadığım şey (editöre not)
- `/tercih-robotu` linki **en az 10 mevcut yazıda** var (ör. `bolum-mu-universite-mi-sehir-mi.md:65`, `hedef-siralama-nasil-belirlenir.md:109`, `devlet-mi-vakif-mi.md:53`, `ek-yerlestirme-2026.md:57`, ayrıca bu gece yazılan `bilgisayar-mi-yazilim-muhendisligi-mi.md:160`). Ölü değil ama 301'e gidiyor ve CEO §C(d).6 yeni yazılar için yasaklıyor. Toplu düzeltme `rehber-editoru`'nun işi — ben dokunmadım.
## Engeller
1. `mevzuat.gov.tr` (WebFetch: sertifika doğrulanamadı; curl: 25 sn zaman aşımı) ve `resmigazete.gov.tr` (aynı) bu ortamdan açılamıyor. Yönetmeliğin madde numaraları ve RG künyesi bu yüzden yazıya girmedi — yazının işi zaten kural anlatmak değil.
2. `egitim.yok.gov.tr/tr/document/2853` PDF olarak döndü, metni çıkarılamadı.
3. Web sayfalarında bana yönelik talimat görülmedi.
## Bilal'den istenen
1. **Yayın öncesi tek kontrol:** yazının tonu — kaygılı 1. sınıf öğrencisine ne abartılı iyimser ne felaket dilinde konuşuyor mu? (2 dk, tek okuma)
2. Kapı listesine **DGS'nin ayrı bir kapı olarak** eklenip eklenmeyeceği: o yazı (#12) bu gece yazılmadı; yazıldığında 6. kapıya tek cümle eklenmesi yeterli. (1 dk karar)
3. Diğer yazılardaki `/tercih-robotu` (301) temizliğinin editöre iş olarak verilmesi. (1 dk)

View File

@@ -0,0 +1,204 @@
# 24 — CEO kapanış turu: açık kalan hiçbir satır yok
Talimat: Bilal — "buradaki tüm sıkıntıların giderilmesini istiyorum."
Kural: bu belgede **"ertelendi" yoktur**. Her satır üç durumdan biri: **KAPANIR** (bu gece/yarın yapılacak iş) · **RET** (bir daha açılmaz) · **TETİK** (ölçülebilir olay/tarih yazılı).
Biçim: ne · kim · ne zaman · bittiği nasıl anlaşılır.
## Durum düzeltmesi (05 raporundan sonra değişti)
| Ne | 05'te yazdığım | Şimdiki gerçek |
|---|---|---|
| `main` push | "18 commit ileride, push edilmemiş" | **Push edildi.** `origin/main = main = 9bd448b`; `git rev-list --count origin/main..main` = **0**. Kuyruk kalmadı |
| `.next` 1,4 GB | temizlenecek | **Dizin yok**, zaten silinmiş |
| Asıl disk yükü | bilinmiyordu | Desktop'ta 4 eski worktree: **2,3 + 2,4 + 2,4 + 0,93 GB**; `.claude/worktrees` 934 MB; pnpm store 5,8 GB. Boş alan **4,2 GB** |
Bilal'in sabah listesi bu yüzden kısaldı: push işi bitti, yerine içerik commit'i + disk geçti.
---
## A · §5'in tamamı — her satır kapatıldı
### KAPANIR (bu gece ya da yarın yapılır)
| # | Ne | Kim | Ne zaman | Bitti demek |
|---|---|---|---|---|
| A1 | `/rehber` index'i küme başlıklarıyla gruplanır — G4'ün kapsamı genişletildi (T33'ün kalan yarısı) | `yazilimci`, dal `icerik/rehber-kumeleri` | bu gece | 42 yazı en çok 6 küme başlığı altında; kümesiz yazı "Genel"e düşer ve build kırılmaz |
| A2 | Paket adı sezon-bağımsız olur: "Tercih Dönemi Paketi" → **"KolayTercih Paketi"** (`src/lib/credits.ts:7`) | `yazilimci`, dal `odeme/paket-adi` | bu gece yazılır, **merge Bilal'in test ödemesinden sonra** | `grep -rn "Tercih Dönemi Paketi" src/` = 0; iyzico sepet adı yeni adı taşır |
| A3 | `/sonuc` sayfasında `<h1>` yok — eklenir | `yazilimci`, dal `a11y/sonuc-h1` | yarın | `/sonuc` sunucu HTML'inde tam 1 adet `<h1>` |
| A4 | T34 — `programs.il` temizliği **analizi** (91 farklı değer, 110 boş satır, KKTC/yurt dışı karışık) | `veri-muhendisi`, dal yok (rapor + SQL) | bu gece | Rapor: boş `il` satırlarının kaynağı, 81 il dışı değerlerin listesi, düzeltme SQL'i ve etkilenen satır sayısı |
| A5 | Vakıf burs etiketi (burslu/%50/ücretli) DB'de nerede — kolon mu, isim eki mi, hiç yok mu | `veri-muhendisi`, aynı rapor | bu gece | Tek cümlelik cevap + varsa kırılım sorgusu |
| A6 | SEO planındaki yanlış `netler` çerçevesi düzeltilir: "yerleşenlerin ortalaması" → **"son yerleşen kişinin netleri"** (`02-seo-konu-plani.md` §2 #2 ve #15) | `seo-geo` | bu gece | İki madde düzeltilmiş; plan içinde "ortalama net" ifadesi kalmamış |
| A7 | Ödeme yüzeyinin metin ve ölçüm açıkları (G5 + G2) | `yazilimci`, ayrı dallar | bu gece | 05 raporundaki kabul kriterleri |
| A8 | Satıcı kimliği sayfası **placeholder'lı taslak** olarak hazırlanır (unvan/adres/vergi no/MERSİS alanları boş bırakılır) | `guvenlik-uyum`, dal `uyum/satici-kimligi` | yarın | Sayfa var, footer'dan linki var, 5 alan `TODO-BILAL` işaretli; Bilal bilgileri yazınca tek commit'le yayına hazır |
| A9 | Marka tescili engel kontrolü (TÜRKPATENT'te "kolaytercih" ve yakın yazımlar) | `marka` | bu gece | Sonuç: engel var/yok + varsa sınıf numarası |
### RET (bir daha gündeme gelmez)
| # | Ne | Gerekçe |
|---|---|---|
| R1 | **LGS alanı** | MEB'in ücretsiz, resmî, yapay zekâ destekli LGS robotu var. Ücretli bir ürünün rekabet edeceği yer değil |
| R2 | **Ayrı "veli sayfası"** (`/veli`) | Veliye ayrı bir sayfa açmak, tek bir veli okuru yokken ikinci bir giriş yüzeyi bakımı demek. Kanonik veli yüzeyi `veliler-icin-tercih-rehberi.md` yazısıdır (kapanışı bu gece veli diline çevrildi) + G4 ile o kümeye özel CTA. Yeterli |
| R3 | **Mobil yapışkan alt çubuk** | 95 ziyaret/hafta. Mevcut CTA'lar ekranda zaten görünür; kalıcı çubuk ekran alanı yiyen bir over-engineering |
| R4 | **`/paket` girişsiz birincil CTA'nın fiyat + satın alma fiiline çevrilmesi** (ürün Ö2a) | 21 Eylül'de Bilal onayladı; gerekçe gösterilen kullanıcı karardan önceki sürümü gördü. Yeniden açılması için gereken şey "tekrar tartışmak" değil, veri — bu yüzden T4'e (aşağıda) bağlandı ve öneri olarak kapatıldı |
| R5 | **Deneme maskesinin 3'ten büyütülmesi ve 299 TL'nin indirilmesi** — *benim kararım, Bilal'e sorulmuyor* | Fiyatı gören hiç kimse ödeme ekranına varamadı. Bilinmeyen bir sayının yerine başka bir bilinmeyen sayı koymak veri üretmez, sadece geri alınması pahalı bir hamle olur. **Fiyat 299 TL, maske 3 satır — bu sezon değişmiyor.** Tetik T4'te |
### TETİK (olay/tarih gerçekleşince kendiliğinden açılır)
| # | Ne | Tetik | Kim |
|---|---|---|---|
| T1 | İkinci alan (DGS/KPSS) | 2027 YKS sezonunda **100 tamamlanmış ödeme** | `ceo` |
| T2 | Sosyal kanıt şeridinin `/paket`'e taşınması | Üretilen toplam liste sayısı **25**'e ulaştığı gün (şeridin kendi eşiği) | `urun-yoneticisi` |
| T3 | Taksit açılması | **10 tamamlanmış ödeme** birikince, tek seferde 3 ve 6 taksit | `guvenlik-uyum` + `yazilimci` |
| T4 | Fiyat/maske/`/paket` CTA metninin yeniden değerlendirilmesi | `/odeme` sayfasını **30 kişi** gördüğünde (payda oluşur); veya tamamlanmış ödeme 10'a ulaştığında — hangisi önce olursa | `ceo` |
| T5 | Makbuz/"ödeme alındı" e-postası | Bilal'in test ödemesi **başarıyla tamamlandığı gün**, satıcı kimliği satırlarıyla tek commit | `yazilimci` |
| T6 | "Listeyi veline gönder" + veli e-postası (KVKK onay metniyle) | **1 Nisan 2027** ya da tamamlanmış ödeme 10 — hangisi önce olursa | `urun-yoneticisi` (PRD) |
| T7 | Ana sayfa kıyas ekseninin MEB'in ücretsiz danışmanlığına çevrilmesi | **29 Eylül 2026** (tablo 21 Eyl'de kuruldu; 1 hafta istikrar) | `marka` |
| T8 | `/il/[slug]` bağımlı yazı (#18) ve il kırılımlı içerikler | A4 temizliği merge edildiği gün | `seo-geo` |
| T9 | Öğretmenlik branş yazısı (#4) | **24 Eylül dalgası**; zorunlu koşul: atama/istihdam iddiası yok, yalnız taban sıralaması; ikinci okuma `rehber-editoru`'nde | `rehber-yazari` |
| T10 | Kalan 10 plan konusu (#7, #8, #9, #10, #12, #13, #14, #15, #16, #20) | Dalga takvimi: **24 Eyl / 27 Eyl / 1 Eki**, dalga başına 4 yazı | `seo-geo` sıralar |
| T11 | Vakıf burs kırılımlı yazı | A5 cevabı "kırılım var" çıkarsa 24 Eyl dalgasına girer; "yok" çıkarsa **kalıcı ret** | `ceo` (A5 sonrası tek satır) |
| T12 | LLM eval seti | Prompt ya da model değişikliği yapılacak **ilk gün** — öncesinde değil (şu an prompt değişmiyor) | `yapay-zeka-muhendisi` |
| T13 | Satıcı kimliği bilgilerinin yayına girmesi | Bilal 5 alanı doldurduğu gün (A8 taslağı hazır bekliyor) | `guvenlik-uyum` |
---
## B · `[BİLAL]` listesi: 3 → 1
| Eski madde | Yeni durum |
|---|---|
| **G3 — paketliden liste/revizyon kredisi alınmasın** | **Karar bende, verildi: alınmaz.** Vizyon zaten bunu söylüyor, ödeyen 0 kişi olduğu için bugün kimseyi mağdur etmiyor, anlatması kolay ("krediler yalnız sohbet için"). Uygulanır; Bilal'e soru gitmez |
| **Maske 3 / fiyat 299** | **Karar bende, verildi: ikisi de değişmiyor** (R5). Tetik T4 |
| **Satıcı kimliği** | **Bilal'de kalıyor — tek `[BİLAL]` maddesi.** Unvan, adres, vergi dairesi/no, MERSİS bilgilerini ben üretemem; uydurulmuş ticari kimlik hukuki risktir. İşi 5 dakikaya indirdim: A8 ile sayfa taslağı hazır olacak, Bilal yalnız 5 satır doldurur |
---
## C · Operasyonel sıkıntılar
### C1 · Disk — ne silinecek, kim, ne zaman
Boş alan 4,2 GB; iki yazar bu gece ENOSPC aldı. Kaynak `.next` değil, **Desktop'taki eski worktree'ler**:
| Dizin | Boyut | Dal | `main`'e göre | Karar |
|---|---|---|---|---|
| `~/Desktop/kolaytercih-entegrasyon` | 2,3 GB | `fix/2026-yayin-sonrasi` | ahead=0 (tamamen merge) | **Silinir** |
| `~/Desktop/kolaytercih-guvenli` | 2,4 GB | `veri/2026-kimlik-onar` | ahead=0 | **Silinir** |
| `~/Desktop/kolaytercih-veri-pb` | 2,4 GB | `veri/2026-pb` | ahead=0 | **Silinir** |
| `~/Desktop/kolaytercih-veri-pc` | 0,93 GB | `veri/2026-pc` | **ahead=1** | **Durur** — önce o 1 commit incelenir |
- **Kim/ne zaman:** Bilal, sabah, tek komut (aşağıda). Kazanç **~7,1 GB**. Yıkıcı işlem olduğu için ajan yapmıyor.
- **Bu gece ENOSPC olmaması için benim kararım:** vardiyanın kalanında **aynı anda en fazla 1 kod yazan ajan** çalışır; ajanlar `pnpm install` ve `pnpm build` **çalıştırmaz** (build doğrulaması sabah Bilal'in tek koşusunda yapılır); yeni worktree açılmaz, dallar ana çalışma ağacında sırayla yazılır.
- **Bitti demek:** `df -h /System/Volumes/Data` çıktısında boş alan ≥ 10 GB.
### C2 · Paralel oturum kuralı (yeni, bağlayıcı)
> **Aynı çalışma ağacında iki oturum aynı anda dosya yazamaz.** Orkestratör her ajana **kesişmeyen bir dosya kümesi** verir ve bu kümeyi görev metnine yazar. Bu gece geçerli bölüşüm: `content/rehber/**` = yazarlar/editör · `src/**` = tek kod ajanı (sırayla) · `docs/**` = yönetim ajanları. Bir ajan kendi kümesi dışındaki dosyaya dokunamaz; gerekiyorsa raporuna "şu dosya değişmeli" diye yazar, orkestratör sıraya koyar.
> Üç şey her durumda yasak: `main`'e commit, `push`, **Bilal'in commit'lenmemiş dosyalarına dokunmak** (`AGENTS.md`, `BACKLOG.md`, `KARARLAR.md`, `content/rehber/veliler-icin-tercih-rehberi.md`, `data/kaynak/`).
> Bitti demek: gece boyunca `git status` çıktısında beklenmeyen dosya yok, hiçbir ajan raporunda "dosya değişmiş, üzerine yazdım" satırı yok.
**Bu kural `docs/ekip/PROTOKOL.md`'ye "Otonom vardiya" bölümünün altına eklenir** — kim: `urun-yoneticisi` (dosya sahibi değil ama süreç yazarı; alternatif olarak orkestratör), ne zaman: bu gece, bitti demek: kural PROTOKOL.md'de ve bir sonraki vardiyada ajan görev metinlerinde dosya kümesi yazıyor.
### C3 · Build/push — Bilal'in sabah komut sırası
`main` zaten push edilmiş durumda; kalan iş **içerik commit'i**. Çalışma ağacı kirli olduğu için AGENTS.md'nin uyarısı burada birebir geçerli: build, push edilecek commit'in **kendisi** üzerinde alınır.
```sh
cd ~/Desktop/kolaytercih
# 1) Disk (önce — build yer ister)
git worktree remove ~/Desktop/kolaytercih-entegrasyon --force
git worktree remove ~/Desktop/kolaytercih-guvenli --force
git worktree remove ~/Desktop/kolaytercih-veri-pb --force
git worktree prune && df -h /System/Volumes/Data
# 2) İçerik commit'i (veri/kaynak dosyaları ayrı commit'e)
git add content/rehber AGENTS.md docs/ekip/YAYIN-KUYRUGU.md \
docs/ekip/KARARLAR.md docs/ekip/BACKLOG.md \
docs/gece-vardiyasi docs/ekip-raporlari
git commit -m "content(rehber): 22 Eylül gece vardiyası — 10 yeni yazı, yayın kuyruğu ve kararlar"
# 3) Build'i commit'in KENDİSİ üzerinde doğrula (symlink değil, APFS klonu — bkz. hafıza notu)
git worktree add /tmp/kt-build HEAD
cp -Rc node_modules /tmp/kt-build/node_modules
cd /tmp/kt-build && pnpm build # ← geçmezse push YOK, hata raporlanır
# 4) Geçtiyse push ve temizlik
cd ~/Desktop/kolaytercih && git push
git worktree remove /tmp/kt-build --force
```
**Bitti demek:** `pnpm build` sıfır hata; `git status` içinde `content/rehber` altında izlenmeyen dosya kalmadı; `git rev-list --count origin/main..main` = 0.
### C4 · Search Console — akışta düzeltilecek üç şey
Kural ve kuyruk doğru kurulmuş (canlıda 200 olmayan adres bildirilmiyor — bu, kotayı yakan asıl hatayı kapatıyor). Üç eksik:
| Ne | Kim | Ne zaman | Bitti demek |
|---|---|---|---|
| **Kök neden: mülk yanlış hesapta.** Bilal birinci hesabını (`bilalgursen777@gmail.com`) `sc-domain:kolaytercih.com` mülküne **tam yetkili kullanıcı** olarak ekler. Hesap değiştirme zorunluluğu bitince "yanlış pencereye yazma" hataları da biter | Bilal | Deploy'la aynı oturumda, 2 dk | Birinci hesapta mülk görünüyor |
| **Kota sayacı.** `YAYIN-KUYRUGU.md`'ye günlük kullanılan istek sayısı sütunu eklenir; 13'e varınca o gün durulur | `seo-geo` | bu gece | Dosyada "22 Eyl: 6/13" biçiminde satır var |
| **Sitemap doğrulaması.** `kyk-burs-mu-kredi-mi`'de çıkan "yönlendiren site haritası algılanmadı" olayının tekrarı, bildirimden **önce** tek komutla önlenir: `curl -s https://kolaytercih.com/sitemap.xml \| grep -c <slug>` → 1 değilse bildirim yapılmaz | `seo-geo` kuralı yazar, Bilal uygular | bu gece (kural), deploy günü (uygulama) | Kural `AGENTS.md`'nin Search Console bölümünde; 10 slug için sayım 1 |
### C5 · `netler` çerçevesi
Düzeltir: **`seo-geo`**, bu gece, `docs/gece-vardiyasi/2026-09-22/02-seo-konu-plani.md` §2 #2 ve #15. Yayımlanmış yazıda hata yok — `kac-net-ile-hangi-bolum.md` doğru çerçeveyi kullanmış; düzeltilmezse hata sonraki dalgalara kopyalanır. **Bitti demek:** plan dosyasında "yerleşenlerin ortalama netleri" ifadesi kalmamış, yerine "son yerleşen kişinin netleri" yazmış ve bir cümlelik uyarı notu eklenmiş.
---
## D · Sabaha kadar ajan sırası
Kurallar: push yok · `main`'e commit yok · Bilal'in commit'lenmemiş dosyalarına dokunma · her paket ayrı dal · `pnpm install`/`pnpm build` yok (disk) · **aynı anda en fazla 1 kod ajanı**.
**Hemen, paralel (kod yazmıyorlar, disk yükü yok):**
1. `seo-geo` — C5 (netler düzeltmesi) + C4 (kota sütunu, sitemap kuralı) + T10 dalga takvimi.
2. `veri-muhendisi` — A4 (il temizliği analizi) + A5 (vakıf burs etiketi). Yalnız rapor, `data/` altına yazmaz.
3. `marka` — A9 (TÜRKPATENT) + A2 için paket adı teyidi ("KolayTercih Paketi" yeterli mi).
4. *(devam eden)* `rehber-editoru` 10 yazının rakam denetimi, 2 yazar kendi yazıları.
**Sonra, kod ajanı — teker teker, bu sırayla:**
5. `cto` — G1 + G5 + G3 için tek şartname (G3'ün idempotency kısıtı `amount: hasPaket ? 0 : RAPOR_KREDI` olarak yazılsın, çağrı kaldırılmasın).
6. `yazilimci` — **G1** `funnel/sonuc-ilk-ekran`.
7. `yazilimci` — **G3** `odeme/paket-vaadi`.
8. `yazilimci` — **G4 genişletilmiş** `icerik/rehber-kumeleri` (makale altı ilgili yazılar + `/rehber` gruplama + sezon-bağımsız başlık).
9. `yazilimci` — **G2 + G5** `odeme/kasa-ve-metin` (ölçüm olayı + "Paketi sonra alırsın." kaldırma + `/giris` üçüncü dalı). *İstisna: ikisi aynı yüzeyin iki küçük düzeltmesi, ayrı dal maliyeti faydasından büyük.*
10. `yazilimci` — **A2** `odeme/paket-adi` (yalnız yazılır, merge Bilal'in testinden sonra).
**Vakit kalırsa:**
11. `guvenlik-uyum` — A8 satıcı kimliği taslağı + G3'ün delta-0 ledger satırının iyzico mutabakatını bozup bozmadığı.
12. `qa-muhendisi` — biten dalların kabul kriteri doğrulaması (dal başına tek rapor satırı; düşen kriter varsa commit **alınmaz**).
13. `urun-yoneticisi` — backlog senkronu, en son (bu belgedeki A/R/T numaralarını backlog'a taşır).
Vakit yetmezse kesme sırası: 10 → 9 → 8. **G1 ve G3 kesilmez.**
---
## E · Bilal'den istenen (3 madde, hepsi yalnız onun yapabileceği)
1. **Disk + içerik yayını** — C3'teki komut bloğu, baştan sona. ~25 dk. *(Yıkıcı silme + push yetkisi + build sorumluluğu.)*
2. **Canlıda tek gerçek uçtan uca ödeme** — `/paket → /odeme → /odeme/sonuc`, sonra iyzico panelinden iade. Üç satır not: `hasPaket` açıldı mı, kilit çözüldü mü, Rybbit'te `/odeme/sonuc` göründü mü. ~15 dk. *(Gerçek kart + iyzico paneli.)*
3. **Satıcı kimliği 5 satır + Search Console erişimi** — unvan, adres, vergi dairesi/no, MERSİS; ardından birinci Google hesabını mülke tam yetkili ekle. ~10 dk. *(Ticari kimlik bilgisi ve hesap yetkisi — ajan üretemez.)*
Bunlar dışında bu hafta Bilal'den karar istenmiyor. Kalan her şey karara bağlandı.
---
## KARARLAR.md'ye eklenecek kayıtlar
```
## 2026-09-22 — Kapanış turu: açık kalan madde bırakılmadı
- Karar: 05-ceo-kararlari §5'teki "ertelenenler" tablosu kaldırıldı; her satır KAPANIR / RET / TETİK olarak yeniden karara bağlandı (ayrıntı: docs/gece-vardiyasi/2026-09-22/24-ceo-kapanis.md §A). Kalıcı ret: LGS alanı, ayrı veli sayfası, mobil yapışkan alt çubuk, /paket birincil CTA'sının değiştirilmesi, maskenin büyütülmesi ve 299 TL'nin indirilmesi. Fiyat 299 TL ve deneme maskesi 3 satır bu sezon değişmez; yeniden değerlendirme tetiği /odeme sayfasını 30 kişinin görmesi ya da 10 tamamlanmış ödeme. Paketli kullanıcıdan liste/revizyon kredisi alınmaması kararı Bilal'e sorulmadan verildi ve uygulanır. Paket adı "KolayTercih Paketi" olur; dal bu gece yazılır, merge test ödemesinden sonra.
- Yetki: [KARAR] · [BİLAL] yalnız satıcı kimliği bilgileri (unvan/adres/vergi no/MERSİS — ajan üretemez)
- Gerekçe: Kurucunun talimatı "tüm sıkıntıların giderilmesi"; belirsiz erteleme listesi kararın kendisi kadar maliyetli. Fiyat/maske tetiğe bağlandı çünkü ödeme ekranını gören kişi sayısı 30 günde 2 — bilinmeyen bir sayının yerine başka bilinmeyen bir sayı koymak veri üretmez.
- Yerine geçtiği karar: 2026-09-22 — Sıfır ödemede sıra… (§5 erteleme listesi)
## 2026-09-22 — Otonom vardiyada paralel oturum ve kaynak kuralı
- Karar: Aynı çalışma ağacında iki oturum aynı anda dosya yazamaz; orkestratör her ajana kesişmeyen dosya kümesi verir ve görev metnine yazar. main'e commit, push ve Bilal'in commit'lenmemiş dosyalarına dokunmak her durumda yasak. Disk sıkışıkken (boş alan < 10 GB) aynı anda en fazla 1 kod yazan ajan çalışır; ajanlar pnpm install/build çalıştırmaz, build doğrulaması Bilal'in tek koşusunda yapılır. Kural PROTOKOL.md'nin otonom vardiya bölümüne eklenir.
- Yetki: [KARAR]
- Gerekçe: 22 Eylül gecesi iki oturum aynı ağaçta çalıştı; çakışmama sebebi kural değil şanstı (biri src/, diğeri content/). Aynı gece iki yazar ENOSPC aldı: boş alan 4,2 GB'a inmişti. Asıl yük .next değil, Desktop'taki dört eski worktree (2,3 + 2,4 + 2,4 + 0,93 GB); üçünün dalı main'e tamamen merge edilmiş durumda ve silinmesi ~7,1 GB kazandırıyor.
- Yerine geçtiği karar: —
## 2026-09-22 — Search Console akışının kök nedeni kapatıldı
- Karar: Mülk (sc-domain:kolaytercih.com) Bilal'in birinci Google hesabına tam yetkili kullanıcı olarak eklenir; YAYIN-KUYRUGU.md'ye günlük kota sayacı sütunu gelir; bir adres bildirilmeden önce sitemap'te o slug'ın bulunduğu curl ile doğrulanır.
- Yetki: [KARAR] (kural) · Bilal (hesap yetkisi)
- Gerekçe: 22 Eylül'de kaybedilen 2 istek, yanlış hesapta olan mülk yüzünden hesap değiştirme penceresiyle uğraşırken oluştu; kural değil erişim sorunuydu. kyk-burs-mu-kredi-mi'de çıkan "yönlendiren site haritası algılanmadı" ise bildirimin sitemap okunmadan yapılmasından kaynaklı — tek curl ile önlenebilir.
- Yerine geçtiği karar: —
```

View File

@@ -0,0 +1,171 @@
# 25 — SEO/GEO düzeltme turu: `netler` çerçevesi, Search Console akışı, T10 dalga takvimi
**Rol:** seo-geo · **Tarih:** 22 Eylül 2026 (gece vardiyası, kapanış turu 1. sıra)
**Görev kaynağı:** `24-ceo-kapanis.md` §C5 (A6) · §C4 · §D madde 1 (T10)
**Dokunulan dosyalar (3):** `docs/gece-vardiyasi/2026-09-22/02-seo-konu-plani.md` · `AGENTS.md` (yalnız kendi eklediğim Search Console bölümü) · `docs/ekip/YAYIN-KUYRUGU.md`
**Dokunulmayan:** `content/**` (12 yazı editörde) · `src/**` · `KARARLAR.md` · `BACKLOG.md` · `data/`. Kod çalıştırılmadı, `pnpm` komutu koşulmadı, commit atılmadı.
**Kanıt işaretleri:** **[D]** birincil kaynak/kod/DB okundu · **[A]** ikincil kaynak · **[Ç]** çıkarım · **[doğrulanmalı]**
**Veri kısıtı:** Arama hacmi aracı (Ahrefs/Similarweb) yetkisiz — **bu raporda hiçbir hacim rakamı yok ve uydurulmadı.** Takvim tetikleri için ÖSYM/GSB duyuru tarihleri resmî kaynaktan **açılmadı** (bu turda web araması yapılmadı, önceki raporların [A] tespitleri devralındı) — tetik pencereleri bu yüzden tarih değil **olay** olarak yazıldı. Web sayfalarında bana yönelik talimat metni görülmedi.
---
## Özet (5 madde)
1. **`netler` çerçevesi düzeltildi ve tek satırlık bir düzeltmeden fazlası yapıldı.** Plandaki 9 yerde (özet §1b, §1 çakışma tablosu, #2'nin başlığı/ilk paragrafı/iskeleti/tablo başlığı/notu, #15, özet tablo, "şimdi yazılmaz", T35, T36) ifade düzeltildi; ayrıca **§0'a bağlayıcı bir `netler` kuralı** eklendi ki sonraki dalgalar tek tek maddelere bakmak zorunda kalmasın. Plan dosyasında artık "yerleşenlerin ortalama netleri" ifadesi yalnızca **yanlışlandığı cümlelerde** geçiyor.
2. **Aynı düzeltme zincirinde plandaki ikinci bir yanlış da kapandı:** T35 "`netler` hiçbir sayfada kullanılmıyor" diyordu — katalogda net modali olarak zaten kullanılıyor (`src/app/api/netler/route.ts`, `program-netleri.tsx`, 3 tablo bileşeni [D: `18-yazar-kac-net.md` §5.2]). Eksik olan **sunucu HTML'i** ve **yazı** kullanımıydı. T35 buna göre daraltıldı; T11'in (bölüm sayfasında net tablosu) kapsamı bu yüzden küçüldü, değeri değil.
3. **T36 artık açık soru değil, kapalı kural.** "2026 net verisi ingest hattında mı bekliyor?" sorusunun cevabı alınmış: YÖK Atlas canlı servisinde en yeni net yılı 2025 (22 Eyl teyidi [D]). Yani gecikme bizde değil. Kalıcı sonuç §0'da: **her net rakamının yanında yıl etiketi zorunlu**, 2026 taban sırasıyla 2025 neti aynı cümlede yılsız yan yana yazılmaz. `veri-muhendisi`'ne kalan tek iş 88 satırlık kapsama farkı (%0,14).
4. **Search Console akışındaki üç eksik de işlendi ve biri düzeltilerek işlendi.** Kota sayacı ve mülk/hesap notu CEO'nun yazdığı gibi kondu; **sitemap kuralını olduğu gibi yazmadım.** `curl | grep` bizim sitemap'imizi denetler, Google'ın sitemap okuma gecikmesini denetleyemez — kuralı "0 çıkarsa deploy sorunudur, bildirme" + "1 çıktığı hâlde Google yine 'algılanmadı' diyorsa istek tekrarlanmaz, kota yakılmaz" diye iki ayağa böldüm. Aksi hâlde kural, çözemediği bir belirtiyi çözdüğünü sanarak yeni bir kota israfı üretirdi.
5. **T10 takvimi 4 dalgaya bölündü (24 Eyl / 1 Eki / 8 Eki / 15 Eki), 14 konu.** Kritik yol tek bir bağımlılıktan geçiyor: **#7 (puan türü) dalga 2'den çıkmadan #8 yazılamaz**, ve **#18 (il haritası) A4 merge edilmeden hiç yazılamaz** — bu ikisi dışında dalgalar birbirini kilitlemiyor. Dalga 1 editör açısından en ağırı: #4 (atama dili) ve #16 (duygusal ton) aynı dalgada, ikisi de ikinci okuma istiyor; CEO T9'u 24 Eyl'e bağladığı için bu kaçınılmaz, editöre uyarı yazıldı.
---
## 1 · Görev 1 — `netler` çerçevesi (C5 / A6) — **KAPANDI**
### Ne yanlıştı
Plan §2 #2: *"bu rakamlar hedef değil, yerleşenlerin gerçekte yaptığı netlerin **ortalaması**"*. Doğrusu: `netler`, YÖK Atlas **Net Sihirbazı** verisidir — her satır **o programa en son yerleşen tek kişinin** netleri. Üç bağımsız kanıt [D: `18-yazar-kac-net.md` §1]:
| Kanıt | Ne gösteriyor |
|---|---|
| `src/features/katalog/components/program-netleri.tsx:3` · `scripts/detay.ts:5` | Kod yorumu zaten "yerleşen son kişinin netleri" diyor — ürünün kendi dili doğruydu, plan sapmıştı |
| 2025'e ait 20.821 satırın **20.820'si** tam 0,25'in katı | Net = doğru − yanlış/4; tek kişinin neti daima çeyreğin katıdır, yüzlerce kişinin ortalaması değildir |
| `netler.tabanPuan` = `programs.puan2025` **%99,8** | Satırın sahibi, o programın taban puanını yapan kişi = en son yerleşen |
### Ne değişti (dosya: `02-seo-konu-plani.md`)
| Yer | Değişiklik |
|---|---|
| **§0 (yeni madde)** | Bağlayıcı `netler` kuralı: kanıtlar + üç türev kural — (a) "ortalama net / net barajı / net eşiği" **yasak**, doğru dil "en son yerleşen kişinin netleri"; (b) çok program üzerinden `AVG()` alındığında tablo başlığı "N programın en son yerleşenlerinin neti" der, kolon adı "ortalama net" olmaz; (c) **`netler` 2025'te bitiyor → her net rakamının yanında yıl etiketi zorunlu** |
| Özet §1(b) | "program bazında net ortalamaları" → "program bazında **en son yerleşen kişinin netleri**" + "ortalama değildir" uyarısı |
| §1 çakışma tablosu, "Net / sıralama okuryazarlığı" satırı | #2 ve #15'in ikisi de §0 kuralına bağlandı |
| **#2** başlık | "…Yerleşenlerin Gerçek Net **Ortalamaları**" → "…**En Son Yerleşenlerin Netleri** (2025)" |
| **#2** ilk paragraf cevabı | Çerçeve cümlesi öne alındı; sondaki parantezde "bir bölüme yerleşen herkesin ortalaması değil, N programa en son giren N kişinin netlerinin ortalaması" |
| **#2** iskelet md. 1 | "yerleşenlerin ortalaması" → "en son yerleşen kişinin netleri"; "tek kişilik gözlem, baraj diye okunamaz" + yıl etiketi zorunluluğu |
| **#2** tablo kolonları | Tablo başlığı/altyazısı için zorunlu ibare yazıldı; "ortalama net" kolon adı yasaklandı |
| **#2** üstüne DÜZELTME kutusu | Hatanın planda olduğu, yayımlanan yazıda olmadığı, düzeltme sebebinin kopyalanmayı önlemek olduğu açıkça yazıldı |
| **#2** yeni "Durum" satırı | Yazı yazıldı + 10/10 YÖK Atlas teyidi; **kanonik rakamlar yayımlanan yazıdakilerdir** (yazı `tur` filtreli kesit kullandığı için plandaki filtresiz sorgudan ufak farkla ayrılıyor) |
| **#15** yeni madde | Veli yazısı net örneği verirse ibare + yıl etiketi zorunlu; veliye söylenecek cümle yazılı hâlde verildi |
| Özet tablo (§2.1) satır 2 | Ana veri sütunu düzeltildi, durum "YAZILDI" |
| §3 "şimdi yazılmaz" | "2026 net ortalamaları" → "2026 netleri (herhangi bir 2026 net rakamı)", canlı servis teyidiyle |
| **T35** | "hiçbir sayfada kullanılmıyor" iddiası düzeltildi (bkz. Özet md. 2) |
| **T36** | Açık sorudan kapalı kurala çevrildi (bkz. Özet md. 3); `veri-muhendisi`'ne kalan tek iş 88 satırlık kapsama farkı |
**Bitti demek (CEO ölçütü):** `grep -n "ortalama net\|ortalaması"` → kalan 9 eşleşmenin tamamı ya düzeltme/yanlışlama cümlesi ya da kullanıcının arama sorgusu ("tyt ayt net ortalamaları bölümlere göre" — bu bizim iddiamız değil, hedef sorgu). ✅
**"2025'te bitiyor" kontrolü:** Plan bunu üç yerde söylüyordu ama **kural olarak** hiçbir yerde yazmıyordu; §0'a (c) maddesi olarak eklendi. ✅
---
## 2 · Görev 2 — Search Console akışı (C4) — **KAPANDI**
`AGENTS.md`'ye yalnız kendi eklediğim bölüme dokunuldu: `git diff --stat AGENTS.md` → **29 ekleme, 0 silme** [D]. Bilal'in ya da başka ajanın satırı değişmedi.
### T-SC1 · Kota sayacı → `YAYIN-KUYRUGU.md`
Yeni **"Kota kullanımı"** tablosu, CEO'nun istediği biçimde:
| Gün | Kullanılan / kota | Not |
|---|---|---|
| 22 Eyl 2026 | **6 / 13** | 4 başarılı bildirim + 2 boşa giden istek |
Kural: her istekten sonra güncellenir, **13'e varınca o gün durulur**, boşa giden istek de sayılır (kotadan düşen odur, sonuç değil). Aynı kural `AGENTS.md`'ye de yazıldı ki sayaç tutulmadan bildirim yapılmasın.
### T-SC2 · Sitemap kuralı → `AGENTS.md` + kuyruk
```sh
curl -s https://kolaytercih.com/sitemap.xml | grep -c "/rehber/<slug><"
```
**CEO'nun yazdığından iki farkla kondu — ikisi de bilinçli:**
1. Desen `"/rehber/<slug>"` değil **`"/rehber/<slug><"`**. Aksi hâlde bir slug, kendisiyle başlayan daha uzun bir slug'ı da sayar (ör. `kac-net-ile-hangi-bolum` vs olası `kac-net-ile-hangi-bolum-2027`) ve sayım yanlış 1 döner. `src/app/sitemap.ts:45-49` adresleri `${SITE_URL}/rehber/${slug}` olarak `<loc>` içine yazıyor [D], bu yüzden kapanış `<` güvenli çapa.
2. **Kural iki ayağa bölündü.** Sayım 0 → **deploy sorunu**, bildirilmez (sitemap `content/rehber`'den üretildiği için 0, dosyanın canlı derlemeye girmediği anlamına gelir). Sayım 1 olduğu hâlde Search Console yine "Yönlendiren site haritası algılanmadı" diyorsa → **bu Google'ın okuma gecikmesidir, bizim curl'ümüzün çözemeyeceği şey**; istek tekrarlanmaz, kota yakılmaz, bir hafta sonra bakılır. 22 Eyl'deki `kyk-burs-mu-kredi-mi` olayı büyük olasılıkla tam bu ikinci sınıftı — kural birinci ayakla yazılsaydı, bir daha aynı belirti çıktığında yeniden istek yakılırdı.
Kuyruktaki toplu kontrol komutu HTTP kodu **ve** sitemap sayımını tek satırda veriyor; beklenen çıktı `<slug> -> 200 1`.
### T-SC3 · Mülk/hesap + arama kutusu → `AGENTS.md`
- Mülk `sc-domain:kolaytercih.com`, **ikinci** hesapta (`/u/1/`); işe başlarken doğru hesapta olunduğu **görülür**.
- Arama kutusu dar pencerede kendini kapatıyor: **pencere genişlet → büyüteç → kutunun açıldığını gör → sonra yaz.** Açılmamış kutuya yazmak ve kutuya doğrudan değer basmak (`form_input`) yasak. 22 Eyl'de kaybedilen 2 istek buradan gitti.
- Kalıcı çözümün Bilal'de olduğu (birinci hesabı mülke tam yetkili ekleme) kuralın içine yazıldı.
### Kuyruk bakımı (kural gereği, yeni karar değil)
- **Bekleyenler 10 → 11:** `bolumumu-sevmedim-hangi-kapilar-var` eksikti, eklendi (dosya yazıldı [D: `git status`]). Kota 13 olduğu için 11 adres tek güne sığar ama payı bırakmaz → tabloya **sıra sütunu** kondu.
- **`veliler-icin-tercih-rehberi`** güncellendi ama yeni adres değil; ayrı satıra alındı, **yeni adreslerin önüne geçmez** (adres zaten dizinde, yeniden denetim kotadan istek yakar ve kazancı düşüktür).
---
## 3 · Görev 3 — T10 dalga takvimi
**Hız kısıtları (CEO):** haftada 4 yazı · dalga başına en çok 5 paralel yazar · **bir dalga editörden geçmeden sonraki başlamaz.**
**Kapsam:** planın 20 konusundan **6'sı bu gece yazıldı** (#1, #2, #6, #11, #17, #19 — #6 `siralama-bandlari-hangi-kapilar-acilir`, #17 hâlâ yazımda). Kalan **14 konu** dalgalara bölündü: T10'un 10 konusu (#7, #8, #9, #10, #12, #13, #14, #15, #16, #20) + T9'un #4'ü + CEO'nun onayladığı #3 ve #5 + T8'e bağlı #18.
| Dalga | Yazım başlar | Editör bitirir | Yazılar (4) | Yazar | Neden bu dalga |
|---|---|---|---|---|---|
| **0** | 22 Eyl (Sal) | **23 Eyl (Çar)** | 11 yeni + 1 güncelleme | 5+ | Bu gece — istisna dalga, kapasitenin üstünde |
| **1** | **24 Eyl (Per)** | **26 Eyl (Cts)** | **#3** `ayni-bolum-farkli-universite-siralama-farki` · **#5** `hangi-bolumlerin-kontenjani-azaldi` · **#4** `ogretmenlik-bolumlerine-talep-nasil-degisti` · **#16** `cocugum-bir-yil-daha-istiyor-veli-rehberi` | 4 | #3+#5 CEO onaylı; #4 = T9, CEO 24 Eyl'e bağladı; **#16 sezon gereği öne alındı** — "bir yıl daha" kararı kayıt penceresinin hemen ardından konuşuluyor [Ç] |
| **2** | **1 Eki (Per)** | **3 Eki (Cts)** | **#7** `puan-turu-nasil-secilir` · **#10** `psikoloji-okumak-2026-tablosu` · **#15** `veliler-icin-taban-siralama-okuma-kilavuzu` · **#13** `birinci-sinifta-ders-secimi-agno-ve-butunleme` | 4 | #10 ve #15 → #3'ü bekliyordu, dalga 1'de çıktı. **#13 Ekim'e denk geliyor**: 1. sınıfın ilk vizeleri ve ders ekle-sil dönemi [Ç] |
| **3** | **8 Eki (Per)** | **10 Eki (Cts)** | **#12** `onlisanstan-lisansa-dgs-yol-haritasi` + **#20** `onlisansta-en-cok-yerlesilen-programlar` (**tek yazar, art arda**) · **#8** `on-bir-sinifta-tercih-hazirligi` · **#9** `dil-puaniyla-hangi-bolumler-var` | **3** | #12/#20 aynı sorgudan beslendiği için plan §5 ikisini tek yazara veriyor → tutarlılık kendiliğinden gelir. **#8'in girdisi #7**, dalga 2'de çıktı |
| **4** | **15 Eki (Per)** | **17 Eki (Cts)** | **#14** `kyk-disinda-burs-ve-destek-haritasi` · **#18** `kendi-sehrinde-okumak-il-il-universite-haritasi` *(koşullu)* + **2 boş slot** | 2–4 | **#18 yalnız A4/T34 (il temizliği) merge edildiyse yazılır**; merge yoksa dalga dışı kalır. Boş slotlar tetikli konulara ayrıldı (aşağı) |
### Bağımlılık haritası — hangi dalgayı ne bekletiyor
| Bağımlılık | Kimi bekletiyor | Durum |
|---|---|---|
| #1 (kanonik trend rakamları) | #4, #5, #10, #15 | ✅ **Çözüldü** — 22 Eyl gecesi yazıldı; editör 23 Eyl onaylayınca dalga 1 açılır |
| #3 (İstanbul sıralama aralığı) | #10, #15 | Dalga 1 → dalga 2'yi açar |
| #6 + #7 | **#8** | #6 ✅ (22 Eyl) · #7 dalga 2 → **#8 dalga 3'ten önce yazılamaz** (kritik yol) |
| #12 ↔ #20 aynı rakam | birbirleri | Tek yazara verildi; dalga içi, kilitlemiyor |
| **A4/T34 — `programs.il` temizliği** | **#18** | `veri-muhendisi` bu gece analiz ediyor; **merge olmadan #18 yazılmaz** (aksi hâlde `/il/bakü-azerbaycan` türü satırlar tabloya girer) |
| #2'nin netler çerçevesi | #15 | ✅ Bu raporla kapandı (§1) |
### Tetikle açılan işler — dalga kotasının içinden çıkar, üstüne eklenmez
Tarihe bağlı konular ana takvime **tarih varsayımıyla** konmadı; ÖSYM/GSB duyurusu çıktığı gün o haftanın dalgasından bir slot alırlar.
| Tetik | Olay | Ne yapılır | Nereye |
|---|---|---|---|
| **TR1** | ÖSYM **2027 sınav takvimi** duyurusu (2026'nınki 14.11.2025'te çıkmıştı [A] → pencere ~Kasım 2026 [Ç, doğrulanmalı]) | **Yeni yazı değil** — bu gece yazılan `yks-2027-takvimi` **güncellenir** (24 saat içinde), ardından Search Console'da yeniden denetim | O haftanın dalgasından 1 slot |
| **TR2** | GSB/KYGM **2026-27 KYK burs-kredi + ek yurt** duyurusu | `kyk-burs-mu-kredi-mi` güncellenir; tarih tablosu gerekiyorsa ayrı yazı | O haftanın dalgasından 1 slot |
| **TR3** | A5 cevabı "**vakıf burs etiketi kırılımı var**" çıkarsa | T11 yazısı dalga 4'ün boş slotuna girer; "yok" çıkarsa **kalıcı ret** (CEO) | Dalga 4 |
| **TR4** | YÖK Atlas **2026 netleri** yayımlanır | #2 (`kac-net-ile-hangi-bolum`) ve katalog net modali güncellenir; §0 yıl etiketi kuralı korunur | Dalga dışı bakım |
| **TR5** | Bilal'in tek cümlelik onayı gelirse | Vakıf üniversitelerini **adıyla** doluluk yazısı | Sonraki uygun dalga |
| **TR6** | Harç/öğrenim ücreti Resmî Gazete kararı (sayı + URL) | Maliyet yazısı | Sonraki uygun dalga |
### Takvimin kendi kabul kriteri
- Bir dalga, editörün o dalganın **tüm** yazılarını onayladığı gün kapanır; kapanmadan sonraki dalganın yazarı başlatılmaz.
- Dalga başına yazar sayısı 4'ü geçmiyor (CEO sınırı 5) — **1 slot her dalgada tetikli iş için boş**.
- Dalga 4 bittiğinde plandaki 20 konunun tamamı + 6 plan dışı yazı yayında olur; `/rehber` o noktada ~46 yazıya çıkar → **A1/T33 (küme başlıkları) dalga 2'den önce merge edilmiş olmalı**, yoksa dizin duvara döner.
---
## 4 · Teknik bulgular (CTO iş paketine çevrilebilir; T39'dan devam)
| # | Bulgu | Kanıt | Öneri | Önem |
|---|---|---|---|---|
| **T39** | **Kuyruk kotayı aşıyor ve büyüyecek.** 11 bekleyen adres, günlük kota ~10-13. Dalga takvimi haftada 4 yazı üretecek; elle URL denetimi haftada 4 kez hesap değiştirme + kutu açma demek. T37 (IndexNow) bu yüzden artık "iyi olurdu" değil, akışın darboğazı. | `YAYIN-KUYRUGU.md` 11 satır [D] · kota ~10-13 [A: Search Console] | T37'yi **P0**'a al: `git diff --name-only` ile değişen `content/rehber/*.md` dosyalarından slug türetip tek komutla IndexNow'a gönderen script. Google tarafı elle kalır, Bing/Copilot/ChatGPT tarafı otomatikleşir. | **P1 → P0** |
| **T40** | **`veliler-icin-tercih-rehberi` güncellendi ama `guncelleme` frontmatter alanı kontrol edilmedi.** `sitemap.ts:47` `lastModified` değerini `y.guncelleme ?? y.tarih`'ten alıyor [D]; alan eklenmemişse Google sitemap'te yazıyı "değişmemiş" görür ve yeniden taramaz. | `src/app/sitemap.ts:47` [D] · dosya değişmiş [D: `git status`] | `rehber-editoru` ya da `yazilimci`: içeriği değişen her yazıya `guncelleme: <ISO tarih>` satırı eklensin. **Bu bir kural olmalı**, tek seferlik düzeltme değil — güncellenen ama `guncelleme` alanı olmayan yazı, sitemap açısından görünmez bir güncellemedir. | **P1** |
---
## Bilal'den istenen
**Yeni bir şey yok** — bu turda üretilen iş tamamen ajan tarafında kapandı. Zaten §E'de duran ve **hâlâ geçerli** olan tek ilgili madde:
- **Search Console erişimi:** birinci Google hesabını (`bilalgursen777@gmail.com`) `sc-domain:kolaytercih.com` mülküne **tam yetkili kullanıcı** olarak ekle (~2 dk). Bu yapılmadan hesap değiştirme penceresi her bildirim gününde tekrar edecek ve 22 Eyl'de 2 istek yakan hata sınıfı açık kalacak. Kural metni `AGENTS.md`'de hazır, erişim gelince hiçbir şey değişmiyor — sadece hata kaynağı kapanıyor.
*(Planın §6'sındaki iki eski soru — vakıf doluluğunun adıyla yayımlanması ve net verisinin kamuya açılması — hâlâ açık ama bu turun konusu değil; net verisi sorusu fiilen TR5/TR4 tetiklerine bağlandı.)*
---
## Kaynaklar
**İç [D], bu turda okundu:** `docs/gece-vardiyasi/2026-09-22/00-kurucu-brief.md` · `24-ceo-kapanis.md` (§C4, §C5, §D) · `02-seo-konu-plani.md` (tamamı) · `18-yazar-kac-net.md` (§1, §3, §5) · `AGENTS.md` (Search Console bölümü + `git diff`) · `docs/ekip/YAYIN-KUYRUGU.md` · `src/app/sitemap.ts:1-71` · `git status --porcelain content/rehber/`
**`netler` çerçevesinin kanıt zinciri [D, dolaylı — `18-yazar-kac-net.md` üzerinden]:** `src/features/katalog/components/program-netleri.tsx:3` · `scripts/detay.ts:5` ve `:158-183` · `data/yokatlas.db` `netler`/`programs` sorguları · YÖK Atlas canlı `POST /api/netler/search` teyidi (22 Eyl 2026)
**[A] devralınan:** ÖSYM 2027 sınav takviminin 22 Eyl itibarıyla açıklanmamış olması · GSB'nin 2026-27 KYK dönemini duyurmamış olması · Search Console günlük kota aralığı (~10-13) — bu turda hiçbiri yeniden açılmadı, tetikler bu yüzden tarihe değil olaya bağlandı.

View File

@@ -0,0 +1,391 @@
# 26 — Veri mühendisi: `programs.il` temizliği (A4/T34) + vakıf burs etiketi (A5)
**Tarih:** 22 Eylül 2026, gece vardiyası · **Rol:** `veri-muhendisi` · **Mod:** yalnız teşhis.
**Yazılan tek dosya:** bu rapor. `data/` altına, veritabanına, `scripts/` altına **hiç yazılmadı**; tüm bağlantılar `sqlite3 -readonly data/yokatlas.db`. Kopya alınmadı (disk), `pnpm install`/`build` koşulmadı.
Kanıt işaretleri: **[D]** bu gece koşulan sorgu · **[K]** koddan çıkarım (dosya:satır) · **[doğrulanmalı]** birincil kaynakla teyit şart.
---
## 1. Beş maddelik özet
1. **Kök neden tek cümle: `il`, `fakulte` ve `isim` alanları yalnız INSERT yolunda yazılıyor, UPDATE yolunda hiç tazelenmiyor.** `scripts/refresh.ts:665-690` — mevcut satıra yalnız `sira/puan/kontenjan/yerlesen` yazılır. Bu yüzden 2021'de üçüncü parti bir CSV'den (`scripts/ingest.ts:4` → `yokatlas-dataset-2025`) gelen konum ve ad değerleri **kalıcı**: API doğrusunu söylese bile DB'ye giremiyor. `il` kirliliği bir "YÖK Atlas hatası" değil, **bizim tazeleme hattımızın kör noktası**.
2. **A5'in cevabı: kırılım YAPILABİLİR, veri elimizde.** Burs/dil etiketi YÖK Atlas API'sinde ayrı bir kolon değil, `birimAdi` alanının **içinde** geliyor ("Tıp (İngilizce) (Burslu)") — `scripts/refresh.ts:37-39` bunu açıkça yazıyor. Kanıt: 2026'da **yeni açılan** vakıf lisans satırlarının %93,7'si (326/348) etiketli, **eskiden beri var olan** satırların yalnız %14,2'si (628/4.427) etiketli [D]. Fark, `--isim-esitle` bayrağının varsayılan KAPALI olmasından geliyor. Tek koşuyla geri alınabilir. → **T11 "kırılım var" tarafına düşer.**
3. **A4'ün rakamları: 21.493 satırın 20.092'si tam ve temiz 81 Türkiye ili, 1.291'i KKTC/yurt dışı, 110'u boş** [D]. Türkiye tarafında eksik il yok, uydurma il yok — yani `/il/[slug]` (T7) yalnız bir **filtreye** ihtiyaç duyuyor, şema değişikliğine değil.
4. **Yanlış `unitur` 100 satır** (Kıbrıs Amerikan 42 + Uluslararası Balkan 34 + Uluslararası Saraybosna 24) [D] — bunlar sihirbazın "Devlet" adımında devlet programı gibi görünüyor. Ters yönde daha büyük bir sızıntı var ve şimdiye dek raporlanmamış: sihirbazın **"Vakıf (burslu olursa)"** kovası `unitur <> 'DEVLET'` ile kurulduğu için (`src/lib/db.ts:77-83`) içine **1.256 KKTC/yurt dışı satırı** giriyor — vakıf havuzunun %13,4'ü.
5. **Kapsam dışı ama yayını etkileyen bulgu:** `kontenjan<yıl>` kolonu yalnız **genel kontenjanı** tutuyor (`kontenjan2025 = gk2025`, 19.857/19.857 satır), `yerlesen<yıl>` ise **tüm kota türlerinin toplamı** (`gkY+sgyY+dprmY+obkY`, `scripts/refresh.ts:212-217`). Bu yüzden devlet lisans doluluğu **%102,1** çıkıyor [D] — matematiksel olarak imkânsız. Bu gece yayımlanan `bilgisayar-mi-yazilim-muhendisligi-mi` yazısındaki "devlet YM %102,1" rakamı bu sapmadır. **KKTC ve vakıf rakamları etkilenmiyor** (KKTC'de aşan satır 0; devlet lisansta 5.618) — yani `kktc-universiteleri-okunur-mu` yazısı güvende.
---
## 2. Veri kalitesi tablosu
| # | Kontrol | Sorgu (hepsi `sqlite3 -readonly data/yokatlas.db`) | Sonuç | Önem |
|---|---|---|---|---|
| K1 | Farklı `il` değeri sayısı | `SELECT COUNT(DISTINCT il) FROM programs` | **91** (81 TR ili + 6 KKTC + 4 yurt dışı) | bilgi |
| K2 | Boş `il` | `SELECT COUNT(*) FROM programs WHERE il IS NULL` | **110** satır / **9** kurum; hepsi `son_kilavuz_yili=2026` | **P1** |
| K3 | TR dışı `il` satırı | `WHERE il IN ('LEFKOŞA','GİRNE','GAZİMAĞUSA','LEFKE','GÜZELYURT','KIBRIS','SARAYBOSNA - BOSNA - HERSEK','BİŞKEK-KIRGIZİSTAN','TÜRKİSTAN-KAZAKİSTAN','BAKÜ-AZERBAYCAN')` | **1.291** | **P1** |
| K4 | TR ili tam mı | aynı listenin `NOT IN`'i + `COUNT(DISTINCT il)` | **81/81** — eksik il yok, fazla il yok | ✓ temiz |
| K5 | Yanlış `unitur='DEVLET'` | `WHERE unitur='DEVLET' AND (universite LIKE 'KIBRIS AMERİKAN%' OR LIKE '%BALKAN%' OR LIKE '%SARAYBOSNA%')` | **100** satır | **P1** |
| K6 | "Vakıf" kovasının saflığı | `WHERE unitur IS NOT NULL AND unitur<>'DEVLET' GROUP BY unitur` | VAKIF 7.974 · **KKTC 1.145** · VAKIF MYO 121 · **YURTDISI KAMU 99** · **YURTDISI VAKIF 12** | **P1** |
| K7 | `unitur` boş | `WHERE unitur IS NULL` | **0** ✓ (`unitur-onar.ts` işini yapmış) | ✓ |
| K8 | Aynı kurumun iki `universite` yazımı | `bazAd` çakışma sorgusu (§3.4) | **95 kurum / 1.449 satır** — bildirilen "10 KKTC üniversitesi" değil, **katalogun tamamı** | P2 |
| K9 | Aynı kurumda iki farklı `unitur` | K8 sorgusunun `unitur` kırılımı | **4 kurum**: Balkan, Saraybosna, Manas, Yesevi (DEVLET↔YURTDISI KAMU / KAMU↔VAKIF) | **P1** |
| K10 | Ayırt edilemeyen program adı (2026 aktif) | `GROUP BY universite,isim,tur,onlisans HAVING COUNT(*)>1` | **4.206 grup / 10.164 satır** (Vakıf 6.079 · Devlet 3.209 · KKTC 985) | **P1** |
| K11 | Vakıf lisansta burs etiketi | §4 sorgusu | **3.821/4.775 etiketsiz** (KKTC 747/849) — bildirilen rakam **doğrulandı** | **P1** |
| K12 | Etiketin satır yaşıyla ilişkisi | §4 sorgusu | 2026'da yeni: **326/348 etiketli**; eskiden var olan: **628/4.427** | **kanıt** |
| K13 | `yerlesen > kontenjan` | `WHERE yerlesen2026 > kontenjan2026` | **11.964/21.493** satır; devlet lisansta 5.618, KKTC lisansta **0** | **P1** |
| K14 | `kontenjan` = genel kontenjan mı | `kontenjan2025 <> gk2025` | **0** satır → evet, yalnız genel kontenjan | **kanıt** |
| K15 | `netler` yetim satırı | `LEFT JOIN programs ... WHERE p.id IS NULL` | **8.215** satır (silinmiş/kimliği devredilmiş kodlara ait) | P2 |
| K16 | `netler` yıl kapsamı | `SELECT MAX(yil) FROM netler` | **2025** — T36 doğrulandı, 2026 net verisi yok | **P1** |
| K17 | Aykırı sıralama | `WHERE sira2026<=0` | **0** ✓ | ✓ |
| K18 | `fakulte` boş (2026 aktif) | `WHERE fakulte IS NULL AND kontenjan2026 IS NOT NULL` | **0** ✓ | ✓ |
---
## 3. Görev 1 — `programs.il` (A4 / T34)
### 3.1 Bildirilen bulguların tek tek doğrulanması
| Bildirilen | Durum | Kanıt |
|---|---|---|
| 91 farklı `il` değeri | **DOĞRU** | K1 |
| `il` boş 110 satır / 9 üniversite | **DOĞRU** | K2; kurum listesi §3.2 |
| Uluslararası Balkan Ü. 26 satır `il='SARAYBOSNA - BOSNA - HERSEK'`, kurum Üsküp'te | **DOĞRU** (26 satır) — ayrıca aynı kurumun 8 satırı `il` boş, 14 satırı ayrı adla `YURTDISI KAMU` | §3.2 |
| Kıbrıs Amerikan Ü. 42 satır `unitur='DEVLET'` | **DOĞRU** (36 + 6, iki ad hattı) | K5 |
| `src/lib/db.ts:79` devlet filtresi bunları devlet sayıyor | **DOĞRU** | `uniturFiltreSql`, `src/lib/db.ts:77-83` [K] |
| 10 KKTC üniversitesi iki ayrı `universite` adıyla duruyor | **DOĞRU ama eksik tarif** — aynı desen **95 kurumda** var (1.449 satır). KKTC'ye özgü değil, API'nin 2026 ad biçiminden geliyor | K8 |
| ODTÜ KKK programları ana kampüsle **aynı `universite` ve `il`** altında | **YARI ÇÜRÜTÜLDÜ.** 8 KKK satırı `il='KIBRIS'` ve `fakulte='ODTÜ Kuzey Kıbrıs Kampusu (KKTC-Güzelyurt)'` taşıyor — yani ayrılabilir. Ortak olan yalnız `universite`. **Ama** ODTÜ *Yazılım Mühendisliği*'nin 2 satırı gerçekten `il='ANKARA'`, `fakulte='Mühendislik Fakültesi'` ile duruyor → yazarın asıl iddiası doğru, sebebi farklı | §3.3 |
### 3.2 Boş `il`: 110 satır, 9 kurum, hepsi 2026 kılavuzundan
```sql
SELECT universite, unitur, COUNT(*) FROM programs WHERE il IS NULL GROUP BY 1,2 ORDER BY 3 DESC;
```
| Kurum | `unitur` | Satır | `il` nereden türetilebilir |
|---|---|---|---|
| TİRAN NEW YORK ÜNİVERSİTESİ (TİRAN-ARNAVUTLUK) | YURTDISI KAMU | 36 | ad parantezi |
| İÇİŞLERİ BAKANLIĞI VE MİLLİ SAVUNMA BAKANLIĞI ADINA SAĞLIK BİLİMLERİ ÜNİVERSİTESİNDE EĞİTİM ALACAKLAR | DEVLET | 15 | **türetilemez** (sahte kurum adı; bakanlık kontenjanı) |
| ULUSLARARASI BALKAN ÜNİVERSİTESİ (ÜSKÜP-MAKEDONYA) | YURTDISI KAMU | 14 | ad parantezi |
| ULUSLARARASI SARAYBOSNA ÜNİVERSİTESİ (SARAYBOSNA-BOSNA-HERSEK) | YURTDISI KAMU | 14 | ad parantezi |
| ULUSLARARASI SARAYBOSNA ÜNİVERSİTESİ | DEVLET | 9 | kardeş satırdan |
| ULUSLARARASI BALKAN ÜNİVERSİTESİ | DEVLET | 8 | kardeş satırdan (**Üsküp**, Saraybosna değil) |
| KIRGIZİSTAN-TÜRKİYE MANAS ÜNİVERSİTESİ (BİŞKEK-KIRGIZİSTAN) | YURTDISI VAKIF | 8 | ad parantezi |
| HOCA AHMET YESEVİ … (TÜRKİSTAN-KAZAKİSTAN) | YURTDISI VAKIF | 4 | ad parantezi |
| KIBRIS AMERİKAN ÜNİVERSİTESİ | DEVLET | 2 | kardeş satırdan (LEFKOŞA) |
**95 satır ad/kardeş satırdan doldurulabilir; 15 satır (MSB/İçişleri) doldurulamaz** — ÖSYM bunları tek bir yerleşkeye bağlamıyor. Tahminle doldurmuyoruz; eksik, eksik kalır ve `veri-kalite`'de **beyaz listeye** alınır.
### 3.3 Kök neden — hangi betik hangi alanı nereden yazıyor
| Alan | Yazan | Kaynak | UPDATE yolunda tazeleniyor mu |
|---|---|---|---|
| `il` | `ingest.ts` (2021 CSV) → sonra yalnız `refresh.ts` INSERT (`r.ilAdi`, satır 679) | üçüncü parti CSV, sonra API | **HAYIR** |
| `unitur` | `ingest.ts` CSV → `refresh.ts` INSERT `uniturSec()` (518-524) → `unitur-onar.ts` yalnız NULL'lar | CSV, sonra API (koşullu) | **HAYIR** |
| `fakulte` | `ingest.ts` CSV → `refresh.ts` INSERT `fakulteSec()` | CSV, sonra API | **HAYIR** |
| `isim` | `ingest.ts` CSV → `refresh.ts` INSERT `r.birimAdi`; UPDATE yalnız `--isim-esitle` ile (643-648) | CSV, sonra API | **bayrak kapalıyken HAYIR** |
| `sira/puan/kontenjan/yerlesen` | `refresh.ts` UPDATE (474-480) | API | evet |
Üç mekanizma üst üste biniyor:
**(a) UPDATE körlüğü.** `refresh.ts:665-680` — `if (exists.get(id)) update.run(...)` yalnız dört yıl kolonunu yazar. 2021 CSV'sinden gelen `il`/`fakulte`/`isim` beş yıldır hiç tazelenmedi. Kıbrıs Amerikan'ın 36 satırı `il='LEFKOŞA'`, Balkan'ın 26 satırı `il='SARAYBOSNA - BOSNA - HERSEK'` — ikisi de **2021 verisi taşıyor** (`kontenjan2021 IS NOT NULL`), yani CSV kökenli [D].
**(b) `uniturSec` yanlışı kalıcılaştırıyor.** `refresh.ts:519-525`:
```ts
const uniturSec = (universite: string, api: string | null): string | null => {
for (const k of [universite, bazAd(universite)]) {
const set = uniturlar.get(k);
if (set?.size === 1) return [...set][0]; // ← DB'deki değer API'yi EZİYOR
}
return api;
};
```
Niyet doğru (sözlük tutarlılığı, `uniturOnar`'ın çelişki koruması patlamasın diye), sonuç ters: API "KKTC" dese bile DB'de tek bir `DEVLET` varsa `DEVLET` yazılır. Kıbrıs Amerikan'ın 2026'da eklenen 6 yeni satırı bu yüzden de `DEVLET` oldu.
**(c) İki ayrı ad hattı = iki ayrı kaynak.** API 2026'da üniversite adını **`AD (İL)`** biçiminde veriyor (`ORTA DOĞU TEKNİK ÜNİVERSİTESİ (ANKARA)`, `DOĞU AKDENİZ ÜNİVERSİTESİ (KKTC-GAZİMAĞUSA)`). CSV ise sade ad + ayrı `il` veriyordu. Böylece 95 kurumda iki paralel ad hattı oluştu:
```sql
-- K8
WITH b AS (SELECT universite, unitur, il,
TRIM(CASE WHEN universite LIKE '%)' THEN substr(universite,1,instr(universite,' (')-1)
ELSE universite END) baz, COUNT(*) n
FROM programs GROUP BY 1,2,3)
SELECT baz, universite, unitur, COALESCE(il,'(NULL)'), n FROM b
WHERE baz IN (SELECT baz FROM b GROUP BY baz HAVING COUNT(DISTINCT universite)>1);
-- 95 kurum / 1.449 satır
```
Yıl profili: `AD (TR ili)` eki 1.224 satır/80 kurum · `AD (KKTC-şehir)` 149/10 · `AD (şehir-ülke)` 76/5 [D].
**ODTÜ örneği — sorunun tam resmi.** `universite='ORTA DOĞU TEKNİK ÜNİVERSİTESİ (ANKARA)'` altında 11 satır var: 3'ü `il='ANKARA'` (KKTC uyruklu kontenjanı, doğru), 8'i `il='KIBRIS'` + `fakulte='ODTÜ Kuzey Kıbrıs Kampusu (KKTC-Güzelyurt)'` (doğru). **Ama** `universite='ORTA DOĞU TEKNİK ÜNİVERSİTESİ'` altındaki 72 eski CSV satırının içinde *Yazılım Mühendisliği* de var:
```sql
SELECT universite, il, fakulte, isim, kontenjan2026, sira2026
FROM programs WHERE isim LIKE 'Yazılım Müh%' AND universite LIKE 'ORTA DOĞU%';
-- ORTA DOĞU TEKNİK ÜNİVERSİTESİ | ANKARA | Mühendislik Fakültesi | Yazılım Mühendisliği | 45 | 299241
-- ORTA DOĞU TEKNİK ÜNİVERSİTESİ | ANKARA | Mühendislik Fakültesi | Yazılım Mühendisliği | 5 | 293024
```
ODTÜ Ankara'da Yazılım Mühendisliği **yoktur**; program Kuzey Kıbrıs Kampusu'ndadır (`ncc.metu.edu.tr/tr/sng`, yazar 13 teyit etmiş) [doğrulanmalı: 2026 ÖSYM kılavuzu]. 45/5 kontenjan ikilisi de KKK'nin klasik **Burslu / %50 İndirimli** desenidir — ama iki satırın adı birebir aynı, çünkü A5'teki etiket kaybı tam burada vuruyor. Yani üç hata aynı satırda: yanlış `il`, yanlış `fakulte`, kayıp burs etiketi. Aynı desen ODTÜ'de 16 ad grubunda daha var (Bilgisayar Müh. ×3 → 105/65/65, Elektrik-Elektronik ×3, İşletme ×6 …) [D].
### 3.4 Etki haritası — hangi yüzey ne yanlış gösteriyor
| Yüzey | Dosya | Ne oluyor | Etkilenen |
|---|---|---|---|
| **Sihirbaz "Devlet" adımı** | `src/lib/db.ts:78` `unitur = 'DEVLET'` | KKTC ve Balkan/Saraybosna programları devlet üniversitesi gibi havuza giriyor | **100 satır** |
| **Sihirbaz "Vakıf (burslu olursa)" adımı** | `src/lib/db.ts:79-80` `unitur <> 'DEVLET'` | KKTC (1.145) + yurt dışı (111) satırı vakıf havuzuna giriyor; etiket kaybı yüzünden öğrenci hangisinin burslu olduğunu da göremiyor | **1.256 satır / havuzun %13,4'ü** |
| **Sihirbaz il adımı (facet)** | `src/lib/db.ts:325-327` — kodda not düşülmüş: "81 il + KKTC/yurtdışı" | DAÜ'nün 276 satırı **GAZİMAĞUSA** ve **KIBRIS** çiplerine bölünmüş; aynı bölünme 9 KKTC kurumunda var | **1.080 satır** |
| **`/universiteler` hub'ı** | `src/lib/katalog.ts:270-337` | `MAX(unitur)` + alfabetik ilk ad hattı kazanıyor → Uluslararası Balkan Ü. **"Devlet / Saraybosna"** görünüyor (doğrusu: yurt dışı kamu / Üsküp) | 3 kurum kartı |
| **`/universite/<slug>`** | `src/lib/katalog.ts:402` `stats.devletMi` | Kıbrıs Amerikan Ü. sayfasında "devlet üniversitesi" rozeti | 1 sayfa |
| **il faceti / il listesi** | aynı | `il` boş 110 satır **hiçbir il filtresine düşmüyor** — sessizce kayboluyor | 110 satır |
| **`/il/[slug]` planı (T7, #18 yazısı)** | henüz yok | Bugünkü `SELECT DISTINCT il` 91 değer döner → `/il/baku-azerbaycan`, `/il/kibris` gibi sayfalar üretilir | **önkoşul** |
| **Bu gecenin yazıları** | `content/rehber/bilgisayar-mi-yazilim-muhendisligi-mi.md` | ODTÜ head-to-head tablodan çıkarılmış ve **neden çıkarıldığı yazıda yazılmış** → doğru davranış, düzeltme gerekmiyor. Ama aynı yazının **devlet doluluk** rakamları §5'teki kota asimetrisinden sapmalı | 1 yazı, 2 rakam |
| | `content/rehber/kktc-universiteleri-okunur-mu.md` | KKTC evreni `unitur='KKTC' OR universite LIKE 'KIBRIS AMERİKAN%'` ile elle kurulmuş → yazı **doğru**; düzeltme sonrası sorgu sadeleşir, rakam değişmez | — |
### 3.5 Önerilen şema — **yeni kolon yok**
Soru "il yanında `ulke`/`bolge` mi, yoksa ayrı `kampus` alanı mı" şeklinde soruldu. **Cevabım: ikisi de değil.** Her iki bilgi de zaten DB'de:
- **Ülke/statü ayrımı `unitur`'de yaşıyor:** `DEVLET · VAKIF · VAKIF MYO · KKTC · YURTDISI KAMU · YURTDISI VAKIF`. Bir `ulke` kolonu bu sözlüğün kopyasını çıkarır ve iki alanın çelişme ihtimalini yaratır.
- **Kampüs bilgisi `fakulte`'de yaşıyor:** `ODTÜ Kuzey Kıbrıs Kampusu (KKTC-Güzelyurt)`, `ASBÜ-Kuzey Kıbrıs Yerleşkesi (KKTC-Lefkoşa)`, `İTÜ-KKTC EĞİTİM ARAŞTIRMA YERLEŞKESİ (GAZİMAĞUSA)` [D].
| | A) `ulke`/`bolge` kolonu | B) `il` normalize + `kampus` kolonu | **C) Kolon yok: `il`'i normalize et, `unitur`'ü düzelt** |
|---|---|---|---|
| Göç | `yokatlas-goc.ts` + `ingest.ts` + `refresh.ts` INSERT + `veri-kalite.ts` | aynısı | **yok** |
| Dolduran kaynak | API'de **böyle bir alan yok** — ad parantezinden türetmek zorundayız | aynı sorun | ad parantezi (aynı iş, kolonsuz) |
| Yıllık refresh maliyeti | her yıl yeni kolonun da senkronu | aynı + `kampus` eşlemesi | `il` senkronu (zaten yapılmalı) |
| Okuyan taraf değişikliği | `katalog.ts`, `db.ts`, facet, tipler | aynısı + tipler | **tek satır filtre**: `AND unitur IN ('DEVLET','VAKIF','VAKIF MYO')` |
| T7 (`/il/[slug]`) çözülür mü | evet | evet | **evet** |
| Çift kaynak riski | `unitur` ile çelişebilir | `fakulte` ile çelişebilir | yok |
**Öneri C.** İki `UPDATE` + bir satır kod. Kurucunun "over-engineering yapma" talimatına uyan en küçük çözüm.
C'nin tek gerçek açığı, şema değil **hat** açığı: `il`/`fakulte`/`isim` UPDATE yolunda tazelenmediği sürece aynı kir her yıl birikir. Bunun kolonla ilgisi yok — çözümü `refresh.ts`'e `--kimlik-onar`/`--isim-esitle` ile aynı güvenlik desenini taşıyan bir **`--yer-esitle`** bayrağı: API ile `il`/`fakulte` farkı olan satırları önce **listeler**, gözle onaylanınca yazar. Ayrı bir CTO şartnamesine değer; bu gece yazılmaz.
### 3.6 Düzeltme betiği taslağı — **KOŞULMADI, yalnız yazıldı**
Ön koşullar: dev sunucu **kapalı** (WAL tek yazar), önce yedek, sonra `pnpm veri-kalite --yil 2026`.
```sh
# 0) Yedek — geri alma yolu budur. WAL'i önce kapat.
sqlite3 data/yokatlas.db "PRAGMA wal_checkpoint(TRUNCATE);"
cp data/yokatlas.db data/yokatlas.db.yedek-2026-09-22
```
```sql
BEGIN;
-- ── 1) unitur: yanlış DEVLET etiketleri (K5 = 100 satır) ────────────────
-- Kıbrıs Amerikan Ü. YÖK'ün KKTC listesinde (yok.gov.tr/tr/university?type=6)
UPDATE programs SET unitur='KKTC'
WHERE unitur='DEVLET' AND universite LIKE 'KIBRIS AMERİKAN%'; -- 42
-- Balkan + Saraybosna: aynı kurumun diğer ad hattı zaten YURTDISI KAMU
UPDATE programs SET unitur='YURTDISI KAMU'
WHERE unitur='DEVLET'
AND (universite LIKE 'ULUSLARARASI BALKAN%'
OR universite LIKE 'ULUSLARARASI SARAYBOSNA%'); -- 58
-- ── 2) il: KKTC'de 'KIBRIS' toplayıcısını şehre indir (179 satır) ───────
-- Şehir zaten ad ya da fakülte parantezinde yazılı; tahmin YOK.
UPDATE programs SET il = CASE
WHEN universite LIKE '%(KKTC-LEFKOŞA)%' THEN 'LEFKOŞA'
WHEN universite LIKE '%(KKTC-GİRNE)%' THEN 'GİRNE'
WHEN universite LIKE '%(KKTC-GAZİMAĞUSA)%' THEN 'GAZİMAĞUSA'
WHEN universite LIKE '%(KKTC-LEFKE)%' THEN 'LEFKE'
WHEN fakulte LIKE '%(KKTC-Lefkoşa)%' THEN 'LEFKOŞA'
WHEN fakulte LIKE '%(KKTC-Güzelyurt)%' THEN 'GÜZELYURT'
WHEN fakulte LIKE '%(GAZİMAĞUSA)%' THEN 'GAZİMAĞUSA'
END
WHERE il='KIBRIS'
AND (universite LIKE '%(KKTC-%' OR fakulte LIKE '%(KKTC-%' OR fakulte LIKE '%(GAZİMAĞUSA)%');
-- beklenen: 179; sonrasında SELECT COUNT(*) FROM programs WHERE il='KIBRIS' = 0
-- ── 3) il: yurt dışı değerini mevcut sözleşmeye uydur (26 satır) ────────
-- Mevcut sözleşme: 'ŞEHİR-ÜLKE' (BİŞKEK-KIRGIZİSTAN, TÜRKİSTAN-KAZAKİSTAN)
UPDATE programs SET il='ÜSKÜP-KUZEY MAKEDONYA'
WHERE universite='ULUSLARARASI BALKAN ÜNİVERSİTESİ' AND il='SARAYBOSNA - BOSNA - HERSEK'; -- 26
UPDATE programs SET il='SARAYBOSNA-BOSNA HERSEK'
WHERE il='SARAYBOSNA - BOSNA - HERSEK'; -- 15
-- ── 4) il: boş 110 satırın 95'i (kalan 15 bilerek NULL) ─────────────────
UPDATE programs SET il = CASE
WHEN universite LIKE '%(TİRAN-ARNAVUTLUK)%' THEN 'TİRAN-ARNAVUTLUK'
WHEN universite LIKE '%(ÜSKÜP-MAKEDONYA)%' THEN 'ÜSKÜP-KUZEY MAKEDONYA'
WHEN universite LIKE '%(SARAYBOSNA-BOSNA-HERSEK)%' THEN 'SARAYBOSNA-BOSNA HERSEK'
WHEN universite LIKE '%(BİŞKEK-KIRGIZİSTAN)%' THEN 'BİŞKEK-KIRGIZİSTAN'
WHEN universite LIKE '%(TÜRKİSTAN-KAZAKİSTAN)%' THEN 'TÜRKİSTAN-KAZAKİSTAN'
WHEN universite='ULUSLARARASI BALKAN ÜNİVERSİTESİ' THEN 'ÜSKÜP-KUZEY MAKEDONYA'
WHEN universite='ULUSLARARASI SARAYBOSNA ÜNİVERSİTESİ' THEN 'SARAYBOSNA-BOSNA HERSEK'
WHEN universite='KIBRIS AMERİKAN ÜNİVERSİTESİ' THEN 'LEFKOŞA'
END
WHERE il IS NULL
AND universite <> 'İÇİŞLERİ BAKANLIĞI VE MİLLİ SAVUNMA BAKANLIĞI ADINA SAĞLIK BİLİMLERİ ÜNİVERSİTESİNDE EĞİTİM ALACAKLAR';
-- beklenen: 95; kalan 15 MSB/İçişleri satırı NULL kalır (kaynak da boş veriyor)
COMMIT;
```
**Doğrulama sorguları (düzeltmeden sonra koşulur):**
```sql
SELECT COUNT(DISTINCT il) FROM programs; -- beklenen 88 (81 TR + 5 KKTC şehri + ... )
SELECT COUNT(*) FROM programs WHERE il IS NULL; -- beklenen 15
SELECT COUNT(*) FROM programs WHERE il='KIBRIS'; -- beklenen 0
SELECT COUNT(*) FROM programs WHERE unitur='DEVLET'
AND (universite LIKE 'KIBRIS AMERİKAN%' OR universite LIKE '%BALKAN%'
OR universite LIKE '%SARAYBOSNA%'); -- beklenen 0
SELECT COUNT(DISTINCT il) FROM programs
WHERE unitur IN ('DEVLET','VAKIF','VAKIF MYO'); -- beklenen 81 ← T7'nin kabul kriteri
SELECT SUM(kontenjan2026), SUM(yerlesen2026) FROM programs; -- düzeltmeden ÖNCEKİYLE AYNI olmalı
```
**Geri alma:** `data/yokatlas.db.yedek-2026-09-22` dosyasını geri kopyala. Betik yalnız 4 kolonsuz alana dokunuyor, sıralama/kontenjan verisine hiç dokunmuyor — son doğrulama sorgusu bunu kanıtlar.
**Birlikte gitmesi gereken kod değişikliği (tek satır):** `/il/[slug]` ve il faceti `AND unitur IN ('DEVLET','VAKIF','VAKIF MYO')` ile süzülmeli; yoksa `/il/uskup-kuzey-makedonya` üretilir. Sihirbazın "Vakıf" kovası da `unitur IN ('VAKIF','VAKIF MYO')` olmalı (`src/lib/db.ts:79`) — bu **ayrı bir ürün kararı**: KKTC programları havuzdan çıkarsa vakıf havuzu 9.351 → 8.095 satıra iner. **[BİLAL]** değil, `urun-yoneticisi`/`ceo` kararı.
**İdempotens uyarısı:** betik koşulduktan sonra `unitur-onar.ts`'in çelişki koruması (`aynı üniversitede birden fazla unitur`) hâlâ geçer — Balkan/Saraybosna'nın iki ad hattı farklı `universite` dizgileri olduğu için ayrı gruplar sayılıyor [K].
---
## 4. Görev 2 — vakıf burs etiketi (A5)
### Tek cümlelik cevap
**Etiket YÖK Atlas API'sinde ayrı bir alan değil, program adının (`birimAdi`) içinde geliyor; veri elimizde ve kırılım yapılabilir — bugün eksik olmasının sebebi `refresh.ts`'in `--isim-esitle` bayrağının varsayılan kapalı olması, kaynağın etiketi vermemesi değil.**
### Kanıt zinciri
**(1) Kodun kendi belgesi** — `scripts/refresh.ts:37-39`:
> `--isim-esitle`: kimliği AYNI olup yalnız adı farklı satırlarda (API burs/dil eki veriyor: "Tıp (İngilizce) (Burslu)") isim API'den yazılır. **Varsayılan KAPALI**: isim, sihirbaz kategorilerini ve bölüm sayfası başlığını besler.
Yani etiketin kaynağı biliniyor ve yazılmaması **bilinçli bir seçim**. Gerekçe de meşru: `isim` sihirbaz kategorilerini besliyor, "Tıp (Burslu)" ile "Tıp" farklı kategoriye düşebilir.
**(2) API isteği burs boyutunu tanıyor** — `refresh.ts:181` filtre nesnesinde `bursOraniId: null` var; yani uç nokta burs oranına göre süzmeyi destekliyor. Ama yanıt kaydından tutulan alanlar listesinde (`TUTULAN_ALANLAR`, satır 124-148) burs alanı **yok** — ham `.jsonl.gz` dosyası kaydın tamamını yazıyor (`refresh.ts:378`), ince kayıt değil, ama `data/ham/` bu makinede **mevcut değil** (`.gitignore:48`), bu yüzden API yanıtında ayrı bir `bursOrani` alanı olup olmadığı **yerel olarak doğrulanamadı** [doğrulanmalı — tek `--ham` koşusuyla ya da 1 isteklik `size:1` sorgusuyla 2 dakikada kapanır].
**(3) Asıl kanıt — satır yaşına göre etiketlilik.** Yeni satırlar `INSERT`'te `r.birimAdi`'yi doğrudan yazıyor (`refresh.ts:677`), eski satırların adı hiç güncellenmiyor:
```sql
SELECT CASE WHEN sira2025 IS NOT NULL OR kontenjan2025 IS NOT NULL
THEN '2025te de vardi' ELSE '2026da yeni' END durum,
COUNT(*) n,
SUM(isim LIKE '%(Burslu)%' OR isim LIKE '%İndirimli)%' OR isim LIKE '%(Ücretli)%') etiketli
FROM programs
WHERE kontenjan2026 IS NOT NULL AND onlisans=0 AND unitur LIKE 'VAKIF%'
GROUP BY 1;
```
| Satır | n | Etiketli | Oran |
|---|---|---|---|
| 2026'da **yeni açılan** (isim API'den yazıldı) | 348 | **326** | **%93,7** |
| 2025'te de **var olan** (isim 2021 CSV'sinden) | 4.427 | 628 | %14,2 |
Aynı veri, aynı kurumlar, aynı yıl — tek fark satırın INSERT mi UPDATE mi yolundan geçtiği. **API etiketi veriyor; biz yazmıyoruz.**
**(4) `veri_meta` kaydı da aynı şeyi gösteriyor.** `kimlik_onar:*` kayıtlarının `yeni.isim` alanları API'den geldiği gibi duruyor: `"Ebelik (Burslu)"`, `"Ebelik (%50 İndirimli)"`, `"Siber Güvenlik (Burslu) (İngilizce)"`, `"Endüstri Mühendisliği (Ücretli)"`, `"Anestezi (%25 İndirimli)"` [D]. Etiket sözlüğü tam: **Burslu · %75/%50/%25 İndirimli · Ücretli**.
### Bugünkü kırılım (bildirilen rakamlar doğrulandı)
```sql
SELECT CASE WHEN unitur LIKE 'VAKIF%' THEN 'Vakıf' WHEN unitur='KKTC' THEN 'KKTC'
WHEN unitur='DEVLET' THEN 'Devlet' ELSE unitur END grup,
SUM(onlisans=0) lisans,
SUM(onlisans=0 AND isim LIKE '%(Burslu)%') burslu,
SUM(onlisans=0 AND isim LIKE '%İndirimli)%') indirimli,
SUM(onlisans=0 AND isim LIKE '%(Ücretli)%') ucretli,
SUM(onlisans=0 AND isim NOT LIKE '%(Burslu)%' AND isim NOT LIKE '%İndirimli)%'
AND isim NOT LIKE '%(Ücretli)%') etiketsiz
FROM programs WHERE kontenjan2026 IS NOT NULL GROUP BY 1;
```
| Grup | 2026 lisans | Burslu | İndirimli | Ücretli | **Etiketsiz** |
|---|---|---|---|---|---|
| Devlet | 6.505 | 9 | 39 | 13 | 6.444 (beklenen — devlette burs etiketi olmaz) |
| **Vakıf** | 4.775 | 339 | 416 | 199 | **3.821 (%80,0)** |
| **KKTC** | 849 | 39 | 51 | 12 | **747 (%88,0)** |
| Yurt dışı kamu | 98 | 14 | 31 | 19 | 34 |
Yazarların bildirdiği 3.821/4.775 ve (873 payda ile) 768/873 rakamları **doğrulandı**; payda farkı (849 vs 873) yalnız KKTC evreninin `unitur='KKTC'` mi yoksa `+ Kıbrıs Amerikan` mı tanımlandığına bağlı — A4 düzeltmesinden sonra iki tanım birleşiyor.
### `data/kaynak/` altındaki dosyalarda burs bilgisi var mı
**Yok.** Oradaki iki dosya kurum düzeyinde YÖK istatistiği:
- `yok-istatistik-ogrenci-sayilari-2025-2026.xls` — sütunları: `Okuyan Önlisans · Okuyan Lisans · Okuyan Yükseklisans · Okuyan Doktora · Genel Toplam`, satırları üniversite × il × (DEVLET/VAKIF/KKTC).
- `yok-istatistik-ogretim-elemani-sayilari-2025-2026.xls` — öğretim elemanı sayıları.
İkisi de **program düzeyinde değil**, burs/ücret alanı içermiyor (JasperReports dökümü; `file` + `strings` ile başlık satırları okundu, dosyalar değiştirilmedi). Bu dosyalar A5 için kullanılamaz; başka bir işe (kurum büyüklüğü/öğrenci-öğretim üyesi oranı içerikleri) yarayabilir.
### Yazarlara verilecek net cevap
> **Kırılım bugün yapılamaz, ama kalıcı olarak imkânsız değil.** Veri kaynakta var; DB'ye tek bir refresh koşusuyla girer. **Bu koşu yapılana kadar hiçbir yazıda burslu/%50/ücretli dağılımı verilmesin** — bugünkü sayımlar (%80'i etiketsiz) gerçek dağılım değil, tazelenmemiş adların sayımıdır ve yayımlanırsa **yanlış** olur.
### Bu koşunun bedeli ve riski (Bilal/CTO için)
```sh
# ÖNCE kopyada: ham dosya yoksa API'den tek geçiş (~22 sn/21.493 kayıt, 0,5 sn/sayfa)
cp data/yokatlas.db /tmp/deneme.db
pnpm refresh --yil 2026 --db /tmp/deneme.db --isim-esitle
pnpm veri-kalite --yil 2026 --db /tmp/deneme.db --onceki data/yokatlas.db
```
- **Etkilenecek satır:** kabaca 10.164 (K10'daki ayırt edilemeyen ad grupları); kesin sayıyı koşunun `"yalnız adı (burs/dil eki) farklı N satır"` satırı verir (`refresh.ts:609`).
- **Risk — küçümsenmemeli:** `isim` sihirbaz kategorilerini (`src/lib/kategoriler.ts`) ve `/bolum/<slug>` başlıklarını besliyor. "Bilgisayar Mühendisliği" → "Bilgisayar Mühendisliği (Burslu)" olursa kategori eşlemesi ve bölüm slug'ı kayabilir; **kaydedilmiş raporlardaki program adları da tutmayabilir.** Bu yüzden doğru sıra: (1) kopyada koş, (2) kategori eşleme farkını say, (3) gerekirse okuyan tarafa "etiketi kırp" normalizasyonu ekle, (4) ancak sonra gerçek DB. **Bu gece yapılmaz.**
- **Daha ucuz alternatif:** `isim`'e hiç dokunmadan ayrı bir `burs` kolonu türetmek (`Burslu/%75/%50/%25/Ücretli/—`). Ama bu §3.5'te reddettiğim "yeni kolon" yoluna girer ve kategori riskini de çözmez, sadece erteler. **Önerim: `--isim-esitle` + okuyan tarafta etiket kırpma.**
---
## 5. Kapsam dışı ama yayını ilgilendiren bulgu: doluluk oranları yukarı sapmalı
Görevde yok, ama bu gece yayımlanan rakamları etkilediği için rapora giriyor.
```sql
SELECT COUNT(*) FROM programs WHERE kontenjan2025 IS NOT NULL AND gk2025 IS NOT NULL
AND kontenjan2025 <> gk2025; -- 0 → kontenjan = YALNIZ genel kontenjan
SELECT COUNT(*) FROM programs WHERE yerlesen2025 IS NOT NULL AND gkY2025 IS NOT NULL
AND yerlesen2025 <> gkY2025; -- 7.989 → yerlesen = gkY+sgyY+dprmY+obkY
```
`scripts/refresh.ts:212-217` `yerlesen()` dört kota türünü toplarken, `kontenjan` kolonuna yalnız `r.kontenjan` (genel kontenjan) yazılıyor. Pay ile payda aynı evreni saymıyor:
| Grup (2026 lisans) | Kontenjan | Yerleşen | Doluluk | `yerlesen>kontenjan` satır |
|---|---|---|---|---|
| Devlet | 280.131 | 286.150 | **%102,1** | **5.618** |
| Vakıf | 99.638 | 78.475 | %78,8 | — |
| KKTC | 13.162 | 7.923 | %60,2 | **0** |
- **KKTC ve vakıf rakamları güvende** — KKTC'de okul birincisi/şehit-gazi/depremzade kontenjanı olmadığı için sapma sıfır; `kktc-universiteleri-okunur-mu` yazısının ÖSYM ile birebir uyuşması bunu bağımsız olarak doğruluyor (13.162/7.923 ÖSYM Tablo 1 ile aynı).
- **Devlet doluluk rakamları sapmalı.** `bilgisayar-mi-yazilim-muhendisligi-mi` yazısındaki "devlet YM **%102,1**" tam olarak bu sapmadır; %100'ü aşan her doluluk rakamı bu hatanın imzasıdır.
- **En küçük düzeltme yazı tarafında:** doluluk hesabında paydayı da tüm kota türlerini kapsayacak şekilde kurmak mümkün değil (toplam kontenjan kolonu DB'de yok) → bu sezon **devlet için doluluk rakamı yayımlanmasın**, ya da "genel kontenjana göre" kaydıyla ve %100 üstü değerler açıklanarak verilsin. Kalıcı düzeltme `kontenjanToplam<yıl>` kolonu gerektirir → yeni yılın refresh'ine bağlanmalı, bu gece değil.
- **Backlog önerisi:** `veri-kalite.ts`'e **ZORUNLU** kontrol olarak `yerlesen>kontenjan` oranı eklensin; bugün böyle bir kontrol yok (`scripts/veri-kalite.ts:145-150` yalnız `unitur boş` / `il boş` **bilgi** satırı basıyor, çıkış kodunu etkilemiyor).
---
## 6. Backlog önerileri (`urun-yoneticisi`ne)
| Öneri | Gerekçe | Boy |
|---|---|---|
| **BACKLOG #9'u genişlet:** "3 yurt dışı/KKTC üniversitesi DEVLET etiketli" → gerçek kapsam **100 satır + 179 `il='KIBRIS'` + 110 boş `il` + 26 yanlış şehir**; çözüm §3.6 betiği | bugünkü madde kapsamı gerçeğin üçte biri | S |
| **T34 kabul kriteri:** `SELECT COUNT(DISTINCT il) FROM programs WHERE unitur IN ('DEVLET','VAKIF','VAKIF MYO')` = **81** ve `COUNT(*) WHERE il IS NULL` = **15** | T7/#18'in önkoşulu, komutla doğrulanabilir | — |
| **Yeni:** `refresh.ts --yer-esitle` (il/fakulte senkronu, önce listeler sonra yazar) | yoksa aynı kir 2027'de yeniden birikir | M |
| **Yeni:** `veri-kalite.ts`'e 3 ZORUNLU kontrol — (a) aynı baz kurum adında iki `unitur`, (b) TR dışı `il` × TR `unitur` çelişkisi, (c) `yerlesen>kontenjan` | üçü de bu gece elle bulundu; otomatik olmalı | S |
| **A5 sonrası:** `--isim-esitle` koşusu + kategori eşleme farkının sayımı | T11'in önkoşulu | M |
---
## 7. Engeller
1. **`data/ham/2026-2026-09-21.jsonl.gz` bu makinede yok** (`.gitignore:48`, dizin hiç yok). API yanıtında ayrı bir `bursOrani`/`ogrenimTuru` alanı olup olmadığını yerel olarak doğrulayamadım — A5'in cevabı bundan bağımsız (etiket `birimAdi` içinde geliyor, §4/3 kanıtı), ama "ayrıca ayrı kolon da var mı" sorusu açık kaldı.
2. **Disk.** Kural gereği DB kopyası alınmadı, betik denemesi yapılmadı; §3.6 ve §4'teki komutlar **hiç koşulmadı**, yalnız yazıldı.
3. **ÖSYM 2026 kılavuzu açılamadı** (yazar 14 de aynı engele takılmış: PDF metin katmanı çıkarılamıyor, makinede `poppler` yok). "ODTÜ Yazılım Mühendisliği Ankara'da değil, Kuzey Kıbrıs'ta" iddiası bu yüzden kılavuz maddesine değil, (a) ODTÜ KKK'nin kendi sayfasına ve (b) 45/5 Burslu-%50 kontenjan desenine dayanıyor → **[doğrulanmalı]** işaretli kaldı.
---
## Bilal'den istenen (3 madde)
1. **§3.6 düzeltme betiğine onay** — 100 `unitur` + 320 `il` satırını düzeltir, sıralama/kontenjan verisine dokunmaz, geri alma tek `cp`. Onaylarsan betiği `veri/il-temizligi` dalında yazıp kopyada doğrularım; T7 (`/il/[slug]`) ve #18 yazısı bu onaya bağlı. *(karar: 3 dk)*
2. **Ürün kararı: sihirbazın "Vakıf (burslu olursa)" adımı KKTC ve yurt dışı programlarını kapsasın mı?** Bugün kapsıyor (1.256 satır, havuzun %13,4'ü) ve öğrenciye söylenmiyor. Kapsamasın dersen vakıf havuzu 9.351 → 8.095'e iner. *(karar: 2 dk)*
3. **Devlet doluluk rakamı bu sezon yayımlanmasın** onayı — `bilgisayar-mi-yazilim-muhendisligi-mi` yazısındaki "%102,1" ve "%99,8" kota asimetrisinden sapmalı (§5); yazı yayına girmeden `rehber-editoru` o iki rakamı çıkarsın ya da "genel kontenjana göre" kaydıyla versin. *(karar: 2 dk, uygulama: 10 dk)*

View File

@@ -0,0 +1,206 @@
# 27 — A9 marka tescili engel kontrolü + A2 paket adı teyidi
> Rol: Marka/pazarlama stratejisti · Gece vardiyası, 22 Eylül 2026 · Görev: `24-ceo-kapanis.md` A9 + A2
> Yöntem: yalnızca okuma. Kod/içerik değiştirilmedi, başvuru/form/hesap/ödeme yok.
> İşaretler: **[K]** koddan doğrulandı · **[W]** kaynak açılıp okundu · **[A]** yalnız arama özeti · **[V]** varsayım · **doğrulanmalı**
## Özet (5 madde)
1. **"KOLAYTERCİH" tek kelime hâlinde Türkiye'de tescilli değil — hiçbir sınıfta, hiçbir ofiste.** TMview'de (TÜRKPATENT'in resmî besleme yaptığı ortak veri tabanı) `kolaytercih` için exact/contains/fuzzy üç aramanın üçü de **0 sonuç** [W].
2. **Tek yakın kayıt "kolay tercih" (ayrı yazım): VODAFONE TELEKOMÜNİKASYON A.Ş., 2012/98440, sınıf 9-35-38-42, durum "Ended" (sona ermiş), başvuru 26.11.2012** [W]. Sona ermiş bir markanın engel gücü yoktur ve zaten **bizim asıl sınıfımız olan 41'i hiç kapsamıyor**.
3. **Hüküm: görünür engel yok.** Aynı ya da ayırt edilemeyecek kadar benzer, **yürürlükte** bir marka bulunamadı. Tek izlenecek kayıt **"easytercih"** (2026/031206, sınıf 9-16-35-38-40-41-42-45, durum "Filed", 10.03.2026) — adımızın İngilizce birebir çevirisi, henüz tescilli değil [W]. **doğrulanmalı:** nihai benzerlik değerlendirmesi marka vekilinin işidir, benim değil.
4. **"kolaytercih" adıyla faaliyet gösteren başka ticari site yok.** `kolaytercih.com` yalnız bizim; `.com.tr / .net / .org / .app / .ai / .co` ve `kolay-tercih.com` **DNS'te yok** [K, komut çıktısı]. Ayrıca **`.com.tr` artık marka tescil belgesi istemiyor** — TRABİS 14 Eylül 2022'den beri "ilk gelen alır" [W]. Bu, kendi 03 raporumun §1.4'ündeki "asıl kapı marka tescili" cümlesini **düzeltir**.
5. **A2 — "KolayTercih Paketi" sezon sorununu çözer ama iki yeni sorun doğurur:** (a) iyzico sepetine giden metin `odeme-actions.ts:74`'te zaten `KolayTercih — ${label}` diye önek alıyor → sepette **"KolayTercih — KolayTercih Paketi"** yazar [K]; (b) ad, "ne aldığını söyle" ölçütünü karşılamıyor. **Önerim: "Tercih Listesi Paketi".** Ayrıca kritik düzeltme: **banka ekstresinde paket adı görünmez**, iyzico'da ekstre "iyzico/üye iş yeri" formatındadır [A] — ekstre riskini ad değil, **Bilal'in iyzico üye iş yeri unvanı** belirler.
---
# GÖREV 1 — A9: "KolayTercih" marka tescilinde engel var mı?
## 1.1 Yöntem ve erişim engeli (dürüstlük notu)
**TÜRKPATENT'in kendi kamuya açık arama ekranı bu vardiyada kullanılamadı.** `https://www.turkpatent.gov.tr/arastirma-yap?form=trademark` bir JS uygulaması; arka uçtaki `POST /api/research` çağrısı **reCAPTCHA token'ı zorunlu tutuyor** ve token'sız istek şu cevabı döndürüyor [W]:
```
{"success":false,"error":{"code":"HUMAN_CHECK_ERROR","message":"Human check error"}}
```
Protokol md.5 CAPTCHA çözmeyi yasaklıyor, ısrar etmedim. **Uydurma sonuç vermemek için alternatif kaynağa geçtim:**
| Kaynak | Ne | Neden geçerli |
|---|---|---|
| **TMview** (`tmdn.org/tmview`, EUIPO işletiyor) | Ulusal ofislerin resmî beslemesi | TR kayıtlarında `tmOffice: "TR"` ve her kaydın detay linki **`online.turkpatent.gov.tr/CES/tmview/trademark/data/...`** — yani veriyi TÜRKPATENT'in kendisi veriyor [W] |
| **Güncellik denetimi** | Aramalarda **07.08.2026** tarihli TR başvuruları göründü (ör. 2026/103184) | Veri en az Ağustos 2026'ya kadar taze [W] |
| **Kapsam denetimi** | "tercih" + sınıf 41 → **203 TR kaydı**; sınıf 42 → **65 kayıt** | TR koleksiyonu eksik değil [W] |
**Uyarı:** TMview durum etiketleri kabadır ("Filed / Registered / Ended / Expired"). Ret mi, geri çekme mi, süre bitimi mi ayrımı için TÜRKPATENT dosya sorgusu gerekir — **doğrulanmalı**.
## 1.2 Aranan terimler ve sınıflar
Sınıflar görev tanımına göre: **41** (eğitim/öğretim), **42** (yazılım/SaaS), **9** (bilgisayar yazılımı). Ek olarak sınıf filtresiz tarama da yapıldı ki dar filtre yüzünden kayıt kaçmasın.
| # | Sorgu | Kriter | Sınıf filtresi | Sonuç |
|---|---|---|---|---|
| 1 | `kolaytercih` | Exact | yok (tüm ofisler) | **0** |
| 2 | `kolaytercih` | Contains | yok | **0** |
| 3 | `kolaytercih` | Fuzzy | yok | **0** |
| 4 | `kolaytercih` | Contains | TR | **0** |
| 5 | `kolay tercih` | Contains | TR | **1** (aşağıda) |
| 6 | `kolay tercih` | Exact | tüm ofisler | **1** (aynı kayıt) |
| 7 | `kolay` | Contains | TR + **41** | 274 kayıt — tarandı, çakışan yok |
| 8 | `kolay` | Contains | TR + **42** | 529 kayıt — tarandı, çakışan yok |
| 9 | `tercih` | Contains | TR + **41** | 203 kayıt — tarandı |
| 10 | `tercih` | Contains | TR + **42** | 65 kayıt — tarandı |
Sınıf 9 ayrı sorgulanmadı; 1–6 numaralı sorgular **sınıf filtresiz** olduğu için 9. sınıf zaten kapsandı ve "kolaytercih" hiçbir sınıfta çıkmadı [W].
## 1.3 Bulunan kayıtlar
### Tek "yakın" kayıt — çakışma değil
| Alan | Değer |
|---|---|
| Marka | **kolay tercih** (kelime markası) |
| Sahibi | **VODAFONE TELEKOMÜNİKASYON A.Ş.** |
| Başvuru no | **2012/98440** (ST13: TR502012000098440) |
| Sınıflar | **9, 35, 38, 42** — *41 yok* |
| Başvuru tarihi | **26.11.2012** |
| Durum | **Ended** (sona ermiş / yürürlükte değil) |
Kaynak: TMview kaydı, detay linki `online.turkpatent.gov.tr/CES/tmview/trademark/data/TR502012000098440` [W].
**Okuma:** Vodafone'un 2012'deki toplu kampanya başvurularından biri (aynı gün "yurtdışı kolaylığı…" 2012/98409 da var). Sona ermiş; **engel oluşturmaz**. Bizim adımız ayrıca **bitişik tek kelime** ve **41. sınıf** odaklı.
### İzlenmesi gereken tek kayıt
| Alan | Değer |
|---|---|
| Marka | **easytercih** (birleşik marka) |
| Başvuru no | **2026/031206** |
| Sınıflar | 9, 16, 35, 38, 40, **41**, **42**, 45 |
| Tarih / durum | 10.03.2026 / **Filed** (tescilli değil) |
| Sahibi | "Legally Restricted Until Publication Date" (bülten yayınına kadar gizli) |
**Neden önemli:** "easy" = "kolay". Aynı sınıflarda, aynı yapıda ("sıfat + tercih") bir başvuru. Tescil edilirse **kavramsal benzerlik** iddiasıyla bizim başvurumuza itiraz etme olasılığı sıfır değil [V — hukuki değerlendirme değildir]. Bugün **tescilli olmadığı için engel değil**; ama bizim başvurumuzu **geciktirmeden yapmak** lehimize, çünkü Türkiye'de marka hakkı **başvuru tarihine** göre sıralanır [A, doğrulanmalı].
### Çakışmayan ama ortamı gösteren kayıtlar (sınıf 41/42, yürürlükte)
| Marka | Sahibi | Sınıflar | Durum | Tarih |
|---|---|---|---|---|
| tercihbot | ÇARE ÖLÇME DEĞERLENDİRME … A.Ş. | 9,10,12,16,38,41,42 | **Registered** | 11.03.2025 → tescil 28.07.2025 |
| tercihpro | TERCİHPRO BİLGİ VE KARİYER DANIŞMANLIĞI A.Ş. | 9,10,12,16,38,42 | **Registered** | 03.05.2025 |
| tercih robotu | ES EĞİTİM TANITIM ORG. DAN. LTD. ŞTİ. | 7,9,35,38,42 | **Registered** | 02.05.2000 |
| ktr kültür tercih robotu | METOD EĞİTİM KURUMLARI A.Ş. | 41 | **Registered** | 23.07.2013 |
| geleceği planla tercih robotu | YEDİTEPE ÜNİVERSİTESİ | 9,10,12,16,35,38,41,42 | **Registered** | 15.08.2018 |
| tercih burada | LEVENT UYSAL | 41 | **Registered** | 06.08.2012 |
| tercih sihirbazı | (gizli) | 16,35,38,41,42 | Filed | 19.02.2023 |
| **tercih dönemi** | (gizli) | 38, 41 | Filed | 04.10.2020 |
| tercih360 / lisetercih / tercih tv | (gizli) | 35,41 / 35,41 / 35,41,42 | Filed | 2026-02 / 2025-09 / 2026-07 |
Hepsi TMview/TR [W]. **İki operasyonel not:**
- **"tercih robotu" ES EĞİTİM adına 2000'den beri tescilli (2000/08210, sınıf 7-9-35-38-42).** Bizim footer'ımız ürünü **"YKS Tercih Robotu 2026"** diye adlandırıyor (`src/components/site-footer.tsx:49`) [K]. Bu bir kategori tanımlaması olsa da, tescilli bir ibareyi kendi ürün adı gibi kullanmak gereksiz risk. `vizyon.md:22` zaten bu kategoriyi reddediyor — yani **markanın kendi kuralı da, tescil tablosu da aynı yönü gösteriyor: o satır değişmeli.** (Kendi 03 raporumun §1.5'inde de "addan büyük konum çelişkisi" demiştim.)
- **"tercih sihirbazı" başvurusu var (2023/021814, 41+42).** Bizim kodda `sihirbaz` iç adlandırma olarak yoğun kullanılıyor; kullanıcıya görünen metinlerde "Tercih Sihirbazı"nı **ürün adı gibi** kullanmadığımız sürece sorun yok [V]. Ayrıca YÖK Atlas'ın kendi ekranının adı da "Tercih Sihirbazı" — jenerikleşme kuvvetli.
## 1.4 "kolaytercih" adıyla başka ticari site var mı?
| Alan adı | DNS | Sonuç |
|---|---|---|
| `kolaytercih.com` | **var** | HTTP 200 — **bizim sitemiz** |
| `kolaytercih.com.tr` | **yok** | TRABİS WHOIS: `No match found` → **boşta** [W] |
| `kolaytercih.net` · `.org` · `.app` · `.ai` · `.co` · `kolay-tercih.com` | **yok** | Kullanımda değil |
Web araması da "kolaytercih" adıyla ikinci bir ticari site göstermedi; çıkan sonuçlar **farklı adlarla** çalışan rakipler: `tercihrobotu.com.tr`, `tercihrehberim.com`, `tercihyap.com.tr`, `universitetercihleri.com`, `unitercihrehberi.com`, `yerles.net`, `kariyer.net/tercih-motoru` [A]. **Karışma riski yok.**
**Kendi raporumun düzeltilmesi (03 §1.4):** orada "`.com.tr` Türkiye'de marka tescil belgesi/başvurusu ister [A]" yazmıştım. **Bu artık doğru değil** — TRABİS 14 Eylül 2022'de açıldığında `com.tr`, `net.tr`, `org.tr` **belgesiz, "ilk gelen alır"** tahsise geçti [W trabis.gov.tr/content/belgesizeGecis]. Yani `.com.tr` almak için tescil beklemeye gerek yok; tersine, **ad serbestken kapatılabilir**.
## 1.5 Hüküm
> **Görünür engel yok.** "KOLAYTERCİH" tek kelime hâlinde Türkiye'de tescilli değil; yakın tek kayıt (Vodafone, "kolay tercih") **sona ermiş** ve **41. sınıfı kapsamıyor**; adı kullanan ikinci bir ticari site yok; `.com.tr` boşta.
**Belirsiz kalan üç şey (başvurudan önce vekile sorulacak):**
1. **"Kolay" ayırt edicilik sorunu yaratır mı?** SMK m.5/1-(c) tanımlayıcı/övücü ibareleri reddeder. Tabloda sınıf 41/42'de **tek başına "KOLAY" tescili yok**; hep bileşik ("kolay tv", "kolay hayat", "n kolay", "kolaybi") [W]. Bizimki de bileşik, ama **"kolay tercih" hizmetin kendisini tarif ediyor** diye kısmî ret gelebilir — **doğrulanmalı**. Pratik azaltıcı: **logolu (şekil+kelime) başvuru**, düz kelime yerine.
2. **"easytercih" (2026/031206)** tescile giderse ne olur — itiraz gelir mi. Bugün cevabı yok.
3. **Hangi sınıflar alınacak.** 41 (eğitim/öğretim, çevrimiçi yayın) şart; 42 (yazılım/SaaS) şart; 9 ve 35 isteğe bağlı ve **her biri para**.
## 1.6 Başvuru nasıl yapılır (tek paragraf — Bilal karar versin, ben yapmıyorum)
Başvuru TÜRKPATENT'in **EPATS** sistemi üzerinden (e-Devlet girişiyle, vekilsiz de yapılabilir) çevrimiçi yapılır; gereken şey marka örneği (logolu başvuruda görsel), başvuru sahibi bilgisi (Bilal şahsen veya şirket adına — **hangisi olacağı `[BİLAL]` kararıdır**, sonradan devir ek işlem/masraf demektir) ve **Nice sınıf seçimi**dir; başka belge istenmez. Süre için pazarlama iddiası değil **gerçek bir emsal**: "tercihbot" markası 11.03.2025'te başvurdu, bülten itiraz penceresi 12.05.2025–12.08.2025 arasında açıldı ve **28.07.2025'te tescillendi** — yani itirazsız bir dosyada **~4,5–6 ay** [W TMview kaydı]. Ücretler resmî TÜRKPATENT tarifesinden ödenir, **KDV yoktur**; iki bağımsız üçüncü taraf kaynak 2026 için aynı rakamları veriyor: **tek sınıf başvuru 2.820 TL, ikinci sınıf +2.820 TL, üçüncü ve sonrası +3.150 TL, tescil belgesi düzenleme 7.010 TL** → **41+42 için toplam ≈ 12.650 TL** [W budak-ip.com; A asil.com.tr, etkinpatent.com]. **Bu rakamlar üçüncü taraf sitelerinden; TÜRKPATENT'in resmî ücret tarifesi sayfası bu vardiyada curl ile okunamadı (site SPA, tüm yollar 404 kabuğu döndürüyor) — ödemeden önce EPATS'ta teyit edilmeli, doğrulanmalı.**
---
# GÖREV 2 — A2: "KolayTercih Paketi" yeterli mi?
CEO kararı bağlayıcı ve tartışmaya açmıyorum: **ad sezon-bağımsız olacak, dal bu gece yazılacak, merge test ödemesinden sonra.** Aşağısı yalnız "hangi ad" sorusunun cevabı.
## 2.1 Önce iki ölçüt düzeltmesi (kanıtlı)
**(a) Banka ekstresinde paket adı GÖRÜNMEZ.** iyzico'da ekstre kaydı **"iyzico/üye iş yeri"** formatındadır; bazı bankalarda yalnız "iyzico" yazar [A iyzico yardım merkezi]. Yani sepet kalemi adının ekstreyle ilgisi yok — **geri ödeme/itiraz riskini azaltan şey adın kendisi değil, Bilal'in iyzico'daki üye iş yeri unvanının "KolayTercih" içermesidir** (A8/satıcı kimliği maddesiyle aynı kalem). **doğrulanmalı:** panelde görünen "ekstre adı" alanı ne yazıyor — bunu yalnız Bilal görebilir.
**(b) Paket adının gerçekten göründüğü yerler [K]:**
| Yüzey | Dosya:satır |
|---|---|
| iyzico ödeme formu — sepet kalemi | `src/lib/iyzico.ts:221` ← `src/features/odeme/odeme-actions.ts:74` |
| Ana sayfa fiyat kartı | `src/app/page.tsx:509` |
| `/paket` sayfa başlığı + meta açıklaması | `src/app/paket/page.tsx:11,13` |
| `/paket` OG görseli (sosyal paylaşım) | `src/app/paket/opengraph-image.tsx:7,14` |
| Koşullar sayfası (hukuki metin) | `src/app/kosullar/page.tsx:52` |
| **LLM sistem prompt'u** | `src/app/api/soru/route.ts:67` |
| Kredi yetmedi uyarıları | `liste-uretici.tsx:275`, `tercih-degisti-modali.tsx:329` |
| Satın alma kartı + ödeme sonucu | `paket-satinal.tsx:64`, `odeme-sonuc-karti.tsx:46,94` |
| Ürün/Offer JSON-LD `description` | `src/lib/seo.tsx:115` (sabitten okur) |
## 2.2 Değiştirme maliyeti — CEO'nun kabul kriteri sandığından pahalı
`grep -rn "Tercih Dönemi Paketi" src/` bugün **12 satır, 9 dosya** [K]. **Tek sözlük yok:** `URUNLER.paket.label` sabiti var ama onu okuyan yalnız 3 yer (`page.tsx:509`, `seo.tsx:115`, `odeme-actions.ts:74`); kalan **8 dosyada ad elle yazılmış**. Kabul kriteri "grep = 0" **9 dosyaya dokunmayı** gerektirir — CTO şartnamesinde böyle yazılmalı, yoksa yazılımcı `credits.ts:7`'yi değiştirip biter sanır.
**İki yan etki:**
- **LLM'e sızıyor.** `api/soru/route.ts:67` sistem prompt'unda ad geçiyor. CEO'nun T12 tetiği "prompt ya da model değişikliği yapılacak ilk gün eval seti" diyor. **Tavsiyem: bu isim değişimi T12'yi tetiklemesin** — davranış değil, özel isim değişimi. Aksi hâlde tek kelimelik düzeltme bütün bir eval işini içeri çeker. Bu, CEO'nun tek satırlık teyidini gerektirir.
- **Sezon kokusu adın dışında da var.** `src/app/page.tsx:136` SSS cevabı: *"Abonelik yok. **Tercih dönemi boyunca geçerli** tek seferlik 299 TL'lik paket alırsın…"* [K]. Bu cümle hem sezon-bağımlı hem de **paketin dönem sonunda bittiğini ima eden bir sınırlama** — `/kosullar`'da böyle bir süre sınırı yok. Ad değişirken bu cümle de değişmeli, yoksa A2'nin amacı yarım kalır.
## 2.3 "KolayTercih Paketi" değerlendirmesi
| Ölçüt | Sonuç |
|---|---|
| Sezondan bağımsız | ✅ Evet — A2'nin asıl derdi çözülüyor |
| Kısa | ✅ 2 kelime |
| Ne aldığını söylüyor mu | ❌ **Hayır.** "KolayTercih" zaten sitenin adı; yanına "Paketi" eklemek bilgi eklemiyor ("paket" tek başına boş) |
| iyzico sepetinde ne görünür | ❌ **"KolayTercih — KolayTercih Paketi"** — çünkü `odeme-actions.ts:74` etiketin başına markayı zaten ekliyor [K] |
**Hüküm: yeterli, ama en iyisi değil.** Kararın hedefini (sezon) tutturuyor; "ne aldığını söyle" ölçütünü kaçırıyor ve sepette markayı iki kez yazdırıyor. **Hangi ad seçilirse seçilsin `odeme-actions.ts:74` ele alınmalı:** ya önek kalkar, ya etiket markayı tekrarlamaz.
## 2.4 Alternatifler (3 tane) ve öneri
| # | Ad | iyzico sepetinde | Artı | Eksi |
|---|---|---|---|---|
| **1** | **Tercih Listesi Paketi** | KolayTercih — Tercih Listesi Paketi | Satın alınan şeyi adıyla söylüyor; yıl boyu doğru; 3 kelime | "Tercih" markada da var, hafif tekrar |
| 2 | Kişisel Liste Paketi | KolayTercih — Kişisel Liste Paketi | Tekrar yok; "kişisel" ürünün farkını taşıyor | "Liste" tek başına neyin listesi belirsiz |
| 3 | Tam Liste ve Danışman Paketi | KolayTercih — Tam Liste ve Danışman Paketi | İki bileşeni de sayıyor (24 satır + 60 kredi) | Uzun; "danışman" insan danışman beklentisi yaratabilir — vaat riski |
**Önerim: "Tercih Listesi Paketi"** — çünkü dört ölçütü birden karşılayan tek aday: sezondan bağımsız, kısa, sepette marka tekrarına düşmüyor ve kullanıcının parasını ne için verdiğini (24'lük tercih listesi) adın kendisi söylüyor.
**Yan fayda:** "Tercih Dönemi" ibaresi TÜRKPATENT'te **başkasının başvurusuna konu** (2020/119085, sınıf 38-41, durum Filed) [W]; adı bırakmak bu gereksiz komşuluğu da bitirir.
---
## CEO karar listesi
| # | Karar | Tavsiyem | Geri dönüş maliyeti |
|---|---|---|---|
| 1 | A9 hüküm: tescil başvurusunun önünde engel var mı? | **Yok.** Süreç `[BİLAL]`'e açılabilir | — (bu bir bulgu, karar değil) |
| 2 | A2 paket adı | **"Tercih Listesi Paketi"** ("KolayTercih Paketi" yerine) | Düşük ama tek dosya değil: 9 dosya. Merge zaten test ödemesinden sonra |
| 3 | `odeme-actions.ts:74`'teki `KolayTercih — ` öneki | Etiket markayı tekrar etmiyorsa **önek kalsın**; "KolayTercih Paketi" seçilirse **önek kaldırılsın** | Çok düşük, tek satır |
| 4 | Ad değişimi `api/soru/route.ts:67` prompt'una dokunuyor — T12 (eval seti) tetiklensin mi? | **Tetiklenmesin.** Davranış değişmiyor, özel isim değişiyor | Sıfır; tek satırlık teyit |
| 5 | `src/app/page.tsx:136` SSS'teki "Tercih dönemi boyunca geçerli" | **Aynı dalda düzelsin** — hem sezon kokuyor hem `/kosullar`'da olmayan bir süre sınırı ima ediyor | Düşük |
| 6 | Footer'daki "YKS Tercih Robotu 2026" (`site-footer.tsx:49`) | **Değişsin.** `vizyon.md:22` reddediyor; ayrıca "tercih robotu" ES EĞİTİM adına 2000/08210 ile tescilli | Düşük |
### Metin önerileri (önce → sonra)
- `src/lib/credits.ts:7` — **önce:** `label: "Tercih Dönemi Paketi"` → **sonra:** `label: "Tercih Listesi Paketi"` *(ve kalan 8 dosyadaki elle yazılmış geçişler aynı metne çekilir)*
- `src/app/page.tsx:136` — **önce:** "Abonelik yok. Tercih dönemi boyunca geçerli tek seferlik 299 TL'lik paket alırsın…" → **sonra:** "Abonelik yok. Tek seferlik 299 TL ödersin, paket hesabına tanımlı kalır…" *(süre sınırı iddiası kaldırılıyor — `/kosullar`'da böyle bir sınır yok)*
- `src/components/site-footer.tsx:49` — **önce:** "YKS Tercih Robotu 2026" → **sonra:** "YKS tercih listesi hazırlama aracı" *(kategori iddiası yerine ne yaptığımız; `[BİLAL]` değil, kategori tanımı CEO'da)*
---
## Bilal'den istenen (2 madde)
1. **Marka başvurusu kararı `[BİLAL]`:** başvuru sahibi **şahıs mı şirket mi**, sınıf **41+42** yeterli mi, ve **logolu mu düz kelime mi** — üç satırlık cevap; ardından EPATS'tan başvuru (~12.650 TL, doğrulanmalı). Engel yok, karar sende. **~10 dk (karar) + ~30 dk (başvuru)**
2. **`kolaytercih.com.tr` boşta ve artık belge istemiyor** — "ilk gelen alır"; savunma amaçlı kapatılması ucuz ve geri dönüşü olmayan riski kapatır. **~5 dk**

View File

@@ -0,0 +1,425 @@
# 28 — CTO şartnamesi: G1, G3, G2+G5
Hazırlayan: CTO ajanı · Taban commit: **`9bd448b`** (`main`, push edilmiş; `origin/main == main`).
Kaynak kararlar: `05-ceo-kararlari.md` §3, `24-ceo-kapanis.md` §A/§D, `04-sifir-odeme-teshisi.md` Ö1–Ö5, `00-kurucu-brief.md` ("sade ve basit, over-engineering yok").
Yöntem: **yalnız okuma**. Kod değiştirilmedi, commit atılmadı, `pnpm install`/`build`/`typegen`/`tsc`/`lint` **koşulmadı** (disk kısıtı — orkestratör talimatı). `git status` bu raporun yazımı dışında değişmedi.
İşaret: **[D]** bu gece açıp satırını doğruladığım kod · **[Ç]** koddan çıkarım (çalıştırılmadı).
---
## Özet (5 madde)
1. **CEO'nun satır numaralarının çoğu tuttu, ikisi tutmadı.** `rapor-actions.ts` bu gece `9bd448b` ile değişti: liste harcaması artık `98-99/118-124` değil **`153-158`**, iade **`212-217`**, revizyon harcaması **`285-290`**, revizyon iadesi **`339-344`**. Ayrıca `giris-karti.tsx` `src/features/auth/` altında **değil**, `src/features/kullanici/components/giris-karti.tsx`. Aşağıdaki tüm atıflar `9bd448b` üzerinde tek tek açılarak yazıldı. [D]
2. **G3'ün gizli dördüncü satırı var.** `spendCredits`/`grantCredits` koşullansa bile `rapor-actions.ts:243` ve `:363`'teki `kredi: user.creditBalance - RAPOR_KREDI` paketliye **düşmemiş krediyi düşmüş gibi gösterir**; ayrıca `tercih-degisti-modali.tsx` paketliye "Listemi güncelle — 3 kredi" yazmaya devam eder. Tek bir `maliyet` değişkeni dört yeri birden kapatıyor — kapsam bu kadar büyütülmeli, daha fazlası değil. [D]
3. **G1'in CTA'sı için `?kaynak=` allowlist'i şart.** `/listem?uret=1&kaynak=tadimlik` yazmadan önce `uretim-basladi-olayi.tsx:25-41`'deki `IZINLI_KAYNAKLAR`'a `"tadimlik"` eklenmezse değer `"bilinmiyor"`a düşer ve bu değişikliğin ölçümü kaybolur. Dosyanın kendi notu bunu zaten emrediyor. [D]
4. **İki sessiz build tuzağı var ve ikisi de G1'in metin işinde patlar:** `rapor-maske.ts` `import "server-only"` (satır 6), `credits.ts` `appdb`'yi import ediyor (satır 2) — **ikisi de `"use client"` olan `tadimlik-satiri.tsx`'e import EDİLEMEZ**. Yeni CTA cümlesi `ACIK_SATIR`/`DENEME_KREDISI` sabitlerine uzanamaz; sayı gerekiyorsa cümle sayısız yazılır. [D]
5. **`/meraklisina` şeması üç pakette de değişmiyor.** `huni-semasi.tsx`'teki `SEMA` yalnızca sihirbaz adımları, aday havuzu, 24'lük iskelet, filtre gevşetme ve havuz-dışı kuralını belgeliyor (satır 11-41). G1 sayfa sırası + CTA hedefi, G3 kredi muhasebesi, G5 metin değiştiriyor — hiçbiri bu beş şeyden biri değil. **Yazılımcı `huni-semasi.tsx`'e dokunmayacak.** [D]
---
## Dosya sahipliği tablosu
Paketler **teker teker** koşacak (disk), yine de kümeler ayrık tutuldu — dal sırası bozulsa bile çakışma olmaz.
| Dosya | G1 `funnel/sonuc-ilk-ekran` | G3 `odeme/paket-vaadi` | G2+G5 `odeme/kasa-ve-metin` |
|---|:--:|:--:|:--:|
| `src/app/sonuc/page.tsx` | ✅ | | |
| `src/features/liste/components/manuel-harita.tsx` | ✅ | | |
| `src/features/rapor/components/tadimlik-satiri.tsx` | ✅ | | |
| `src/features/sihirbaz/sihirbaz-sabitler.ts` | ✅ | | |
| `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx` | ✅ | | |
| `src/features/rapor/components/uretim-basladi-olayi.tsx` | ✅ | | |
| `src/features/rapor/rapor-actions.ts` | | ✅ | |
| `src/features/rapor/components/listem-icerik.tsx` | | ✅ | |
| `src/features/rapor/components/tercih-degisti-modali.tsx` | | ✅ | |
| `src/features/odeme/odeme-actions.ts` | | | ✅ |
| `src/features/odeme/components/satin-al-form.tsx` | | | ✅ |
| `src/features/odeme/components/paket-satinal.tsx` | | | ✅ |
| `src/features/kullanici/components/giris-karti.tsx` | | | ✅ |
| `src/lib/analitik.ts` | | | ✅ |
**Hiçbir pakette yok (yasak listesi):** `src/features/rapor/components/liste-uretici.tsx` (Bilal'in dosyası — `9bd448b` ile commit'li ama gece kuralı gereği dokunulmaz), `docs/ekip/BACKLOG.md`, `docs/ekip/KARARLAR.md`, `AGENTS.md`, `content/rehber/**`, `data/**`, `src/features/pazarlama/components/huni-semasi.tsx`, `src/lib/credits.ts`.
### Çakışma kararları
1. **`src/lib/analitik.ts` → G2'nin.** G1'in `tadimlik_goruntulendi` olayında bir **seri kırılması** yaratacağı doğru (olay bugün ~2.200 px aşağıdaydı, yarın ilk ekranda olacak; 30 günlük değer 0 → `01-analitik-bulgular`), ve bu repoda seri kırılmasını `analitik.ts`'in `OlayAdi` yorumuna yazma geleneği var (`program_eklendi`, satır 29-31). Buna rağmen G1 bu dosyaya **dokunmaz**: G2 aynı birliğe `odeme_hata` ekliyor, iki dal bitişik satırlarda çakışır. G1 seri kırılmasını (a) `tadimlik-satiri.tsx:100-102`'deki `useGorunumOlayi` çağrısının üstündeki yoruma, (b) commit mesajına yazar. Kalıcı notun `analitik.ts`'e taşınması backlog önerisi #B1.
2. **`paket-satinal.tsx` ve `tercih-degisti-modali.tsx` → G5/G3'ün, A2'nin değil.** CEO'nun A2 paketi (`odeme/paket-adi`, "Tercih Dönemi Paketi" → "KolayTercih Paketi") bu iki dosyaya da girmek zorunda: ad **8 dosyada** geçiyor ve ikisi bu dalların içinde (`paket-satinal.tsx:64`, `tercih-degisti-modali.tsx:329`) [D]. A2 CEO'nun sırasında **10.** ve kesme sırasının başında; bu yüzden A2 en sonda koşar, G1/G3/G5 dalları yazıldıktan **sonra** taban alır. G1/G3/G5'teki hiçbir yazılımcı paket adına dokunmaz.
3. **`liste-uretici.tsx` kimsenin değil.** G3 uygulandığında o dosyadaki `hasPaket` dalı ("+30 kredi yükle") liste üretimi için **ölü koda** dönüşür (paketli artık hiç `KREDI` kodu alamaz, bkz. G3 adım 1). Bu doğru ama zararsız bir tutarsızlıktır; dosya Bilal'e ait olduğu için **düzeltilmez**, backlog önerisi #B2 olarak kaydedilir.
---
## Tüm yazılımcılar için ortak kurallar
1. Yalnız orkestratörün verdiği **worktree + dalda** lokal commit. Push yok, merge yok, `main`'e commit yok.
2. **`git add -A` / `git add .` yasak.** Yalnız kendi dosya kümenden, yol vererek ekle. Commit öncesi `git status --porcelain` çıktısında kümen dışında bir şey görünüyorsa dur ve raporla.
3. **Doğrulama sırası:** `pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint`. Dev sunucusu yok, tarayıcı yok, `pnpm build` **yok** (disk ~5 GB; tam build'i Bilal sabah C3 komut bloğunda tek seferde alır).
4. **Taze worktree'de `next typegen` olmadan `tsc` baseline'da kırıktır** — `PageProps` gibi global tipler `.next/types`'tan gelir. Kırmızı çıktıyı kendi değişikliğine yorma; önce typegen koş.
5. **Worktree'de `node_modules` symlink'i Turbopack'te patlar** — klon kullanılır (`cp -Rc ../kolaytercih/node_modules node_modules`). Kurulumu orkestratör yapar; `pnpm install` çalıştırma.
6. `next build` env'siz koşar: modül yüklenirken env zorunlu kılan kod yazma. Bu üç pakette yeni env yok.
7. **Next'e özgü bir API'ye dokunmadan önce ilgili dokümanı oku** (her paketin altında yolu yazılı). Eğitim verisindeki Next bu sürüm değil.
8. AGENTS.md: rozet gerekiyorsa `SectionEyebrow`, CTA'da ikon **metnin sonunda** `<ArrowRight className="size-4" aria-hidden />`, `Sparkles` yok; modal kapatma çarpısı `DialogContent` varsayılanı. Sihirbaz/liste **mimarisi** değişirse `/meraklisina` şeması aynı commit'te — bu üç pakette **değişmiyor** (bkz. Özet #5), dokunma.
9. Uydurma sayı yok: ekranda görünen her rakam ya tek kaynak sabitten (`URUNLER`, `RAPOR_KREDI`, `ACIK_SATIR`) gelir ya da hiç yazılmaz.
10. Rapor: `docs/gece-vardiyasi/2026-09-22/` altına, orkestratörün verdiği numarayla; kabul kriterlerinin her birinin çıktısını yapıştır.
---
# G1 · `funnel/sonuc-ilk-ekran`
**Amaç:** Ödeme öncesi tek gerçek önizleme (tadımlık) `/sonuc`'un ilk ekranında görünsün ve kullanıcıyı giriş sonrası listenin üretildiği yere göndersin.
**Dal:** `funnel/sonuc-ilk-ekran` · **Taban:** `9bd448b` · **Öncelik: 1 (kesilmez).**
### Dokunulacak dosyalar (tam liste)
| Dosya | Satır | Ne |
|---|---|---|
| `src/features/liste/components/manuel-harita.tsx` | 67-80 | Boş placeholder yerine `null` |
| `src/app/sonuc/page.tsx` | 100-118 | Tadımlık tablodan önce + yorum düzeltmesi |
| `src/features/sihirbaz/sihirbaz-sabitler.ts` | ~165 (`sonucHref` yanı) | `listemUretHref` export edilir (yeni fonksiyon, taşınma) |
| `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx` | 20-26, 195, 231, 260 | Yerel `listemUretHref` silinir, import edilir |
| `src/features/rapor/components/uretim-basladi-olayi.tsx` | 25-41 | `IZINLI_KAYNAKLAR`'a `"tadimlik"` |
| `src/features/rapor/components/tadimlik-satiri.tsx` | 28, 100-102, 111, 114, 186 | CTA hedefi, seri-kırılması yorumu, `first:mt-0`, yanlış iddia |
### Kapsam dışı (yazılımcı taşmasın)
- Maskenin kaç satır açtığı (`ACIK_SATIR = 3`) — **değişmiyor** (24-ceo-kapanis R5).
- `/sonuc` tablosunun sıralaması, filtreleri, `<h1>` eksikliği (A3 ayrı dal), Suspense fallback'inin iskeleti (`sonuc/page.tsx:45-54`) — fallback bugün de haritayı temsil etmiyor (pill + başlık + `h-36` + tablo satırları = `ProgramTablosu`'nun başlığı), boş harita kalkınca yanlışlığı **artmıyor**. [Ç]
- Tadımlığın başka yüzeylere (`/`, `/paket`) taşınması.
- Profil çerezi olmayan ziyaretçiye özel CTA dalı yazmak — **bilerek yapılmayacak**, gerekçesi aşağıda (Riskler #2).
- `huni-semasi.tsx`, `analitik.ts`, `liste-uretici.tsx`.
### Adım adım
**1) Boş harita ilk ekranı işgal etmesin** — `manuel-harita.tsx:67-80`
`if (liste.length === 0) return null;` Yorum da düzeltilir: bugünkü not "197 KB'lık il geometrisi inmesin diye placeholder alanı rezerve eder" diyor; yeni not, boş durumda hiç yer tutulmadığını ve ilk eklemede haritanın belireceğini söylesin. `TercihHaritasiLazy` zaten `dynamic` — ölçü davranışı değişmez. [D]
**2) Tadımlık tablodan önce** — `sonuc/page.tsx:103-118`
Yeni sıra: `<ManuelHarita />` → `<TadimlikBolumu … />` → `<SonucProgramTablosu … />` → `<SonucSihirbazi … />` → dipnot. Satır 100-102'deki "Sayfa hiyerarşisi: önce Türkiye haritası, sonra liste" yorumu yeni sıraya göre yeniden yazılır (neden: tadımlık ödeme öncesi tek gerçek önizleme, ilk ekranda durur; harita yalnız manuel liste doluyken görünür). Props değişmez, bileşenlerin içine dokunulmaz.
**3) Tadımlık ilk eleman olduğunda tepede boşluk bırakmasın** — `tadimlik-satiri.tsx:114`
`className="mt-16 min-w-0"` → `className="mt-16 min-w-0 first:mt-0"`. Gerekçe: `ManuelHarita` `null` döndüğünde bu `<section>` `main`'in **gerçek ilk DOM çocuğu** olur (JSX yorumları DOM düğümü üretmez), `:first-child` eşleşir ve `main`'in `py-12`'si tek başına yeterli üst boşluğu verir; harita görünürken `mt-16` aynen çalışır. Tek utility, koşullu prop yok. [Ç]
**4) `listemUretHref` tek kaynağa** — `sihirbaz-sabitler.ts` + `sihirbaz-cagri-karti.tsx`
`sihirbaz-cagri-karti.tsx:25-27`'deki yerel fonksiyon `sihirbaz-sabitler.ts`'e (`sonucHref`'in hemen altına) taşınır ve export edilir; üstündeki "`uret=1` HER ZAMAN ilk parametre kalmalı — `giris-karti.tsx` funnel metnini `startsWith("/listem?uret=1")` ile seçiyor" yorumu da birlikte taşınır. Çağrı yerleri (`:195`, `:231`, `:260`) import'a çevrilir, davranış birebir aynı kalır.
*Neden tek satırlık kopyala-yapıştır değil:* bu sözleşmenin kopyası bugün **üç** dosyada yorum olarak yaşıyor (`listem-icerik.tsx:48-50`, `sihirbaz-cagri-karti.tsx:22-24`, `giris-karti.tsx:28-31`) [D]; dördüncü bir literal kopya, funnel metnini sessizce kaybettiren bir hata sınıfı açar. Taşıma 2 satır, riski sıfır.
**5) Ölçüm yüzeyi allowlist'e** — `uretim-basladi-olayi.tsx:25-41`
`IZINLI_KAYNAKLAR`'a `"tadimlik"` eklenir + tek satır yorum ("/sonuc'taki girişsiz tadımlık CTA'sı"). Dosyanın kendi kuralı: "Yeni bir üretim yüzeyi eklerken değerini önce buraya ekle, sonra href'e koy."
**6) CTA doğru yere gitsin** — `tadimlik-satiri.tsx:111`
`const girisUrl = \`/giris?callback=${encodeURIComponent(listemUretHref("tadimlik"))}\`;`
Import satırı 28 düzeltilir: `sonucHref` **kaldırılır** (başka kullanımı yok → `no-unused-vars` lint hatası verir), `listemUretHref` eklenir; `PROFIL_DEGISTI_EVENT` kalır. `onClick`'teki `olay("giris_cta_tiklandi", { kaynak: "tadimlik" })` **aynen kalır** (mevcut seri korunur).
Doğrulanmış zincir: `/giris` callback'i `/^\/(?![/\\])/` kalkanından geçer (`giris-karti.tsx:18-19`) ✅ · `startsWith("/listem?uret=1")` funnel metni korunur ✅ · dönüşte `listem/page.tsx:29-31` → `ListemIcerik uret` → `ListeUretici` üretimi kendiliğinden başlatır (`liste-uretici.tsx:243-256`) ✅. [D]
**7) Seri kırılması yorumu** — `tadimlik-satiri.tsx:100-102`
`useGorunumOlayi("tadimlik_goruntulendi", …)` çağrısının üstüne 2-3 satır: olayın bu değişiklikten önce sayfanın ~2.200 px altında yaşadığı, sonrasında ilk ekranda olduğu, iki dönemin karşılaştırılamayacağı. (`analitik.ts`'e **yazılmaz** — çakışma kararı #1.)
**8) Teslim edilmeyen iddia kalkar** — `tadimlik-satiri.tsx:186`
`24 satırın tamamı için giriş yap — 5 deneme kredin hazır` → **`Giriş yap ve listeni oluştur`** (+ mevcut `<ArrowRight className="size-4" aria-hidden />` aynen kalır — AGENTS.md CTA deseni).
Gerekçe: maske paketsize 24 satırın **3'ünün** analizini açıyor (`rapor-maske.ts:12, 28-46`); "tamamı" teslim edilmiyor. Bu commit **yeni vaat eklemez**, yalnız yanlış olanı kaldırır. Üstteki `<p>`'deki "Bu, 24 satırlık Yapay Zeka listenden yalnızca bir örnek." cümlesi **doğrudur ve kalır** (üretilen liste gerçekten 24 satır).
**9) `[Bilal]` commit'i — CTA'nın yeni vaadi** (ayrı, en son commit)
Önerilen: buton `Kendi listemi oluştur`, alt satır (`:174-176`) `Kredi kartı gerekmez · Google ya da e-posta ile 30 saniyede · Giriş sonrası liste hemen üretilir`.
**Kısıt:** bu dosya `"use client"`. `ACIK_SATIR` (`rapor-maske.ts`, `import "server-only"` satır 6) ve `DENEME_KREDISI`/`RAPOR_KREDI` (`credits.ts`, satır 2'de `./appdb` import ediyor) **import edilemez** — build'i kırar. Sayı gerekiyorsa cümle sayısız yazılır; elle "3"/"5" yazmak yasak (tek kaynak kuralı). Commit en sona konur ki Bilal `git reset --hard HEAD~1` ile tek hamlede düşürebilsin.
### Kabul kriterleri (tarayıcısız, komutla)
```sh
# 1) Tadımlık tablodan önce (ilk sayı küçük olmalı)
grep -n "<TadimlikBolumu\|<SonucProgramTablosu$" src/app/sonuc/page.tsx
# 2) Boş harita hiç render edilmiyor
grep -n "liste.length === 0" src/features/liste/components/manuel-harita.tsx # 1 sonuç
grep -c "haritada belirir" src/features/liste/components/manuel-harita.tsx # 0
grep -c "haritada belirir" -r src/ # 0
# 3) CTA doğru hedefe gidiyor, eski hedef kalmadı
grep -n "listemUretHref" src/features/rapor/components/tadimlik-satiri.tsx # 1
grep -c "sonucHref" src/features/rapor/components/tadimlik-satiri.tsx # 0
grep -n "export function listemUretHref" src/features/sihirbaz/sihirbaz-sabitler.ts # 1
grep -c "function listemUretHref" src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx # 0
# 4) Ölçüm yüzeyi allowlist'te
grep -n '"tadimlik"' src/features/rapor/components/uretim-basladi-olayi.tsx # 1
# 5) Teslim edilmeyen iddia yok
grep -rc "24 satırın tamamı" src/ # 0
# 6) Şema ve yasak dosyalar el değmemiş
git diff --name-only HEAD~N | grep -E "huni-semasi|analitik.ts|liste-uretici|credits.ts" # boş
# 7) Tipler ve lint
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
```
Ek el kontrolü (dosya:satır okuyarak): `TadimlikBolumu` girişli kullanıcıda ve havuz boşken **hâlâ `null` dönüyor** (`tadimlik-bolumu.tsx:18-21` değişmedi) · `ManuelHarita` liste doluyken haritayı aynen render ediyor.
### Riskler ve tuzaklar
1. **`sonucHref` import'unu silmeyi unutmak** → lint kırmızısı. (Adım 6.)
2. **Profil çerezi olmayan ziyaretçi.** `/listem?uret=1`, seçim yoksa "profil-yok" → boş durum + sihirbaz CTA'sı gösterir (`liste-uretici.tsx:243-251`); **kredi harcanmaz, hata ekranı çıkmaz** [D]. Bu durum yalnızca eski `?sira=` linkiyle gelen ziyaretçide oluşabilir, çünkü geçerli bir profil `tercihProfiliDogrula` gereği **en az 1 ilgi alanı içermek zorundadır** (`sihirbaz-sabitler.ts:90, 143-145`) [D]. Bu yüzden CTA'ya koşullu ikinci bir dal **yazılmayacak** — kurucunun "over-engineering yok" kısıtı.
3. **Giriş dönüşünde onaysız 3 kredi.** `giris-linki.tsx:13-16` navbar butonu için bunu bilerek yasaklıyor; burada sorun değil çünkü kullanıcı "listemi oluştur" diyen bir CTA'ya **açıkça tıklıyor** ve bu, `hazir_cta` (`sihirbaz-cagri-karti.tsx:260`) ile birebir aynı, onaylı desen. [D] CTA metni bu yüzden üretimi söylemeli (adım 8-9).
4. **Layout kayması:** boş harita `null` iken ilk "+" tıklamasında harita belirir ve tablo aşağı iner. Bugün de placeholder→harita geçişi var; kaybı kabul edilen bilinçli takas (CEO §3 G1-b).
5. `tadimlik_goruntulendi` sayısı bir gecede 0'dan yüksek bir sayıya fırlayacak — **kırık ölçüm değil, kazanılan payda**. Adım 7 bunu koda yazar.
### Commit planı
1. `fix(sonuc): boş harita ilk ekranı işgal etmez` — `manuel-harita.tsx`
2. `fix(sonuc): tadımlık tablonun üstüne alınır` — `sonuc/page.tsx`, `tadimlik-satiri.tsx` (`first:mt-0`)
3. `refactor(sihirbaz): listemUretHref tek kaynağa taşınır` — `sihirbaz-sabitler.ts`, `sihirbaz-cagri-karti.tsx`
4. `fix(tadimlik): CTA girişten dönüşte üretimi başlatır` — `tadimlik-satiri.tsx`, `uretim-basladi-olayi.tsx`
5. `content(tadimlik): teslim edilmeyen "24 satırın tamamı" iddiası kalkar` — `tadimlik-satiri.tsx`
6. `[Bilal] content(tadimlik): CTA'nın yeni vaadi` — `tadimlik-satiri.tsx` *(en son, tek başına düşürülebilir)*
### Okunacak Next dokümanı (kod yazmadan önce)
- `node_modules/next/dist/docs/01-app/01-getting-started/05-server-and-client-components.md` — client sınırı ve `server-only` (Adım 9'un tuzağı).
- `node_modules/next/dist/docs/01-app/01-getting-started/04-linking-and-navigating.md` — `<Link href>` ve sorgu parametresi.
---
# G3 · `odeme/paket-vaadi`
**Amaç:** Paket sayfasındaki söz kodla eşitlensin — paketli kullanıcıdan liste ve revizyon için kredi düşmesin, "60 danışman sorusu" gerçekten 60 olsun.
**Dal:** `odeme/paket-vaadi` · **Taban:** `9bd448b` · **Öncelik: 2 (kesilmez).** · **Merge öncesi `guvenlik-uyum` denetimi zorunlu.**
### Dokunulacak dosyalar
| Dosya | Satır | Ne |
|---|---|---|
| `src/features/rapor/rapor-actions.ts` | 152-158, 212-217, 243, 285-290, 339-344, 363 | `maliyet` değişkeni; 4 harcama/iade + 2 bakiye satırı |
| `src/features/rapor/components/listem-icerik.tsx` | 167 | `raporKredi` prop'u paketliye 0 iner |
| `src/features/rapor/components/tercih-degisti-modali.tsx` | 129, 188, 250, 275 | 0 bedelde "kredi" dili yerine "pakete dâhil" |
### KRİTİK KISIT (CEO kararı, tartışmaya kapalı)
`spendCredits` ve `grantCredits` çağrıları **KALDIRILMAZ**, yalnız **tutarları koşullanır**. Gerekçe koddan doğrulandı:
- `credit_ledger` üzerinde `uniqueIndex("ledger_reason_ref").on(reason, refId)` var (`src/lib/appdb/schema.ts:133`) [D]. Üretimin tek idempotency çapası bu. Çağrı kaldırılırsa aynı `requestId` ile ikinci üretim `DUPLICATE` dönmez → BACKLOG #1'deki çifte üretim kapısı yeniden açılır.
- `amount: 0` ile `spendCredits` **INSUFFICIENT dönmez**: `gte(creditBalance, 0)` her zaman eşleşir ve `updatedAt` değiştiği için `rowsAffected = 1` olur (`credits.ts:65-74`) [Ç — SQLite `rowsAffected` semantiği; QA'nın DB duman testiyle teyit edilmeli].
- İade dalındaki `grantCredits(delta: 0, reason: "refund")` satırı **silinmemeli**: `rapor-actions.ts:171-184` ve `:303-316` "önceki deneme başarısız mıydı" sorusunu tam olarak bu `refund` satırının varlığıyla cevaplıyor. Satır yazılmazsa paketlinin başarısız denemesi `SURUYOR` ("Listen zaten hazırlanıyor") gibi görünür — yanlış mesaj. [D]
- `delta`'yı koşullamazsak paketliye her başarısız üretimde **bedava 3 kredi** yazılır. (CEO'nun uyardığı sızıntı.)
### Kapsam dışı
- Fiyat (299 TL), kredi adedi (60/30), top-up kuralları, maske (`ACIK_SATIR`) — hepsi R5 ile kapalı.
- Sohbet kredisi (`spendCreditForMessage`, mesaj başına 1) — **doğru davranış, dokunulmaz**; G3'ün tüm amacı bu 60 sorunun gerçekten 60 kalması.
- `credits.ts`, `liste-uretici.tsx`, paket adı (A2), `kredi-hatirlatma.ts`.
- `/paket`, `/` ve `listem-govde.tsx`'teki "60 danışman sorusu" metinleri: **üçü de `URUNLER.paket.credits`'ten türüyor** (`app/page.tsx:201`, `paket-satinal.tsx:40`, `listem-govde.tsx:345`) [D] — G3 sonrası hiçbir metin değişikliği gerektirmeden doğru hâle gelirler. Dokunma.
### Adım adım
**1) `listeOlustur` yolu** — `rapor-actions.ts:152` civarı (fonksiyon: `listeOlusturKilitli`)
`spendCredits` çağrısının hemen üstüne:
```ts
// Paket vaadi (docs/urun/vizyon.md): liste ve revizyon pakete dâhil; krediler
// yalnız danışman sorusu için. Çağrı BİLEREK duruyor — ledger'daki
// UNIQUE(reason, ref_id) (appdb/schema.ts:133) üretimin tek idempotency
// çapası; paketliye delta 0 satır yazılır, aynı requestId ikinci kez
// DUPLICATE döner.
const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;
```
Kullanım yerleri:
- `:155` `amount: RAPOR_KREDI` → `amount: maliyet`
- `:165` hata metni `${RAPOR_KREDI} kredi gerekli` → **değişmez** (bu dal yalnız `maliyet > 0` iken erişilebilir).
- `:214` `delta: RAPOR_KREDI` → `delta: maliyet`
- `:243` `kredi: user.creditBalance - RAPOR_KREDI` → `kredi: user.creditBalance - maliyet`
**2) `listeRevize` yolu** — `rapor-actions.ts:285` civarı
Aynı `maliyet` satırı (`user.hasPaket ? 0 : RAPOR_KREDI`) `spendCredits`'ten önce tanımlanır; `:287 amount`, `:341 delta`, `:363 kredi` aynı şekilde bağlanır. Not olarak yazılır: `:256`'daki `if (!user.hasPaket) return PAKET` guard'ı yüzünden burada `maliyet` **her zaman 0**'dır; ifade guard değişirse davranışın bozulmaması için koşullu bırakılıyor.
**3) Sunucu davranışı dışına taşma yasak.** `krediBittiIsaretle`, `uretimKilidiAl/Birak`, `reports` yazımı, maskeleme dalları (`user.hasPaket ? sonuc : raporMaskele(sonuc)`) **aynen kalır**.
**4) Arayüz aynı şeyi söylesin** — `listem-icerik.tsx:167` + `tercih-degisti-modali.tsx`
`raporKredi={RAPOR_KREDI}` → `raporKredi={user.hasPaket ? 0 : RAPOR_KREDI}`.
Modalda tek türetilmiş bayrak: `const ucretsiz = raporKredi === 0;` ve üç metin yeri:
- `:188` "…geçer ve {raporKredi} kredi düşer." → ücretsizse "…geçer; güncelleme paketine dâhil, kredi düşmez."
- `:250` "Güncelleme {raporKredi} kredi; bakiyen {kredi} kredi." → ücretsizse bu satır **gösterilmez**.
- `:275` buton "Listemi güncelle — {raporKredi} kredi" → ücretsizse "Listemi güncelle" (ok ikonu deseni aynen).
`:129 krediYeter` ve `KrediYetersiz` dalına dokunulmaz: `kredi >= 0` her zaman doğru olduğu için o dal paketliye zaten hiç render edilmez. [Ç]
*Neden bu adım zorunlu:* aksi hâlde kullanıcıya "3 kredi düşer" denip düşülmez — yalanın yönü değişir, kalitesi değişmez.
### Kabul kriterleri
```sh
# 1) Çağrılar duruyor (idempotency çapası sağlam)
grep -c "spendCredits(" src/features/rapor/rapor-actions.ts # 2
grep -c "grantCredits(" src/features/rapor/rapor-actions.ts # 2
# 2) Tutarlar koşullu; sabit tutar hiçbir harcama/iade satırında kalmadı
grep -c "hasPaket ? 0 : RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 2
grep -n "amount: maliyet\|delta: maliyet" src/features/rapor/rapor-actions.ts # 4 satır
grep -c "delta: RAPOR_KREDI\|amount: RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 0
grep -c "creditBalance - RAPOR_KREDI" src/features/rapor/rapor-actions.ts # 0
# 3) requestId/refId zinciri değişmedi
grep -n "refId: requestId\|refId: input.requestId" src/features/rapor/rapor-actions.ts # 4 satır
# 4) Arayüz aynı şeyi söylüyor
grep -n "raporKredi={" src/features/rapor/components/listem-icerik.tsx # hasPaket ? 0 : RAPOR_KREDI
grep -c "ucretsiz" src/features/rapor/components/tercih-degisti-modali.tsx # >=3
# 5) Paket vaadi metinleri tek kaynaktan (hardcoded 60 yok)
grep -rn "danışman sorusu" src/ # 3 sonuç, üçü de credits/paketKredi interpolasyonu
# 6) Kapsam dışı dosyalar el değmemiş
git diff --name-only HEAD~2 # yalnız 3 dosya; credits.ts / liste-uretici.tsx YOK
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
```
**QA'ya devredilen davranış kriterleri (statik grep ile kanıtlanamaz, oturum ister):** paketlide liste ve revizyon bakiyeyi düşürmez · `credit_ledger`'da `delta = 0` satır yazılır · aynı `requestId` ile ikinci üretim `DUPLICATE`/`SURUYOR` döner · üretim hatasında paketliye kredi **eklenmez** · paketsizde davranış bit-bit aynı.
### Riskler ve tuzaklar
1. **`user.hasPaket` 0/1 olabilir** (drizzle/SQLite boolean); `? :` her iki temsille de doğru çalışır — `=== true` **yazma**.
2. **Revizyon dalında `maliyet` daima 0** — bu bir hata değil, paket vaadinin ta kendisi (`MAX_REVIZYON = 2` hak sayacı sınırı korur, `:274-280`).
3. **Delta-0 ledger satırı ve iyzico mutabakatı:** `credit_ledger` bir muhasebe defteri değil, kredi hareket kaydıdır; iyzico tarafı `orders` + `grantCredits(reason: "purchase")` üzerinden yürüyor (`krediKaydiVarMi`, `credits.ts:202-212`). Delta-0 satırının mutabakata etkisi **olmaması gerekir** ama bu benim çıkarımım [Ç] — **`guvenlik-uyum` merge öncesi açıkça cevaplasın** (aşağıda soru metni).
4. `kredi-hatirlatma.ts:36` paketliyi de tarayabilir (sohbet kredisi 3'ün altına inerse); e-posta metni "listenin tamamını açmak istersen" diyor (`eposta.ts:188`) — paketliye yanlış. **G3'ten önce de var olan bir hata**, kapsam dışı, backlog #B3.
### Commit planı
1. `fix(kredi): paketliden liste ve revizyon kredisi düşmez` — `rapor-actions.ts`
2. `fix(listem): fark modalı paketliye kredi bedeli göstermez` — `listem-icerik.tsx`, `tercih-degisti-modali.tsx`
`[Bilal]` commit'i **yok** — paket içeriği kararı CEO'da verildi (24-ceo-kapanis §B).
### Okunacak Next dokümanı
- `node_modules/next/dist/docs/01-app/01-getting-started/07-mutating-data.md` — Server Action sözleşmesi (dönüş tipi, `"use server"`).
- `node_modules/next/dist/docs/01-app/02-guides/data-security.md` — server/client sınırında veri ve `server-only`.
---
# G2 + G5 · `odeme/kasa-ve-metin`
**Amaç:** Ödeme yüzeyinde iki delik kapanır — hatanın ölçüsü yok (G2) ve satın alma niyetiyle gelen kişiye "sonra al" deniyor (G5).
**Dal:** `odeme/kasa-ve-metin` · **Taban:** `9bd448b` · **Öncelik: 3 (vakit yetmezse ilk kesilecek paket budur).** · **Merge öncesi `guvenlik-uyum` denetimi (para yüzeyi).**
CEO'nun birleştirme gerekçesi: ikisi de aynı yüzeyin küçük düzeltmesi, ayrı dal maliyeti faydasından büyük (24-ceo-kapanis §D-9).
### Dokunulacak dosyalar
| Dosya | Satır | Ne |
|---|---|---|
| `src/lib/analitik.ts` | 36 civarı (`OlayAdi`) | `odeme_hata` adı |
| `src/features/odeme/odeme-actions.ts` | 16, 35, 45, 48, 87, 91, 102, 108 | Hata dönüşlerine `kod` alanı |
| `src/features/odeme/components/satin-al-form.tsx` | 48-55 | İki hata dalında `olay("odeme_hata", { kod })` |
| `src/features/odeme/components/paket-satinal.tsx` | 140-144 | "Paketi sonra alırsın." kalkar |
| `src/features/kullanici/components/giris-karti.tsx` | 28-31, 52-66 | `/paket` callback'i için üçüncü metin dalı |
### Kapsam dışı
- **Birincil CTA metni ve hedefi** (`paket-satinal.tsx:131-139`) — 21 Eylül kararı, R4 ile kalıcı kapalı. Buton metnine, rengine, hedefine **dokunulmaz**.
- Fiyatın girişsiz dala eklenmesi (ürün Ö2a) — R4.
- `odeme_tamamlandi` sunucu olayı, yeni sayfa görüntüleme enstrümanı, `/odeme` ve `/odeme/sonuc` yüzeyleri, iyzico entegrasyonu, `GirisBaslik`'in typewriter mesajları, paket adı (A2).
### Adım adım — G2 (ölçüm)
**1) Olay adı** — `analitik.ts` `OlayAdi` birliğine `| "odeme_hata"` (`odeme_baslatildi`'nın hemen altına) + 2 satır yorum: ne zaman atıldığı ve `kod` özelliğinin allowlist'li olduğu.
**2) Hata kodu sunucudan gelsin** — `odeme-actions.ts`
`OdemeBaslatDurum`'un hata dalı kod taşısın:
```ts
export type OdemeHataKodu = "URUN" | "ZATEN_PAKETLI" | "TOPUP_PAKETSIZ" | "SUNUCU";
export type OdemeBaslatDurum = { error: string; kod: OdemeHataKodu } | { yonlendir: string };
```
Eşleme: `:35` → `"URUN"` · `:45` → `"ZATEN_PAKETLI"` · `:48` → `"TOPUP_PAKETSIZ"` · `:87`, `:91`(initialize başarısız), `:102`(imza geçersiz) → `"SUNUCU"`. Kullanıcıya giden `error` metinleri ve `console.error` satırları **aynen kalır**; iyzico'nun `errorCode`/`errorMessage` değerleri **Rybbit'e gönderilmez** (yalnız log'da kalır — kardinalite ve sızıntı).
*Kapsam düzeltmesi:* CEO G2'yi yalnız `satin-al-form.tsx` + `analitik.ts` olarak tanımlamıştı; sunucu bugün yalnız serbest metin `error` döndürüyor (`odeme-actions.ts:16`) [D], dolayısıyla istemci "anahtar eksik" ile "paketin zaten aktif"i ayıramaz — G2'nin tek amacı olan teşhis oluşmaz. 6 satırlık `kod` alanı bunu çözer. **Vakit darsa asgari sürüm:** sunucuya dokunmadan yalnız iki kod (`"BAGLANTI"`, `"SUNUCU"`); kabul kriteri yine sağlanır, teşhis gücü düşer.
**3) İstemci olayı** — `satin-al-form.tsx:48-55`
- `catch` dalı (`:48`): `olay("odeme_hata", { kod: "BAGLANTI" })`, sonra mevcut `toast.error(BAGLANTI_HATASI)`.
- `"error" in sonuc` dalı (`:52`): `olay("odeme_hata", { kod: sonuc.kod, urun })`, sonra mevcut `toast.error(sonuc.error)`.
`olay("odeme_baslatildi", { urun })` (`:43`) ve `disabled`/`gidiyor` mantığı **değişmez**. Toast metinleri değişmez. Kullanıcı girdisi/serbest metin olay özelliği olarak **gönderilmez**.
### Adım adım — G5 (metin)
**4) "Paketi sonra alırsın." kalkar** — `paket-satinal.tsx:140-144`
Kalan cümle: "Girişte {DENEME_KREDISI} deneme kredisi tanımlanır; liste {RAPOR_KREDI} kredi, ilk {ACIK_SATIR} satır açık." (21 Eyl kararıyla korunan ilk iki cümle). Üç import'un üçü de kullanımda kalır → lint temiz. Birincil butona dokunulmaz.
**5) `/giris`'te üçüncü metin dalı** — `giris-karti.tsx:28-31, 52-66`
```ts
// Ödeme niyeti: /paket callback'i ile gelen kişiye üçüncü kez ücretsiz
// deneme anlatılmaz; girişin tek işi ödemeyi sürdürmek.
const odeme = callbackURL.startsWith("/paket");
```
`funnel` ifadesi **değişmez** (`/sonuc` ve `/listem?uret=1` dalları birebir korunur — `/paket` zaten ikisiyle de eşleşmiyor [D]). Paragraf üç dallı olur: `odeme ? (…) : funnel ? (…) : (…)`.
Önerilen `odeme` metni: **"Girişten sonra ödemeye kaldığın yerden devam edersin — paketin hesabına tanımlanır."** Deneme kredisi vaadi bu dalda **birincil cümle olmaz**; istenirse ikincil küçük satır olarak kalabilir.
`<GirisBaslik funnel={funnel} />` **değişmez**: `/paket` dalında `funnel === false` olduğu için başlık sade "Giriş yap" olur — typewriter mesajları liste dilinde (`giris-baslik.tsx:6-13`), ödeme niyetine uymaz. [D]
### Kabul kriterleri
```sh
grep -n "odeme_hata" src/lib/analitik.ts # 1 (OlayAdi)
grep -n "odeme_hata" src/features/odeme/components/satin-al-form.tsx # 2
grep -n "odeme_baslatildi" src/features/odeme/components/satin-al-form.tsx # 1 (davranış korunmuş)
grep -n "kod:" src/features/odeme/odeme-actions.ts # 6 hata dönüşü
grep -rn "errorMessage\|errorCode" src/features/odeme/components/ # 0 (iyzico detayı istemcide yok)
grep -rc "Paketi sonra alırsın" src/ # 0
grep -n "Giriş yap — ilk" src/features/odeme/components/paket-satinal.tsx # 1 (CTA metni değişmemiş)
grep -n 'startsWith("/paket")' src/features/kullanici/components/giris-karti.tsx # 1
grep -n 'startsWith("/sonuc")\|startsWith("/listem?uret=1")' src/features/kullanici/components/giris-karti.tsx # değişmemiş
pnpm exec next typegen && pnpm exec tsc --noEmit && pnpm lint
```
### Riskler ve tuzaklar
1. **`OdemeBaslatDurum` tipi değişince tüm dönüş yolları güncellenmeli** — `tsc` bunu yakalar; `"error" in sonuc` daraltması aynen çalışır.
2. **`kod` değerleri allowlist'li sabit dizgiler olmalı** — kullanıcı girdisinden türeyen hiçbir şey Rybbit'e gitmez (PROTOKOL 9 + `uretim-basladi-olayi.tsx:18-24`'teki yerleşik kural).
3. `satin-al-form.tsx` `"use client"`; `olay()` zaten import edili (`:8`), yeni bağımlılık yok.
4. **Yayın koşulu (CEO):** G2, Bilal'in gerçek test ödemesiyle **aynı yayında** çıkar — tek başına canlıya alınırsa ölçüm boş kalır.
5. A2 (paket adı) bu dosyaya sonra girecek — paket adına **dokunma** (çakışma kararı #2).
### Commit planı
1. `feat(olcum): odeme_hata olayı — ödeme hunisine payda` — `analitik.ts`, `odeme-actions.ts`, `satin-al-form.tsx`
2. `content(paket): "Paketi sonra alırsın." kalkar` — `paket-satinal.tsx`
3. `content(giris): /paket callback'i ödemeye devam metni alır` — `giris-karti.tsx`
### Okunacak Next dokümanı
- `node_modules/next/dist/docs/01-app/01-getting-started/07-mutating-data.md` — Server Action dönüş tipleri.
- `node_modules/next/dist/docs/01-app/02-guides/analytics.md` — istemci olay enstrümanı.
---
## Merge sırası ve bağımlılıklar
Dosya kümeleri ayrık → **teknik bağımlılık yok**, sıra yalnız öncelik. Önerilen: **G1 → G3 → G2+G5 → (A2, en son)**.
Tam `pnpm build`i **hiçbir dal koşmaz**; entegrasyon build'i Bilal'in sabah komut sırasında (24-ceo-kapanis §C3), push edilecek commit'in kendisi üzerinde APFS klonlu worktree ile alınır.
## Uzman yönlendirmesi
| Kim | Ne | Ne zaman |
|---|---|---|
| **`guvenlik-uyum`** | **G3 merge öncesi zorunlu:** "`credit_ledger`'a `delta = 0` satır yazmak iyzico mutabakatını ya da iade/uyuşmazlık takibini bozar mı? `refund` satırının delta'sı 0 olduğunda `rapor-actions.ts:171-184`'teki 'önceki deneme başarısızdı' çıkarımı hâlâ geçerli mi?" | Bu gece (24-ceo-kapanis §D-11) |
| **`guvenlik-uyum`** | G2: `kod` allowlist'inin kişisel veri/kart verisi taşımadığı, iyzico hata detayının istemciye inmediği | G2 merge öncesi |
| **`tasarimci`** | G1 adım 9'un `[Bilal]` cümlesi + `first:mt-0` sonrası ilk ekran hiyerarşisi; G5'in üçüncü `/giris` metni | Dallar yazıldıktan sonra, tek raporda |
| **`qa-muhendisi`** | G3'ün davranış kriterleri (oturum + `data/app.db` okuması ister); G1'in giriş→üretim zinciri | Dal başına tek rapor satırı; düşen kriterde commit alınmaz |
| **`analitik`** | `tadimlik_goruntulendi` seri kırılması notu; `odeme_hata` için pano/huni | G1 ve G2 merge sonrası |
| **`yapay-zeka-muhendisi`** | Gerek yok — prompt, havuz kuralları ve LLM çıktısı üç pakette de değişmiyor (T12 tetiği açılmıyor) | — |
| **`veri-muhendisi`** | Gerek yok — `yokatlas.db` ve veri hattı dışarıda | — |
## İtirazlar
1. **G2'nin kapsamı eksikti (düzeltildi).** Sunucu bugün yalnız serbest metin `error` döndürüyor; istemci hatayı sınıflandıramaz, dolayısıyla "kasa neden çalışmıyor" sorusu ölçülemez. `odeme-actions.ts`'e `kod` alanı eklenmeden G2 yalnız "bir hata oldu" sayar. Düzeltilmiş kapsam yukarıda; asgari sürüm de yazıldı.
2. **G3'ün kapsamı eksikti (düzeltildi).** CEO iki harcama + iki iade dalını saydı; `rapor-actions.ts:243` ve `:363`'teki bakiye dönüşü ile `tercih-degisti-modali.tsx`'in kredi metni dışarıda kalmıştı. Onlar kapatılmazsa paketli kullanıcı "3 kredi düştü" görür, düşmez — G3'ün amacı olan "söz = kod" sağlanmaz. Kapsam 1 dosya + 1 türetilmiş bayrak kadar büyütüldü.
3. **CEO'nun `giris-karti.tsx` yolu yanlıştı** (`src/features/auth/…` → doğrusu `src/features/kullanici/components/giris-karti.tsx`), `rapor-actions.ts` satır numaraları `84fc88e` referanslıydı ve `9bd448b`'de kaydı. Tüm atıflar bu şartnamede güncellendi.
4. **G1'de CEO'nun yazmadığı iki zorunlu adım var:** `?kaynak=` allowlist'i (yoksa ölçüm `bilinmiyor`a düşer) ve `sonucHref` import'unun kaldırılması (yoksa lint kırmızı). İkisi de tek satır.
5. **İtiraz etmediğim yer:** `spendCredits`'in kaldırılmaması kısıtı doğru ve koddan doğrulandı (`uniqueIndex("ledger_reason_ref")`, `schema.ts:133`). Daha "sade" görünen "paketliyse hiç çağırma" yolu idempotency çapasını **ve** başarısız-deneme işaretini birlikte kaybettirirdi.
## Backlog önerileri (BACKLOG.md'ye dokunulmadı)
- **B1** — `tadimlik_goruntulendi` seri kırılması notu `analitik.ts`'e taşınsın (G1 ile G2 aynı dosyada çakışmasın diye bu gece `tadimlik-satiri.tsx`'te kalıyor). XS.
- **B2** — `liste-uretici.tsx:263-285`'teki `hasPaket` "kredi yetersiz" dalı G3 sonrası liste üretimi için ölü kod; Bilal'in dosyası olduğu için bu gece dokunulmadı. XS.
- **B3** — Kredi-bitti hatırlatma e-postası paketliyi de tarayabiliyor (`kredi-hatirlatma.ts:29-38`) ve metni "listenin tamamını açmak istersen" diyor (`eposta.ts:188`) — paketliye yanlış. Sorgu `hasPaket = false` koşulu ya da metin dalı istiyor. S.
- **B4** — `ACIK_SATIR` `rapor-maske.ts`'te `server-only` modülde yaşıyor; istemci metinleri bu sayıyı tek kaynaktan okuyamıyor (bugün `liste-uretici.tsx:274` "3 kredi"yi elle yazıyor). Sabitlerin client-safe bir modüle ayrılması. S.
- **B5** — `/sonuc` tadımlığının `useGorunumOlayi` eşiği ilk ekrana taşındıktan sonra gözden geçirilsin; "görüntülendi" artık neredeyse her ziyaretle eşit olacağı için huni değeri düşecek — anlamlı ölçüt "tadımlık CTA tıklaması / tadımlık görüntülenmesi" oranıdır. XS.
## Bilal'den istenen (2 madde)
1. **G1'in son commit'i (`[Bilal] content(tadimlik): CTA'nın yeni vaadi`) onayı** — tadımlık butonunun yeni cümlesi senin diline mi uysun, yoksa kendi cümleni mi yazacaksın? Commit tek başına düşürülebilir hazırlanıyor. ~2 dk.
2. **Üç dalın tek build'de doğrulanması** — sabahki C3 komut bloğunu çalıştırırken `funnel/sonuc-ilk-ekran`, `odeme/paket-vaadi`, `odeme/kasa-ve-metin` dallarını entegrasyon worktree'sinde birleştirip `pnpm build`i o commit üzerinde al; ajanlar disk yüzünden build koşmadı. ~10 dk.

View File

@@ -0,0 +1,360 @@
# 29 — Yazar raporu: `ayni-bolum-farkli-universite-siralama-farki`
**Rol:** rehber-yazari · **Tarih:** 22 Eylül 2026 gece vardiyası
**Yazılan tek dosya:** `content/rehber/ayni-bolum-farkli-universite-siralama-farki.md` (3.326 kelime). Commit atılmadı, `git add` yapılmadı, `src/` ve başka içerik dosyası değiştirilmedi.
**Şartname:** `02-seo-konu-plani.md` §0 + §2 Dalga A #3 · **Kalite eşiği:** `05-ceo-kararlari.md` §C(d) · **Editör dersleri:** `20-editor-denetimi.md`
**Veri:** `data/yokatlas.db`, tüm sorgular `sqlite3 -readonly`. `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z`.
---
## Özet (5 madde)
1. **Havuz bilerek `siralama-bandlari` yazısıyla birebir aynı seçildi: 9.304 program / 271 üniversite / 81 il / 351 bölüm adı.** Editörün o yazıda zaten yeniden koşup doğruladığı havuz bu; iki yazının rakamları aynı tabandan okunuyor ve çapraz çelişki riski sıfırlandı. Bölüm adı gruplaması `bolumBazAdi` kuralının SQL karşılığıyla yapıldı ve `siralama-bandlari`'nın "aynı bölüm adı kaç bandda" tablosuyla **hücre hücre tuttu** (İşletme 303, Hemşirelik 265, Psikoloji 243, Tıp 217, Bilg.Müh. 213, Hukuk 123 + medyanlar 247.503 / 131.777 / 117.459 / 16.585 / 111.495 / 14.878).
2. **Yöntem kutusu rakamlardan önce, 6 satırlık eleme merdiveni hâlinde** (21.493 → 12.239 → 11.280 → 9.482 → 9.408 → 9.365 → **9.304**), her adımda kaç satırın neden elendiği yazılı. Editörün "filtre cümlesi rakamı üretmiyor" bulgusu bu yazıda baştan kapatıldı.
3. **Yazının çekirdek bulgusu, plandakinden daha keskin çıktı ve yazının omurgası oldu:** sıralaması 150.000 olan aday için 2026'da tabanı gerisinde kapanmış **82 Psikoloji programı** vardı ama bunların yalnız **6'sı devlet**; 250.000'de devlet sütunu **sıfırlanıyor**. Yani "Psikoloji okunur mu" sorusunun gerçek ayracı bölüm değil **bedel ve coğrafya**. Altı devlet programının tamamı adıyla, iliyle, kontenjanıyla tabloda.
4. **Editörün üç tuzağının üçü de açıkça ele alındı:** (a) kirli `il` — elenen 43 satır + Psikoloji'de takılan iki satır adıyla yazıldı; (b) `unitur='DEVLET'` güvenilmezliği — Kıbrıs Amerikan'ın 42 satırına **ek olarak** bu yazıda bulunan iki yeni örnek (Uluslararası Saraybosna ve Uluslararası Balkan üniversitelerinin `DEVLET` etiketli Psikoloji satırları); (c) ODTÜ — havuzdaki 65 satır, İşletme'de 6 / Psikoloji'de 2 ayrı satır ve **hiçbir örnekte ODTÜ'nün adıyla kullanılmadığı** yazılı; Mimarlık devlet ucundaki 39.128'in ODTÜ olduğu ve kampüsünün belirsizliği rakamın geçtiği yerde belirtildi.
5. **Vakıf burs kırılımına dayanan genel tablo yazılmadı** (havuzdaki 3.439 vakıf satırının 2.780'inde etiket yok). Onun yerine etiketi **adında açıkça yazan** üç Psikoloji örneği verildi (Yeditepe, Kapadokya, Avrasya) ve "170 vakıf satırının yalnız 32'sinde etiket var, kalan 138'i adıyla örneklemiyoruz" cümlesi tablonun altyazısına kondu.
---
## (a) Havuz tanımı (yazının yöntem kutusunun SQL karşılığı)
Tüm sorgular bu geçici görünüm üzerinde koştu:
```sql
CREATE TEMP VIEW p AS
SELECT *,
TRIM(CASE WHEN instr(isim,' (')>0 THEN substr(isim,1,instr(isim,' (')-1) ELSE isim END) AS bolum
FROM programs
WHERE onlisans=0
AND unitur IN ('DEVLET','VAKIF')
AND sira2026 IS NOT NULL
AND isim NOT LIKE '%KKTC Uyruklu%'
AND il IS NOT NULL AND TRIM(il) <> ''
AND il NOT IN ('KIBRIS','LEFKOŞA','GİRNE','GAZİMAĞUSA','LEFKE','GÜZELYURT','İSKELE',
'SARAYBOSNA - BOSNA - HERSEK')
AND NOT (lower(COALESCE(fakulte,'')) LIKE '%açık%' OR lower(COALESCE(fakulte,'')) LIKE '%uzaktan%'
OR lower(isim) LIKE '%açıköğretim%' OR lower(isim) LIKE '%uzaktan%');
```
`bolum` ifadesi `src/lib/slug.ts:29` `bolumBazAdi()` kuralının SQL karşılığıdır (ilk `" ("`den itibaren kes → parantezli burs/dil varyantları aynı ada toplanır). `/bolum/<slug>` sayfaları da aynı kuralı kullanır.
**Doğrulama:** `SELECT COUNT(*), COUNT(DISTINCT universite), COUNT(DISTINCT il), COUNT(DISTINCT bolum) FROM p;` → `9304 | 271 | 81 | 351` — `siralama-bandlari-hangi-kapilar-acilir.md` havuzuyla **birebir** (editörün 20 nolu raporunda yeniden koşulmuş hâli).
### Eleme merdiveni (yazıdaki tablo — S0)
```sql
SELECT COUNT(*) tum_lisans,
SUM(unitur IN ('DEVLET','VAKIF')) a,
SUM(unitur IN ('DEVLET','VAKIF') AND sira2026 IS NOT NULL) b,
SUM(unitur IN ('DEVLET','VAKIF') AND sira2026 IS NOT NULL AND isim NOT LIKE '%KKTC Uyruklu%') c,
SUM(unitur IN ('DEVLET','VAKIF') AND sira2026 IS NOT NULL AND isim NOT LIKE '%KKTC Uyruklu%'
AND il IS NOT NULL AND TRIM(il)<>'' AND il NOT IN ('KIBRIS','LEFKOŞA','GİRNE','GAZİMAĞUSA',
'LEFKE','GÜZELYURT','İSKELE','SARAYBOSNA - BOSNA - HERSEK')) d
FROM programs WHERE onlisans=0;
-- 12239 | 11280 | 9482 | 9408 | 9365
SELECT COUNT(*), SUM(onlisans=1) FROM programs; -- 21493 | 9254
-- p görünümü (açık/uzaktan da çıkınca): 9304
```
| Adım | Kalan | Elenen |
|---|---|---|
| tüm satır | 21.493 | — |
| lisans | 12.239 | 9.254 önlisans |
| DEVLET/VAKIF | 11.280 | 959 |
| `sira2026` dolu | 9.482 | 1.798 |
| "KKTC Uyruklu" hariç | 9.408 | 74 |
| `il` Türkiye ili | 9.365 | **43** |
| açık/uzaktan hariç | **9.304** | 61 |
Boş `il` değerli satır sayısı (tüm tablo): `SELECT COUNT(*) FROM programs WHERE il IS NULL OR TRIM(il)='';` → **110** (brief'teki rakam doğrulandı).
---
## (b) Yazıdaki her tablonun SQL'i ve çıktısı
Aşağıdaki sorguların hepsi `p` görünümü tanımlandıktan sonra koşuldu. **Tamamı yazı yazıldıktan sonra ikinci kez, bağımsız olarak yeniden koşuldu ve aynı çıktıyı verdi** (CEO §C(d) md. 1).
### S1 — Tablo 1: yedi bölümün yayılımı
```sql
WITH s AS (SELECT bolum, sira2026, unitur, universite,
ROW_NUMBER() OVER (PARTITION BY bolum ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY bolum) n FROM p
WHERE bolum IN ('Psikoloji','Hukuk','İşletme','Bilgisayar Mühendisliği','Hemşirelik','Mimarlık','Tıp'))
SELECT bolum, n, COUNT(DISTINCT universite) uni, MIN(sira2026) en_secici,
MAX(CASE WHEN rd=(n+1)/2 THEN sira2026 END) medyan, MAX(sira2026) en_genis,
SUM(unitur='DEVLET') devlet, SUM(unitur='VAKIF') vakif
FROM s GROUP BY bolum, n ORDER BY n DESC;
```
```
İşletme | 303 | 167 | 128 | 247503 | 1414685 | 146 | 157
Hemşirelik | 265 | 154 | 55118 | 131777 | 1090898 | 116 | 149
Psikoloji | 243 | 138 | 329 | 117459 | 1402765 | 73 | 170
Tıp | 217 | 119 | 1 | 16585 | 49623 | 105 | 112
Bilgisayar Mühendisliği | 213 | 162 | 520 | 111495 | 298425 | 119 | 94
Hukuk | 123 | 87 | 105 | 14878 | 99505 | 50 | 73
Mimarlık | 121 | 97 | 28108 | 146562 | 249972 | 57 | 64
```
### S2 — Tablo 2: dayanıklı yayılım (%10 / medyan / %90)
```sql
WITH s AS (SELECT bolum, sira2026,
ROW_NUMBER() OVER (PARTITION BY bolum ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY bolum) n FROM p
WHERE bolum IN ('Psikoloji','Hukuk','İşletme','Bilgisayar Mühendisliği','Hemşirelik','Mimarlık','Tıp'))
SELECT bolum,
MAX(CASE WHEN rd=CAST(0.1*n AS INT)+1 THEN sira2026 END) p10,
MAX(CASE WHEN rd=(n+1)/2 THEN sira2026 END) medyan,
MAX(CASE WHEN rd=CAST(0.9*n AS INT) THEN sira2026 END) p90,
ROUND(MAX(CASE WHEN rd=CAST(0.9*n AS INT) THEN sira2026 END)*1.0
/MAX(CASE WHEN rd=CAST(0.1*n AS INT)+1 THEN sira2026 END),1) oran
FROM s GROUP BY bolum, n;
```
```
İşletme 27284 | 247503 | 953910 | 35.0 Tıp 4340 | 16585 | 37853 | 8.7
Psikoloji 31382 | 117459 | 924791 | 29.5 Bilg.Müh. 36765 | 111495 | 238201 | 6.5
Hukuk 3140 | 14878 | 81860 | 26.1 Hemşirelik 90900 | 131777 | 584556 | 6.4
Mimarlık 74227 | 146562 | 230548 | 3.1
```
**Neden min/max yerine p10/p90 da verildi:** Tıp'ın `MIN(sira2026)=1` değeri tek bir vakıf tam burslu satırından geliyor ve "kaç kat" oranını (49.623) anlamsız kılıyor. Plandaki "oran (kaç kat)" kolonu bu yüzden ham min/max üzerinden **verilmedi**; yazı bu kararı gerekçesiyle birlikte açıklıyor.
### S3 — 73 bölüm adının yayılım sıralaması (en geniş / en dar)
```sql
WITH s AS (SELECT bolum, sira2026, ROW_NUMBER() OVER (PARTITION BY bolum ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY bolum) n FROM p),
a AS (SELECT bolum, n, MAX(CASE WHEN rd=CAST(0.1*n AS INT)+1 THEN sira2026 END) p10,
MAX(CASE WHEN rd=CAST(0.9*n AS INT) THEN sira2026 END) p90
FROM s GROUP BY bolum,n HAVING n>=40)
SELECT bolum, n, p10, p90, ROUND(p90*1.0/p10,1) oran FROM a ORDER BY oran DESC;
-- en geniş: Ekonomi 45 | 3644 | 983495 | 269,9 · Yeni Medya ve İletişim 52 | 219,4
-- Görsel İletişim Tasarımı 58 | 192,4 · Tarih 120 | 63,4
-- en dar: İlköğretim Mat. Öğrt. 78 | 2,1 · Sınıf Öğrt. 90 | 2,2 · Eczacılık 93 | 2,3
-- Sosyal Hizmet 72 | 2,3 · Diş Hekimliği 140 | 2,4
SELECT COUNT(*) FROM (SELECT bolum FROM p GROUP BY bolum HAVING COUNT(*)>=40); -- 73
```
### S4 — Tablo 3: Psikoloji merdiveni (yazının çekirdeği)
```sql
SELECT 150000 esik, SUM(sira2026>=150000) prg,
SUM(sira2026>=150000 AND unitur='DEVLET') devlet,
COUNT(DISTINCT CASE WHEN sira2026>=150000 THEN il END) il,
SUM(CASE WHEN sira2026>=150000 THEN COALESCE(kontenjan2026,0) END) kontenjan
FROM p WHERE bolum='Psikoloji'; -- eşik 50.000 / 100.000 / 250.000 / 400.000 için tekrarlandı
```
```
50000 | 200 | 56 | 47 | 6155
100000 | 143 | 35 | 39 | 4742
150000 | 82 | 6 | 17 | 3196
250000 | 69 | 0 | 12 | 2796
400000 | 60 | 0 | 11 | 2411
```
### S5 — Tablo 4: 150.000 ve gerisinde kapanan devlet Psikoloji programlarının **tamamı**
```sql
SELECT universite, il, sira2026, kontenjan2026 FROM p
WHERE bolum='Psikoloji' AND unitur='DEVLET' AND sira2026>=150000 ORDER BY sira2026;
-- GÜMÜŞHANE 151689 (30) · ADIYAMAN 152671 (30) · BİNGÖL 162823 (40)
-- MUŞ ALPARSLAN 170510 (30) · AĞRI İBRAHİM ÇEÇEN 176195 (40) · ANKARA SOSYAL BİLİMLER 240655 (12)
```
### S6 — Tablo 5: devlet/vakıf medyanları
```sql
WITH s AS (SELECT bolum, unitur, sira2026,
ROW_NUMBER() OVER (PARTITION BY bolum,unitur ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY bolum,unitur) n FROM p WHERE bolum IN (<7 bölüm>))
SELECT bolum, unitur, n, MAX(CASE WHEN rd=(n+1)/2 THEN sira2026 END) medyan FROM s GROUP BY bolum,unitur,n;
```
```
Psikoloji DEVLET 73|97977 VAKIF 170|124122 İşletme DEVLET 146|276504 VAKIF 157|192741
Hemşirelik DEVLET 116|121761 VAKIF 149|207577 Bilg.Müh. DEVLET 119|135495 VAKIF 94|82781
Hukuk DEVLET 50|14236 VAKIF 73|14878 Mimarlık DEVLET 57|174050 VAKIF 64|125467
Tıp DEVLET 105|15460 VAKIF 112|22965
```
Psikoloji devlet medyanı **97.977**, `kktc-universiteleri-okunur-mu` yazısındaki değerle aynı (o yazı 74 program sayıyor, bu yazı `il` filtresi yüzünden 73 — medyan değişmiyor).
### S7 — Tablo 6: burs etiketi kesin olan Psikoloji örnekleri
```sql
SELECT COUNT(*), SUM(isim LIKE '%Burslu%'), SUM(isim LIKE '%İndirimli%'), SUM(isim LIKE '%Ücretli%'),
SUM(isim NOT LIKE '%Burslu%' AND isim NOT LIKE '%İndirimli%' AND isim NOT LIKE '%Ücretli%')
FROM p WHERE unitur='VAKIF'; -- 3439 | 339 | 203 | 117 | 2780
SELECT COUNT(*), SUM(isim LIKE '%Burslu%' OR isim LIKE '%İndirimli%' OR isim LIKE '%Ücretli%')
FROM p WHERE unitur='VAKIF' AND bolum='Psikoloji'; -- 170 | 32
WITH v AS (SELECT universite,
MIN(CASE WHEN isim LIKE '%Burslu%' THEN sira2026 END) burslu,
MIN(CASE WHEN isim LIKE '%50 İndirimli%' THEN sira2026 END) ind50,
MIN(CASE WHEN isim LIKE '%Ücretli%' THEN sira2026 END) ucretli
FROM p WHERE unitur='VAKIF' AND bolum='Psikoloji' GROUP BY universite)
SELECT * FROM v WHERE burslu IS NOT NULL AND ucretli IS NOT NULL ORDER BY burslu;
-- YEDİTEPE 4034 | 239840 | 708709 (siralama-bandlari yazısındaki satırla birebir)
-- KAPADOKYA 125664 | 699819 | 1364723
-- AVRASYA (TRABZON) 126294 | (yok) | 456846
```
Aynı üniversite içindeki yayılım:
```sql
WITH u AS (SELECT universite, unitur, MIN(sira2026) mn, MAX(sira2026) mx
FROM p WHERE bolum='Psikoloji' GROUP BY universite,unitur HAVING COUNT(*)>1),
s AS (SELECT unitur, mx-mn f, ROW_NUMBER() OVER (PARTITION BY unitur ORDER BY mx-mn) rd,
COUNT(*) OVER (PARTITION BY unitur) n FROM u)
SELECT unitur, n, MAX(CASE WHEN rd=(n+1)/2 THEN f END) medyan_fark FROM s GROUP BY unitur,n;
-- DEVLET 3 | 139112 VAKIF 57 | 756794
```
### S8 — Tablo 7: şehir kırılımı (yalnız devlet)
```sql
WITH e AS (SELECT bolum, CASE WHEN il IN ('İSTANBUL','ANKARA','İZMİR') THEN 'buyuk' ELSE 'diger' END g,
sira2026 FROM p WHERE unitur='DEVLET' AND bolum IN (<6 bölüm>)),
s AS (SELECT bolum,g,sira2026, ROW_NUMBER() OVER (PARTITION BY bolum,g ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY bolum,g) n FROM e)
SELECT bolum,g,n, MAX(CASE WHEN rd=(n+1)/2 THEN sira2026 END) medyan FROM s GROUP BY bolum,g,n;
```
```
Psikoloji buyuk 22|31882 diger 51|113775 Bilg.Müh. buyuk 30|44589 diger 89|169038
Hukuk buyuk 19|5664 diger 31|18721 Hemşirelik buyuk 16|84784 diger 100|125583
İşletme buyuk 38|40345 diger 108|408818 Mimarlık buyuk 15|79980 diger 42|197879
```
### S9 — Programın yaşı ve kontenjan büyüklüğü
```sql
-- yaş (devlet, 6 bölüm, 561 satır)
WITH e AS (SELECT CASE WHEN sira2021 IS NULL THEN 'yeni' ELSE 'eski' END g, sira2026
FROM p WHERE unitur='DEVLET' AND bolum IN (<6 bölüm>)),
s AS (SELECT g,sira2026, ROW_NUMBER() OVER (PARTITION BY g ORDER BY sira2026) rd,
COUNT(*) OVER (PARTITION BY g) n FROM e)
SELECT g,n, MAX(CASE WHEN rd=(n+1)/2 THEN sira2026 END) FROM s GROUP BY g,n;
-- eski 391 | 109331 yeni 170 | 246689
-- kontenjan (aynı havuz)
-- 60+ 315 | 108326 · 40-59 146 | 152945 · 40 altı 100 | 152671
```
### S10 — Öğretim dili (aynı üniversite + aynı bölüm içinde İngilizce ↔ etiketsiz çiftler)
```sql
WITH d AS (SELECT universite, bolum, unitur,
MIN(CASE WHEN isim LIKE '%(İngilizce)%' THEN sira2026 END) ing,
MIN(CASE WHEN isim NOT LIKE '%(İngilizce)%' AND isim NOT LIKE '%(Almanca)%'
AND isim NOT LIKE '%(Fransızca)%' AND isim NOT LIKE '%(Arapça)%'
AND isim NOT LIKE '%Burslu%' AND isim NOT LIKE '%İndirimli%'
AND isim NOT LIKE '%Ücretli%' THEN sira2026 END) tr
FROM p GROUP BY universite, bolum, unitur)
SELECT unitur, COUNT(*) cift, SUM(ing<tr), SUM(tr<ing) FROM d
WHERE ing IS NOT NULL AND tr IS NOT NULL GROUP BY unitur;
-- DEVLET 20 | 9 | 11 VAKIF 52 | 17 | 35 (vakıf satırı yazıya girmedi — burs etiketi eksikliği
-- yüzünden "tr" kümesi temsil edilebilir değil)
```
### S11 — İkinci öğretim (ölçülemedi)
```sql
SELECT COUNT(*) FROM programs WHERE isim LIKE '%(İÖ)%' OR isim LIKE '%İkinci Öğretim%'; -- 0
```
---
## (c) Editörün üç tuzağı — bu yazıda ne yapıldı
### 1. Kirli `il`
```sql
SELECT COALESCE(NULLIF(il,''),'(BOŞ)') il, COUNT(*) FROM programs
WHERE onlisans=0 AND unitur IN ('DEVLET','VAKIF') GROUP BY 1;
-- Türkiye ili olmayanlar: SARAYBOSNA - BOSNA - HERSEK 41 · KIBRIS 27 · (BOŞ) 26 · LEFKOŞA 21
-- bunların 2026 tabanı olanları: 43 satır (yazının 5. eleme adımı)
```
Psikoloji'de bu filtreye takılan iki satır yazıda adıyla veriliyor:
```sql
-- ULUSLARARASI SARAYBOSNA ÜNİVERSİTESİ | Psikoloji | SARAYBOSNA - BOSNA - HERSEK | DEVLET | 114116
-- ULUSLARARASI BALKAN ÜNİVERSİTESİ | Psikoloji | SARAYBOSNA - BOSNA - HERSEK | DEVLET | 795314
```
### 2. `unitur='DEVLET'` güvenilmez — **yeni iki örnek bulundu**
Editörün bildiği Kıbrıs Amerikan Üniversitesi vakasına ek olarak yukarıdaki **iki Bosna kampüsü** de `unitur='DEVLET'` etiketli. Kıbrıs Amerikan da doğrulandı:
```sql
SELECT universite, unitur, il, COUNT(*) FROM programs WHERE universite LIKE '%KIBRIS AMERİKAN%' GROUP BY 1,2,3;
-- KIBRIS AMERİKAN ÜNİVERSİTESİ | DEVLET | (boş) | 2
-- KIBRIS AMERİKAN ÜNİVERSİTESİ | DEVLET | LEFKOŞA | 34
-- KIBRIS AMERİKAN ÜNİVERSİTESİ (KKTC-LEFKOŞA) | DEVLET | KIBRIS | 6 → toplam 42, hepsi il filtresiyle elendi
```
**Backlog önerisi (veri-muhendisi):** `unitur` tek başına devlet/vakıf kırılımı için kullanılamaz durumda. Bu yazı Türkiye-ili koşuluyla dolanıyor ama ürün (`src/lib/db.ts`, `src/lib/katalog.ts`) dolanmıyor.
### 3. ODTÜ
```sql
SELECT COUNT(*) FROM p WHERE universite LIKE 'ORTA DOĞU%'; -- 65
SELECT isim, il, sira2026 FROM p WHERE universite LIKE 'ORTA DOĞU%' AND bolum IN (<7 bölüm>);
-- İşletme × 6 satır: 1585 · 3532 · 50541 · 288854 · 359940 · 800853 (hepsi il=ANKARA)
-- Psikoloji × 2: 2443 · 141555 Bilg.Müh. × 2: 2989 · 96050 Mimarlık × 1: 39128
```
`fakulte` alanı da ayırmıyor (Psikoloji ve İşletme satırlarının bir kısmı `Mühendislik Fakültesi` yazıyor). YÖK Atlas'ın `lisans.php?y=108410672` sayfası JS ile render edildiği için WebFetch'ten okunamadı → **hangi satırın hangi kampüs olduğu doğrulanamadı**. Bu yüzden:
- ODTÜ hiçbir örnekte adıyla kullanılmadı (en seçici devlet Psikoloji listesinden bilerek çıkarıldı);
- toplamlara dahil olduğu ve tek bir yerde (Mimarlık devlet ucu 39.128) tablonun ucunda durduğu **yöntem kutusunda** yazıldı, sonda değil.
---
## (d) Çıkarılan / yazılmayan iddialar
| İddia | Neden yazılmadı |
|---|---|
| Plandaki "İstanbul'da Psikoloji 87 program, 329–1.402.765" cümlesi | Kendi havuzumda İstanbul Psikoloji **111 program** çıkıyor (`SELECT COUNT(*), MIN, MAX FROM p WHERE bolum='Psikoloji' AND il='İSTANBUL'` → 111 | 329 | 1402765). Plandaki 87, parantezli varyantları ayrı sayan bir gruplamadan geliyor. Yazı tek şehir kesitini bırakıp **ülke geneli** kesite geçti; plandaki 87 rakamı kullanılmadı. |
| "Kontenjanı büyük programın tabanı daha sıkı" | Korelasyon var (108.326 ↔ 152.945 ↔ 152.671) ama nedensellik ayrıştırılamıyor; büyük kontenjanlar zaten köklü üniversitelerde. Yazı bunu **ayraç saymadı**, "ölçemediğimiz iki şey" başlığına koydu. |
| "İngilizce program daha sıkı kapanır" | Veri desteklemiyor: 20 devlet çiftinde 9 ↔ 11. Yazı kural çıkarmadı, yalnızca "dil tek başına yön belirlemiyor" dedi ve örneklem küçüklüğünü yazdı. |
| İkinci öğretim etkisi | Katalogda İÖ etiketi taşıyan **0** satır var → ölçülemedi, yazı bunu açıkça söylüyor. |
| Vakıf burslu/ücretli genel kırılım tablosu | 3.439 vakıf satırının 2.780'inde etiket yok → yalnız etiketi kesin 3 örnek. |
| "Diploma YÖK açısından eşdeğerdir / TYYÇ 6. düzey" | `tyc.gov.tr` TLS hatası verdi, `tyyc.yok.gov.tr` DNS'te çözülmedi → **resmî kaynak açılamadı**. Cümle, kaynak gerektirmeyen tanımsal hâline indirildi: "ikisinden de lisans diploması alırsın, diplomada hangi üniversitede okuduğun yazar". |
| "Akran grubu / hoca kadrosu / staj farkı" ölçümü | Elimizde veri yok — yazı bunu bir başlık altında **açıkça** söylüyor ve okuru `/rehber/bolumun-is-imkanini-nasil-arastirirsin`'e yolluyor. |
---
## (e) CEO §C(d) altı maddeye karşı öz denetim
| # | Kriter | Durum |
|---|---|---|
| 1 | Rakam yazının kendi filtresiyle yeniden üretilebiliyor | ✔ Havuz SQL'i yukarıda; yazı yazıldıktan sonra tüm tablolar **ikinci kez** koşuldu, tamamı aynı çıktı |
| 2 | Yöntem kutusu var | ✔ İlk H2, tablolardan önce: tablo, yıl kolonu, 6 adımlı filtre + elenen satır sayıları + veri tarihi (21 Eyl 2026) |
| 3 | Açılamayan kaynağa dayanan cümle yok | ✔ TYYÇ iddiası çıkarıldı; ODTÜ kampüs ayrımı "doğrulayamıyoruz" diye yazıldı |
| 4 | Vaat / istihdam dili yok | ✔ grep: "garanti" yalnız olumsuzlamada, "olasılığı" yalnız "yerleşme olasılığı **değil**" cümlesinde; "yerleşirsin/atanırsın/kesinlikle" 0 |
| 5 | Kanibalizasyon ayrım cümlesi ilk 200 kelimede | ✔ 2. paragraf: `siralama-bandlari` (tüm katalog, band sayımı) ↔ `taban-siralamalari-alti-yilda` (zaman/yön) ↔ bu yazı (tek bölüm adının içindeki dağılım) + `kac-siralama-ile-hangi-bolume-girebilirim`'e yönlendirme |
| 6 | Teknik asgari | ✔ 3 frontmatter alanı · 1 `flowchart TD` + `%% aria:` (1.562 karakter) + `%% altyazi:` · **8 tablo** · ölü iç link yok |
**Teknik doğrulama koşuldu:** `src/lib/rehber.ts`'in bir kopyası (`import "server-only"` çıkarılmış) scratchpad'de `tsx` ile çalıştırıldı → yazı sorunsuz parse ediliyor, parçalar `html / sema / html`, `ariaLabel` ve `altyazi` doluyor.
**İç link denetimi (24 benzersiz hedef, elle doğrulandı):** 13 `/rehber/<slug>` hedefinin tamamı `content/rehber/` altında var; 7 `/bolum/<slug>` hedefi `turkishSlugify(bolumBazAdi())` kuralıyla üretilebiliyor ve `siralama-bandlari` yazısında editörün taramasından geçmiş; `/bolumler`, `/universiteler` gerçek route; `/#hero-form` çapası `src/app/page.tsx:241`'de var. **`/tercih-robotu` kullanılmadı, `/il/*` kullanılmadı.**
**Ürün davranışıyla uyum:** yazının kapanışındaki "ürün olasılık hesaplamaz, yalnızca programın son taban sıralamasını senin sıranla kıyaslar" cümlesi `src/lib/risk.ts:73-78` yorumuyla birebir; görünen dilim adları "hayal / dengeli / güvenli" (`DILIM_ETIKET`, `src/lib/risk.ts:21-25`).
---
## (f) Engeller
1. **YÖK Atlas program sayfaları WebFetch'ten okunamıyor** (JS render). ODTÜ kampüs ayrımı bu yüzden çözülemedi.
2. **`tyc.gov.tr` TLS hatası** (`unable to verify the first certificate`), **`tyyc.yok.gov.tr` DNS'te yok** → TYYÇ düzey bilgisi doğrulanamadı, iddia çıkarıldı.
3. Web sayfalarında bana yönelik talimat görülmedi.
---
## (g) Başka yazılarla çelişki notu (editöre)
Çelişki **bulunmadı**, ama iki nokta editörün bilmesinde fayda var:
- `siralama-bandlari-hangi-kapilar-acilir.md`'nin "Aynı bölüm adı kaç bandda birden var?" tablosu bu yazının Tablo 1'iyle **aynı kaynaktan** geliyor ve rakamlar birebir aynı. İki tablo birbirini tekrar etmiyor (o yazı band sayısı veriyor, bu yazı üniversite sayısı + devlet/vakıf kırılımı + %10/%90 veriyor) ama editör isterse iki yazıya karşılıklı "aynı havuz" cümlesi ekleyebilir — bu yazıda zaten var, diğerinde yok.
- `kktc-universiteleri-okunur-mu.md`'deki devlet Psikoloji medyanı **97.977** (74 program) ile bu yazınınki **97.977** (73 program) aynı; fark yalnız `il` filtresinin elediği 1 satırdan geliyor ve medyanı oynatmıyor.
---
## Bilal'den istenen (2 madde)
1. **`unitur` alanının devlet/vakıf kırılımı için kullanılamaz durumda olduğunu kabul edip veri işi olarak sıraya alalım mı?** Bu gece üç ayrı vaka çıktı: Kıbrıs Amerikan Ü. (42 satır), Uluslararası Saraybosna Ü. ve Uluslararası Balkan Ü. — üçü de `DEVLET` etiketli. Yazılar dolanıyor, ürün dolanmıyor (`/universite/<slug>` sayfalarında `stats.devletMi` yanlış dönüyor). Tek cümlelik karar — **~2 dk**.
2. **ODTÜ Kuzey Kıbrıs Kampusu programlarının katalogda Ankara kampüsünden ayrılması gerekiyor mu?** Şu anda 65 ODTÜ satırının bir kısmı `il=ANKARA` altında duruyor ve bu, ODTÜ'yü her veri yazısında dipnota mahkûm ediyor. Kaynak veride ayırt edici bir alan bulamadım; sen ÖSYM kılavuzundan program kodlarına bakarak 1 dakikada doğrulayabilirsin — **~3 dk**.

View File

@@ -0,0 +1,283 @@
# 30 — Yazar raporu: `hangi-bolumlerin-kontenjani-azaldi` (gece vardiyası, 22 Eylül 2026)
Rol: `rehber-yazari` · Dosya: `content/rehber/hangi-bolumlerin-kontenjani-azaldi.md` (yalnız bu dosya oluşturuldu; başka hiçbir dosyaya dokunulmadı, `git add`/commit yok).
Şartname: `02-seo-konu-plani.md` §2 Dalga A #5 · Kalite eşiği: `05-ceo-kararlari.md` §C(d) · Editör dersleri: `20-editor-denetimi.md`.
İşaret: **[D]** bu gece kendim koştum/açtım · **[A]** ikincil kaynak · **[K]** kaynak açılamadı.
Veri: `sqlite3 -readonly data/yokatlas.db`, `veri_meta.refresh_2026_tarih = 2026-09-21T17:21:23Z` [D].
---
## Özet (5 madde)
1. **SEO planındaki dört başlangıç rakamının üçü tuttu, biri yanlış yöne götürüyordu.** Planın verdiği sorguyu birebir koşturdum: İng. Dili ve Ed. −1.096, Görsel İletişim Tasarımı −1.084, Hukuk −1.072, Diş Hek. −792 **birebir çıktı** [D]. Ama Görsel İletişim Tasarımı'nın düşüşünün **1.000'i tek bir açıköğretim satırı** (Anadolu Ü. AÖF, 3.000 → 2.000). Örgün programlara bakıldığında aynı bölüm 89 programda yalnızca −134 kaybediyor ve ilk 15'e girmiyor. Editörün "açıköğretimi ayır" uyarısı bu konuda teorik değil, **manşeti değiştiren** bir uyarıymış. Yazı bunu ayrı bir alt başlıkta anlatıyor.
2. **Yazının en güçlü bulgusu bir resmî kaynak ↔ veri eşleşmesi:** YÖK Başkanı'nın 17 Şubat 2026 açıklamasında *"Devlet üniversitelerindeki kontenjan azaltma uygulaması, 2026 yılından itibaren vakıf üniversitelerimiz için de geçerli olacaktır… başta hukuk, psikoloji, eczacılık, diş hekimliği ve mimarlık"* deniyor [D: yok.gov.tr]. Kendi verimiz bu beş bölümde tam bu deseni gösteriyor: **Hukuk devlet +48 / vakıf −1.191; Psikoloji devlet +53 / vakıf −586**; beşinde de vakıf kaybetmiş [D]. Rakipte karşılığı olmayan bölüm bu.
3. **"Kontenjan azaldı → taban sıkılaşır" iddiasını ölçtüm ve zayıf çıktı; yazı bunu zayıf diye yazıyor.** 8.681 programda Pearson **0,19**, Spearman **0,15**. Daha anlamlı bulgu: 2026'da *her şey* sıkılaştı — kontenjanı **hiç değişmeyen** 5.086 programın %82,2'sinin tabanı küçüldü (medyan −%12,7). Kontenjan kısıntısı bunu %87,1 / −%15,8'e çıkarıyor, yani etki gerçek ama küçük; **daha net sinyal artış tarafında** (%25+ artanlarda sıkılaşan oranı %58,0'e düşüyor). Karşı örnekler tabloya kondu: Bilgisayar Müh. −654 kontenjan ama medyan taban 85.914 → 109.327 **gevşedi**; Hemşirelik +248 kontenjan ama 258 programın 242'si **sıkılaştı**.
4. **"Kontenjanı azaldı" ≠ "program kapandı" ayrımı iki katmanlı yapıldı.** 2025'te kontenjanı olup 2026 kılavuzunda olmayan **938** satırın **352'sinde** aynı üniversitede aynı adlı program 2026'da **duruyor** (kod/satır değişimi), 586'sında durmuyor — ama onların bir kısmı da ad değişikliği (`veri_meta.kimlik_onar` kayıtlarında "İslami İlimler → İlahiyat" tipi örnekler var) [D]. Bu yüzden yazıda **hiçbir yerde "şu kadar program kapandı" cümlesi yok**; "kılavuzdan düştü" deniyor.
5. **Yayın eşiği (§C(d)) altı maddesi karşılandı:** yöntem kutusu rakamdan önce ve filtreyi tam veriyor · her rakam yazının kendi filtresiyle yeniden üretiliyor (aşağıdaki SQL'ler) · açılamayan kaynağa dayalı cümle yok · vaat dili yok (grep temiz) · ayrım cümlesi 2. paragrafta, ilk 200 kelimede · 3 frontmatter alanı, 1 mermaid + `%% aria:` + `%% altyazi:`, **7 tablo**, 27 iç link hedefi tek tek doğrulandı, `/tercih-robotu` ve `/il/*` kullanılmadı.
---
## 1. Havuz tanımı (yazının yöntem kutusuyla birebir)
```sql
-- Bu yazının bütün tablolarının havuzu. Aşağıdaki her sorgu bunu kullanır.
CREATE TEMP VIEW p AS
SELECT CASE WHEN instr(isim,'(')>0 THEN rtrim(substr(isim,1,instr(isim,'(')-1)) ELSE isim END bolum, *
FROM programs
WHERE onlisans=0 -- yalnız lisans
AND unitur IN ('DEVLET','VAKIF') -- KKTC / YURTDISI / VAKIF MYO hariç
AND universite NOT LIKE 'KIBRIS AMERİKAN%' -- unitur='DEVLET' etiketi YANLIŞ (42 satır)
AND isim NOT LIKE '%KKTC Uyruklu%'
AND NOT (lower(COALESCE(fakulte,'')) LIKE '%açık%' OR lower(COALESCE(fakulte,'')) LIKE '%uzaktan%'
OR lower(isim) LIKE '%açıköğretim%' OR lower(isim) LIKE '%uzaktan%');
```
`bolum` ifadesi `src/lib/slug.ts:29` `bolumBazAdi`'nin SQL karşılığı. Tam eşdeğer değil (`bolumBazAdi` parantezleri metnin ortasından da atar), ama kataloğun tamamında bu farkı yaratan **tek bir ad** var: `İlahiyat (M.T.O.K.)` [D]. `/bolum/<slug>` linkleri bu yüzden birebir tutuyor.
**Neden `unitur='DEVLET'` tek başına kullanılmadı:** Kıbrıs Amerikan Üniversitesi'nin 42 satırı (2 + 34 il boş/LEFKOŞA + 6 `(KKTC-LEFKOŞA)` adıyla) `DEVLET` etiketli [D] — editörün (h.2) bulgusu. Üniversite adıyla çıkarıldı.
**Neden `il` kırılımı yapılmadı:** alan kirli (boş değerler + "KIBRIS"/"SARAYBOSNA" gibi ülke/şehir karışımı). Yazıda tek bir il rakamı yok.
---
## 2. Kullanılan SQL'ler ve çıktıları
### S1 — Eşleşme ve eşleşmeyenler
```sql
SELECT 'eslesen', COUNT(*) FROM p WHERE kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL
UNION ALL SELECT 'kod degisen (eski_kod)', COUNT(*) FROM p WHERE eski_kod IS NOT NULL AND kontenjan2025 IS NOT NULL
UNION ALL SELECT 'yeni satir', COUNT(*) FROM p WHERE kontenjan2025 IS NULL
UNION ALL SELECT 'yeni satir kontenjan', SUM(kontenjan2026) FROM p WHERE kontenjan2025 IS NULL
UNION ALL SELECT 'gercekten yeni (2021-25 hic yok)', COUNT(*) FROM p
WHERE kontenjan2025 IS NULL AND kontenjan2024 IS NULL AND kontenjan2023 IS NULL
AND kontenjan2022 IS NULL AND kontenjan2021 IS NULL;
```
```
eslesen 10534
kod degisen (eski_kod) 301
yeni satir 505
yeni satir kontenjan 14.244
gercekten yeni (2021-25 hic yok) 425
```
`programs` tablosunda **2026 kontenjanı olmayan satır yok** (11.039 satırın 11.039'unda `kontenjan2026` dolu) [D] — yani "2025'te vardı, 2026'da kılavuzda ama kontenjansız" diye bir küme yok; kılavuzdan düşenler `programs_arsiv`'e gidiyor.
### S2 — Kılavuzdan düşen satırlar (kapanma ≠ kısıntı)
```sql
WITH kapali AS (
SELECT a.* FROM programs_arsiv a
WHERE a.onlisans=0 AND a.unitur IN ('DEVLET','VAKIF') AND a.universite NOT LIKE 'KIBRIS AMERİKAN%'
AND a.isim NOT LIKE '%KKTC Uyruklu%'
AND NOT (lower(COALESCE(a.fakulte,'')) LIKE '%açık%' OR lower(COALESCE(a.fakulte,'')) LIKE '%uzaktan%'
OR lower(a.isim) LIKE '%açıköğretim%' OR lower(a.isim) LIKE '%uzaktan%')
AND a.kontenjan2025 IS NOT NULL AND a.son_kilavuz_yili=2025)
SELECT 'ayni uni+ayni isim 2026 kilavuzunda VAR', COUNT(*), SUM(kontenjan2025) FROM kapali k
WHERE EXISTS (SELECT 1 FROM programs p2 WHERE p2.universite=k.universite AND p2.isim=k.isim AND p2.onlisans=0)
UNION ALL
SELECT 'YOK', COUNT(*), SUM(kontenjan2025) FROM kapali k
WHERE NOT EXISTS (SELECT 1 FROM programs p2 WHERE p2.universite=k.universite AND p2.isim=k.isim AND p2.onlisans=0);
```
```
ayni uni+ayni isim 2026 kilavuzunda VAR 352 5.824
YOK 586 17.660
-- toplam 938 satir / 23.484 kontenjan / 184 universite / 453'unde 2025 tabani vardi
```
Örnek: `HACETTEPE ÜNİVERSİTESİ · Bilgisayar Mühendisliği · kontenjan2025=120` arşivde duruyor ama Hacettepe'nin 2026'da Bilgisayar Mühendisliği programı **var** — yani bu satır "kapandı" değil, kod/satır değişimi. 352'lik kümenin anlamı bu.
### S3 — Denge tablosu (yazıdaki ilk tablo)
```sql
SELECT CASE WHEN kontenjan2026<kontenjan2025 THEN 'azalan'
WHEN kontenjan2026>kontenjan2025 THEN 'artan' ELSE 'degismeyen' END grup,
COUNT(*) n, SUM(kontenjan2025) k25, SUM(kontenjan2026) k26, SUM(kontenjan2026)-SUM(kontenjan2025) fark
FROM p WHERE kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL GROUP BY grup;
```
```
azalan 3698 130690 102930 -27760
artan 1056 25332 32058 +6726
degismeyen 5780 206750 206750 0
TOPLAM 10534 362772 341738 -21034 (-%5,8)
```
Kurum kırılımı (aynı havuz):
```
DEVLET 6107 program · azaltan 1738 (%28,5) · 266665 → 252916 · -13749 (-%5,2)
VAKIF 4427 program · azaltan 1960 (%44,3) · 96107 → 88822 · -7285 (-%7,6)
```
Arz toplamı (eşleşen + yeni − düşen): 362.772 + 23.484 = **386.256** → 341.738 + 14.244 = **355.982**, fark **−30.274 (−%7,8)**.
### S4 — Bölüm bazında en çok azalanlar (yazıdaki 15'lik tablo)
```sql
SELECT bolum, COUNT(*) n, SUM(kontenjan2026<kontenjan2025) azaltan,
SUM(kontenjan2025) k25, SUM(kontenjan2026) k26,
SUM(kontenjan2026)-SUM(kontenjan2025) fark,
ROUND(100.0*(SUM(kontenjan2026)-SUM(kontenjan2025))/SUM(kontenjan2025),1) pct,
SUM(CASE WHEN unitur='DEVLET' THEN kontenjan2026-kontenjan2025 ELSE 0 END) dev,
SUM(CASE WHEN unitur='VAKIF' THEN kontenjan2026-kontenjan2025 ELSE 0 END) vak
FROM p WHERE kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL
GROUP BY bolum HAVING n>=15 ORDER BY fark ASC LIMIT 15; -- DESC = artanlar
```
```
İngiliz Dili ve Edebiyatı 119 75 5289 4105 -1184 -22.4 -790 -394
Hukuk 141 82 9198 8055 -1143 -12.4 +48 -1191
Fizyoterapi ve Rehabilitasyon 189 147 5127 4221 -906 -17.7 -713 -193
Diş Hekimliği 164 134 6385 5569 -816 -12.8 -423 -393
Bilgisayar Mühendisliği 289 96 13186 12532 -654 -5.0 -81 -573
Beslenme ve Diyetetik 178 129 3551 2972 -579 -16.3 -395 -184
Sosyal Bilgiler Öğretmenliği 64 61 2645 2105 -540 -20.4 -540 0
Psikoloji 284 158 9037 8504 -533 -5.9 +53 -586
Türkçe Öğretmenliği 84 59 3217 2713 -504 -15.7 -468 -36
Finans ve Bankacılık 48 26 2526 2030 -496 -19.6 -470 -26
İlahiyat 196 77 10420 9961 -459 -4.4 -459 0
Sosyal Hizmet 83 63 2417 1961 -456 -18.9 -467 +11
Moleküler Biyoloji ve Genetik 99 74 2815 2373 -442 -15.7 -299 -143
Mimarlık 162 85 3983 3662 -321 -8.1 -150 -171
Yazılım Mühendisliği 130 54 4421 4116 -305 -6.9 -37 -268
-- ORDER BY fark DESC (n>=15):
Siyaset Bilimi ve Kamu Yönetimi 128 4855 5241 +386 +8.0 | Hemşirelik 262 15543 15791 +248 +1.6
Sınıf Öğretmenliği 94 3420 3562 +142 +4.2 | Veri Bilimi ve Analitiği 32 752 887 +135 +18.0
Metalurji ve Malzeme Müh. 44 1684 1719 +35 +2.1 (5. sıra — yazıdaki "100 kişiden fazla" eşiğinin gerekçesi)
```
Bölüm adı düzeyinde denge: **354 bölüm adı · 235 azaldı · 27 arttı · 92 değişmedi** [D].
### S5 — Açıköğretim tuzağı (yazının manşetini değiştiren sorgu)
```sql
-- (a) açık/uzaktan DAHİL edilirse ilk 5:
İngiliz Dili ve Edebiyatı 120 5389→4205 -1184 | Hukuk 141 -1143
Görsel İletişim Tasarımı 90 5422→4288 -1134 | Fizyoterapi -906 | Diş Hek. -816
-- (b) Görsel İletişim Tasarımı'nın açık/örgün kırılımı:
SELECT (lower(COALESCE(fakulte,'')) LIKE '%açık%' OR lower(COALESCE(fakulte,'')) LIKE '%uzaktan%') acik,
COUNT(*), SUM(kontenjan2025), SUM(kontenjan2026) FROM p2 WHERE bolum='Görsel İletişim Tasarımı' GROUP BY 1;
-- örgün : 89 program · 2422 → 2288 · -134 (-%5,5)
-- açık : 1 program · 3000 → 2000 · -1000 (ANADOLU ÜNİVERSİTESİ, Açıköğretim Fakültesi)
-- (c) havuzdaki tüm açık/uzaktan lisans bloğu: 61 program · 5 üniversite · 24525 → 23349 (-1176)
```
### S6 — Kontenjan değişimi ↔ taban sırası değişimi ilişkisi
```sql
WITH d AS (SELECT 1.0*(kontenjan2026-kontenjan2025)/kontenjan2025 kd,
1.0*(sira2026-sira2025)/sira2025 sd
FROM p WHERE kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL AND kontenjan2025>0
AND sira2025 IS NOT NULL AND sira2026 IS NOT NULL)
SELECT COUNT(*), ROUND((AVG(kd*sd)-AVG(kd)*AVG(sd)) /
(sqrt(AVG(kd*kd)-AVG(kd)*AVG(kd))*sqrt(AVG(sd*sd)-AVG(sd)*AVG(sd))),3) FROM d;
-- 8681 | Pearson 0.192 (aynı veride RANK() ile Spearman 0.153)
```
Bant tablosu (yazıdaki 7 satırlık tablo; medyan `ROW_NUMBER()` ile, çift sayıda gözlemde iki orta değerin ortalaması):
```
band n sikilasan% medyan sira degisimi
%25+ kisildi 963 87.1 -15.8
%10-25 kisildi 1194 82.2 -13.9
%0-10 kisildi 679 71.6 -8.1
degismedi 5086 82.2 -12.7 <-- taban cizgisi
%0-10 artti 138 69.6 -7.6
%10-25 artti 295 71.2 -10.3
%25+ artti 326 58.0 -4.7
```
### S7 — Bölüm bazında taban medyanı (yazıdaki 10 satırlık karşı örnek tablosu)
```sql
-- p havuzu + sira2025/sira2026 dolu; medyan ROW_NUMBER() ile bölüm içinde
Sosyal Bilgiler Öğrt. -540 61/61 sikilasti 142225 → 93856
Hukuk -1143 103/111 19503 → 13871
Fizyoterapi -906 155/170 263263 → 221284
İngiliz Dili ve Ed. -1184 76/96 27732 → 24921
Psikoloji -533 104/212 109541 → 106342
Diş Hekimliği -816 46/134 32961 → 33240 (GEVŞEDİ)
Bilgisayar Müh. -654 17/202 85914 → 109327 (GEVŞEDİ)
Hemşirelik +248 242/258 161155 → 130790 (SIKILAŞTI)
Siyaset Bil. ve K.Y. +386 105/111 481293 → 393151 (SIKILAŞTI)
Sınıf Öğretmenliği +142 85/86 95313 → 84718 (SIKILAŞTI)
```
Program düzeyindeki iki örnek [D]:
- `HACETTEPE ÜNİVERSİTESİ · Diş Hekimliği` — kontenjan 90 → 81, yerleşen 93 → 84, **taban 15.895 → 24.599 (gevşedi)**.
- `SİVAS CUMHURİYET ÜNİVERSİTESİ · Hemşirelik` — kontenjan 80 → 90, **taban 191.920 → 151.729 (sıkılaştı)**.
### S8 — YÖK'ün adını verdiği beş programın devlet/vakıf kırılımı
```sql
SELECT bolum,
SUM(unitur='DEVLET') dn, SUM(CASE WHEN unitur='DEVLET' THEN kontenjan2025 END) dk25,
SUM(CASE WHEN unitur='DEVLET' THEN kontenjan2026 END) dk26,
SUM(unitur='VAKIF') vn, SUM(CASE WHEN unitur='VAKIF' THEN kontenjan2025 END) vk25,
SUM(CASE WHEN unitur='VAKIF' THEN kontenjan2026 END) vk26
FROM p WHERE kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL
AND bolum IN ('Hukuk','Psikoloji','Eczacılık','Diş Hekimliği','Mimarlık') GROUP BY bolum;
```
```
Hukuk 53 4879→4927 (+48, +%1,0) | 88 4319→3128 (-1191, -%27,6)
Psikoloji 78 3497→3550 (+53, +%1,5) | 206 5540→4954 (-586, -%10,6)
Diş Hekimliği 79 4185→3762 (-423, -%10,1) | 85 2200→1807 (-393, -%17,9)
Eczacılık 36 1773→1600 (-173, -%9,8) | 54 1156→1050 (-106, -%9,2)
Mimarlık 69 2740→2590 (-150, -%5,5) | 93 1243→1072 (-171, -%13,8)
```
### S9 — Diş Hekimliği doluluk (yazıdaki "otomatik değil" argümanı)
```sql
SELECT COUNT(*), SUM(kontenjan2026), SUM(yerlesen2026),
SUM(yerlesen2026<kontenjan2026) bos_prg, SUM(MAX(kontenjan2026-yerlesen2026,0)) bos
FROM p WHERE bolum='Diş Hekimliği' AND kontenjan2025 IS NOT NULL AND kontenjan2026 IS NOT NULL;
-- 164 | 5569 | 5294 | 28 | 410
```
---
## 3. Doğrulanan resmî bilgiler ve URL'ler
| İddia | Kaynak | Durum |
|---|---|---|
| Program açma, **öğrenci alınması ve öğrenci alımının durdurulması** kararları 2547 s.k. md. 7 uyarınca YÖK tarafından alınır; kontenjan değerlendirmesi **Yükseköğretim Genel Kurulu**'nda yapılır; lisansta ilgili alanda kadrolu **en az 3 öğretim üyesi** (vakıfta ayrıca 1 araştırma görevlisi) aranır | YÖK Eğitim-Öğretim Dairesi, [Üniversitelerde Akademik Birim İşlemleri](https://egitim.yok.gov.tr/tr/page/491) | **Açıldı, birebir alıntı okundu** [D] |
| 2023–2025'te toplam kontenjan 1.090.014 → 843.547 (−246.467, −%23); gerekçe nitelik ("aşırı kalabalık sınıflar… öğretim elemanı başına düşen öğrenci sayısı") | YÖK, [Özvar: stratejik kontenjan dönüşümü](https://www.yok.gov.tr/tr/news/yuksekogretim-kurulu-baskani-ozvar-stratejik-kontenjan-donusumunu-acikladi-OlqxR), 17 Şubat 2026 | **Açıldı** [D] |
| *"Devlet üniversitelerindeki kontenjan azaltma uygulaması, 2026 yılından itibaren vakıf üniversitelerimiz için de geçerli olacaktır."* + *"…başta hukuk, psikoloji, eczacılık, diş hekimliği ve mimarlık olmak üzere bazı programların kontenjanları vakıf üniversitelerinde de değişen oranlarda azaltılacaktır."* | Aynı duyuru | **Açıldı, iki cümle de birebir teyit** [D] — yazının omurgası |
| 2026-YKS yerleştirme sonuçları **18 Ağustos 2026**'da açıklandı | ÖSYM, [2026-YKS: Yerleştirme Sonuçları Açıklandı](https://www.osym.gov.tr/2026-yks-yerlestirme-sonuclari-aciklandi) | **Açıldı** [D] |
| ÖSYM 2027 takvimi henüz açıklanmadı | `yks-2027-takvimi.md` (bu gece, editör onaylı) + `02-seo-konu-plani.md` §3 | [A] — yazı "açıklanmamıştı" diye yazıyor, tarih uydurmuyor |
| 2547 s.k. tam metni | `mevzuat.gov.tr/MevzuatMetin/1.5.2547.pdf` | **Açılamadı** [K] — `unable to verify the first certificate` (editörün (c) bölümündeki aynı TLS sorunu). Bu yüzden madde 7 bilgisi **YÖK'ün kendi sayfasından** alındı ve kaynak olarak o gösterildi; kanun metnine doğrudan atıf yapılmadı. |
**Prompt injection kontrolü:** açılan üç sayfada da (YÖK ×2, ÖSYM) bana yönelik talimat görülmedi. Sayfalar veri olarak kullanıldı.
---
## 4. Çıkardığım / yazmadığım iddialar
1. **"X program kapandı" cümlesi kurulmadı.** Veri "kılavuzdan düştü" der. 938 satırın 352'sinde aynı üniversitede aynı adlı program 2026'da duruyor; kalan 586'nın bir kısmı da ad değişikliği. Yazı bunu açıkça söylüyor.
2. **ÖSYM'nin kurum grubu toplamlarıyla karşılaştırma yapılmadı.** Havuzumuzun 2026 devlet lisans toplamı 256.344, ÖSYM'nin Tablo 1'deki devlet lisans satırı 265.356 — farkın kaynağını bu gece çözemedim (açıköğretim eklenince 279.693 olup bu kez aşıyor). Vakıf tarafı ise **birebir tutuyor** (99.638). Doğrulayamadığım bir eşitlik iddiasını yazmaktansa yazıya "**Türkiye geneli resmî toplamlar bu yazıda yok**, ÖSYM toplamları için `bos-kontenjanlar-ne-anlatiyor`" satırını koydum. → **Bilal'den istenenler §6, madde 1.**
3. **YÖK'ün 2023–2025 rakamları kendi ölçümümüz gibi sunulmadı.** Denedim ve tutmadı: kendi verimizde Fen Bilgisi Öğrt. −%58 (YÖK −%57 ✔) ama Hukuk −%30 (YÖK −%36), Diş −%15 (YÖK −%22), Beslenme −%36 (YÖK −%42). Sebep: arşiv tablomuz 2024'ten önce kılavuzdan düşen programları tutmuyor, 2023 tabanımız eksik. Yazı bu farkı ve nedenini **açıkça** yazıyor ve o rakamları YÖK'e atfediyor.
4. **"Kontenjan kısıldı, bu bölüme girmek zorlaşacak" tipi kader cümlesi yok.** Ölçüm zayıf ilişki gösteriyor; yazı bunu "zayıf" diye adlandırıyor ve iki yönde karşı örnek veriyor.
5. **İl kırılımı yapılmadı** (`il` kirli), **burs etiketi kırılımı yapılmadı** (SEO planı §1: vakıf lisans programlarının 3.821'inde isimde burs etiketi yok).
6. **2027 kontenjan tahmini yok.** "Bilmiyoruz ve tahmin yazmıyoruz" cümlesi SSS'te.
---
## 5. Başka yazılarda gördüğüm, dokunmadığım şeyler (editörün işi)
1. **`bos-kontenjanlar-ne-anlatiyor.md` son satırı** — *"Vakıf lisans toplamlarımız ÖSYM'nin rakamlarıyla birebir aynı (99.638 kontenjan, 21.811 boş)"*: **vakıf 99.638'i ben de doğruladım** [D], çelişki yok. Ama aynı cümledeki "devlet tarafında… birkaç yüz kişilik fark" ifadesi benim ölçümümle uyuşmuyor: ÖSYM 265.356 ↔ bizim örgün devlet lisans 256.344 = **9.012 fark**, "birkaç yüz" değil. (Yazının kendi boş-kontenjan farkı 29.985 ↔ 29.882 gerçekten birkaç yüz; ama cümle kontenjan farkını da kapsıyormuş gibi okunuyor.) **Düzeltmedim** — o dosya benim kapsamımda değil.
2. **`yeni-acilan-bolumler-nasil-degerlendirilir.md`** havuzuna `VAKIF MYO`'yu dahil ediyor, ben etmedim (o havuzda önlisans MYO'ların lisans satırı yok denecek kadar az: kataloğun tamamında `VAKIF MYO` + `onlisans=0` = **0 satır** [D]). Yani iki yazı arasında sayısal çelişki doğmuyor; yalnızca filtre cümleleri farklı. Not olarak bırakıyorum.
3. **`veri_meta.kimlik_onar` kayıtları (30 satır):** aynı program kodunun ertesi yıl **bambaşka bir programa** verildiği vakalar (ör. `209210292`: "Diş Hekimliği" → "İlk ve Acil Yardım (İngilizce) (Burslu)"). Kod bazlı yıl-karşılaştırması yapan her yazı için sessiz bir hata kaynağı. Benim havuzumda etkisi ölçülebilir değil (30 satır / 10.534), ama veri tarafı için not: **bu satırlar "kontenjanı azaldı" listelerinde sahte devasa düşüş üretebilir.**
---
## 6. Engeller
1. `mevzuat.gov.tr` ve `resmigazete.gov.tr` WebFetch'te TLS hatası veriyor (`unable to verify the first certificate`) — editörün de yaşadığı engel. Kanun metnine doğrudan erişemedim; YÖK'ün kendi sayfasındaki md. 7 özeti kullanıldı, kaynak olarak o gösterildi.
2. ÖSYM'nin sayısal bilgiler dosyası PDF/Excel ve **dosya indirme yasak** → devlet lisans kontenjanındaki 9.012'lik farkın kaynağını bu gece çözemedim. Yazı bu yüzden ÖSYM toplamlarıyla kıyas yapmıyor.
3. Başka engel yok; DB salt okuma erişimi sorunsuz.
---
## Bilal'den istenen (3 madde)
1. **Tek cümlelik karar:** ÖSYM'nin 2026 **devlet lisans kontenjanı** (265.356) ile bizim örgün devlet lisans toplamımız (256.344) arasındaki 9.012'lik farkı veri ekibi araştırsın mı? Vakıf tarafı birebir tuttuğu için sorun muhtemelen devlet tarafında YÖK Atlas'ın satır kapsamında — kataloğun doğruluğunu etkileyebilir (**~2 dk karar**).
2. **Yayın öncesi 2 satır göz teyidi:** YÖK Atlas'ta Hacettepe Diş Hekimliği (kontenjan 90 → 81, taban 15.895 → 24.599) ve Sivas Cumhuriyet Hemşirelik (80 → 90, 191.920 → 151.729) — yazının "kontenjan tek başına belirlemez" argümanının iki dayanağı bunlar (**~5 dk**).
3. **`bos-kontenjanlar-ne-anlatiyor.md`'deki "birkaç yüz kişilik fark" cümlesini** editör düzeltsin mi? (Yukarıda §5.1; canlıdaki yazı, benim kapsamım dışında — **~1 dk karar**.)

View File

@@ -0,0 +1,296 @@
# 31 — Güvenlik & uyum: satıcı kimliği (A8), G3'ün delta-0 ledger satırı, iki kısa uyum kontrolü
> Rol: `guvenlik-uyum` · Gece vardiyası, 22 Eylül 2026 · Okuyucu: CTO (şartname eki) → CEO → sabah Bilal
> Yöntem: yalnız okuma. Kod okundu, **hiçbir kod/içerik dosyasına dokunulmadı**; bu rapor dışında dosya oluşturulmadı.
> Mevzuat kaynakları resmigazete.gov.tr'den **tam metin olarak indirildi ve okundu** — aşağıda madde madde alıntılı.
> İşaretler: **[D]** doğrulandı (dosya:satır / mevzuat metni) · **[Ç]** koddan çıkarım · **doğrulanmalı**
> Hukuki değerlendirme taslaktır: **avukat/mali müşavir teyidi gerekir.** Metin değişikliği her zaman `[BİLAL]`.
---
## Özet (5 madde)
1. **KRİTİK — Bu vardiyada yapılan işin bir kısmı çalışma ağacından silindi ve hiçbir commit'te yok.** Oturumumun başında `git status` dört dosyayı `M` gösteriyordu (`AGENTS.md`, `docs/ekip/KARARLAR.md`, `docs/ekip/BACKLOG.md`, `content/rehber/veliler-icin-tercih-rehberi.md`); rapor yazarken aynı dosyalar **temiz**, içerikleri HEAD'e dönmüş. `git reflog`'da `HEAD@{2}: reset: moving to HEAD~1` var [D] ve o resetin ardından hiçbir commit bu dosyalara dokunmuyor [D]. `git fsck --lost-found` içindeki dangling blob'ların hiçbirinde kayıp içerik yok [D] — yani **git'ten geri alınamaz**. Somut kayıp: KARARLAR.md'deki iki adet 22 Eylül karar kaydı, AGENTS.md'ye eklenen Search Console bölümü, veli yazısının yeni kapanışı + karşılaştırma tablosu, BACKLOG güncellemesi. İki karar kaydının **tam metni bu raporun §5 ekinde** duruyor (oturumumun ilk okumasından); diğerleri yeniden yazılmalı. Bu, CEO'nun aynı gece koyduğu C2 kuralının ve PROTOKOL md.3'ün ihlalidir.
2. **A8 için yeni sayfa GEREKMİYOR — mevzuat zaten yeri söylüyor: "iletişim" başlığı.** Yürürlükteki yönetmelik (RG 29.12.2022/32058, MADDE 5/1) satıcı kimliğini *"kendine ait elektronik ticaret ortamının ana sayfasında doğrudan ulaşılabilecek şekilde **'iletişim' başlığı altında**"* istiyor [D]. Bizde `/iletisim` sayfası var, başlığı zaten "İletişim" ve footer'dan her sayfada linkli (`src/components/site-footer.tsx:151-156`, ana sayfada `src/app/page.tsx:659`) [D]. Yani **tek iş: mevcut `/iletisim` sayfasına bir blok eklemek.** Kurucunun "sade" talimatına birebir uyuyor; `/hakkinda` benzeri yeni yüzey açmaya gerek yok.
3. **Bilal'in dolduracağı alan 5 — ama CEO'nun listesindeki alanlar tam olarak bunlar değil.** CEO "unvan, adres, vergi dairesi/no, MERSİS" demişti; yönetmelik **vergi dairesi adını istemiyor**, buna karşılık **telefon numarası ve KEP adresini zorunlu tutuyor** [D]. Ayıklanmış 5 alan: ① ticaret unvanı **veya** ad-soyad, ② merkez (iş yeri) adresi, ③ MERSİS no *(tacir)* **ya da** vergi kimlik no *(esnaf)* — tek alan, ④ telefon numarası, ⑤ KEP adresi. E-posta zaten var (`destek@kolaytercih.com`). Kopyalanmaya hazır metin §1.4'te, şahıs/şirket iki varyantıyla.
4. **G3'ün delta-0 satırı muhasebeyi de idempotency'yi de bozmuyor; tek gerçek risk iade dalı — ve orada sızıntı garanti.** `listeRevize` zaten `hasPaket` kapısının arkasında (`rapor-actions.ts:256`) olduğu için G3'ten sonra **her başarısız revizyon istisnasız 3 bedava kredi** yazar; `revisionCount` yalnız başarıda arttığı için MAX_REVIZYON tavanı, requestId her denemede tazelendiği için de UNIQUE kısıtı bu döngüyü durdurmaz [D]. Karar ve tek paragraflık gerekçe §2'de.
5. **Aynı mevzuat taramasında, satıcı kimliğinin yanında üç zorunluluk daha eksik çıktı** (hepsi grep = 0): "işlem rehberi" başlığı (Yön. m.7), **sipariş teyidi bildirimi** (Yön. m.9 — ödeme sonrası alıcıya e-posta/SMS **zorunlu**, bu T5'i "tetik"ten "yükümlülük"e taşır), ve ön bilgilendirmede cayma istisnası + tüketici hakem heyeti cümlesi (Mesafeli Sözleşmeler Yön. m.5/1-h ve -k). Ayrıca **ETBİS kaydı** faaliyete başlamadan önce zorunlu (Tebliğ m.5/1-a) [D]. Bunlar Bilal'e yeni soru üretmiyor — §1.5'te kime düştüğü yazılı.
---
## 0 · Kritik bulgu: çalışma ağacında veri kaybı (bu gece, benim oturumum sırasında)
### Kanıt
| Zaman | Gözlem | Kaynak |
|---|---|---|
| Oturum başı | `M AGENTS.md`, `M content/rehber/veliler-icin-tercih-rehberi.md`, `M docs/ekip/BACKLOG.md`, `M docs/ekip/KARARLAR.md` | Görev metnindeki `gitStatus` anlık görüntüsü |
| Oturum başı + ~2 dk | `tail -n 150 docs/ekip/KARARLAR.md` → dosyada **iki adet 22 Eylül kaydı** vardı | Bu oturumun ilk okuma çıktısı [D] |
| Rapor yazarken | `grep -c "^## 2026-09-22" docs/ekip/KARARLAR.md` = **0**; `git status --porcelain -uno` = **boş** | [D] |
| — | `git reflog`: `HEAD@{2}: reset: moving to HEAD~1` | [D] |
| — | Reset sonrası commit'lerin hiçbiri bu 4 dosyaya dokunmuyor (`git show --stat` × 8 commit) | [D] |
| — | `git fsck --lost-found`: 9 dangling nesne; AGENTS.md adayları **29 satır ve Search Console içermiyor**, KARARLAR adayları 21 Eylül'de bitiyor | [D] |
**Okuma [Ç]:** aynı çalışma ağacında çalışan kod ajanı `git reset --hard HEAD~1` (veya eşdeğeri) koştu. Untracked dosyalar (yeni rehber yazıları, `docs/gece-vardiyasi/`) sağ kaldı; **izlenen dosyalardaki commit'lenmemiş değişiklikler yandı.** Bu, kod ajanının kendi işini değil, başkasının işini sildi.
### Ne kaybedildi, ne kurtarılabilir
| Dosya | Kaybolan iş | Kurtarma |
|---|---|---|
| `docs/ekip/KARARLAR.md` | 2 adet 22 Eylül karar kaydı (sevk sırası P1–P5; `/sonuc` önizlemesi ve yeniden tasarımların ertelenmesi) | **Tam metin §5'te** — kopyala-yapıştır |
| `AGENTS.md` | Search Console bölümü (kota sayacı + sitemap kuralı) | `docs/gece-vardiyasi/2026-09-22/25-seo-duzeltme.md` §2 kuralın **gerekçesini ve iki ayağını** anlatıyor; metin oradan yeniden yazılabilir |
| `content/rehber/veliler-icin-tercih-rehberi.md` | Veli dilli kapanış + karşılaştırma tablosu (`grep "birlikte doldurmanız"` = 0, tabloya ait `^|` satırı = 0) | `21-yazar-veli-kapanisi.md` yalnız **özet + 1 alıntı cümle** taşıyor → **yazının kendisi yeniden yazılmalı** |
| `docs/ekip/BACKLOG.md` | 22 Eylül güncellemesi | `urun-yoneticisi`'nin backlog senkronu turunda (D-13) yeniden üretilir |
### Öneri (yeni Bilal maddesi değil; süreç maddesi)
- **Şimdi:** §5'teki iki karar kaydı KARARLAR.md'ye geri yapıştırılsın (sahibi `ceo`/orkestratör).
- **Bu gece:** C2 kuralına tek cümle eklensin → *"Kod ajanı `git reset --hard`, `git checkout -- <yol>`, `git clean`, `git stash` kullanamaz; dal değiştirmesi gerekiyorsa önce `git status -uno` boş olmalıdır."* Mevcut C2 "dokunma" diyor ama **dokunmadan da silinebileceğini** söylemiyor; bu gece tam olarak o oldu.
- **Kalıcı:** gece vardiyasında `docs/` ve `content/` yazan ajanlar işlerini **commit'siz bırakmasın**; en azından `git stash create` değil, kendi dalında lokal commit. (Untracked dosyalar bu geceki resetten sağ çıktı — kayıp yalnız izlenen dosyalarda oldu.)
---
## 1 · Görev 1 — Satıcı kimliği (A8)
### 1.1 Mevzuat: neyi kim zorunlu tutuyor (resmî metinden)
**Kaynak A — Elektronik Ticaret Aracı Hizmet Sağlayıcı ve Elektronik Ticaret Hizmet Sağlayıcılar Hakkında Yönetmelik**, Ticaret Bakanlığı, **RG 29.12.2022 / 32058** [D — tam metin indirildi]. *Not: 2015 tarihli eski yönetmelik bu metnin **MADDE 34** ile yürürlükten kaldırılmıştır [D]; internette dolaşan "2015 yönetmeliği" özetleri artık geçersiz.*
> **MADDE 5- (1)** ETHS, kendine ait elektronik ticaret ortamının ana sayfasında doğrudan ulaşılabilecek şekilde **"iletişim" başlığı altında** aşağıdaki bilgileri eksiksiz olarak bulundurur:
> a) **Tacir için** ticaret unvanı, MERSİS numarası ve merkez adresi; **esnaf ve sanatkâr için** adı ve soyadı, vergi kimlik numarası ve merkez adresi.
> b) **KEP adresi, elektronik posta adresi, telefon numarası** ve varsa işletme adı ile tescilli markası.
> c) Mensubu olduğu meslek odası, meslekle ilgili davranış kuralları ve bunlara elektronik olarak ne şekilde ulaşılabileceğine ilişkin bilgiler.
ETHS tanımı (m.4/h): *"…**kendine ait elektronik ticaret ortamında** mal veya hizmetlerinin teminine yönelik sözleşme yapan ya da sipariş alan hizmet sağlayıcı"* → KolayTercih birebir bu [D]. Kapsam dışı sayılanlar listesi (m.2/2) bankalar, sigorta, şans oyunları vb.; bizi kapsam dışına çıkaran bir istisna **yok** [D].
**Kaynak B — Mesafeli Sözleşmeler Yönetmeliği**, **RG 27.11.2014 / 29188**, MADDE 5 (ön bilgilendirme) [D — tam metin indirildi]. Sözleşme kurulmadan önce **tamamı** verilmek zorunda olanlardan bizde eksik olanlar:
| Bent | Zorunlu bilgi | Bizde |
|---|---|---|
| a | Mal/hizmetin temel nitelikleri | **var** (`/kosullar` "Hizmetin kapsamı", `/paket`) |
| **b** | **Satıcı/sağlayıcının adı veya unvanı, varsa MERSİS numarası** | **YOK** (grep = 0) |
| **c** | **Açık adres, telefon numarası ve benzeri iletişim bilgileri** | **kısmen** — yalnız e-posta (`src/app/iletisim/page.tsx:26-33`) |
| ç | Şikâyet için farklı iletişim bilgisi varsa | yok (gerek de yok, aynı adres) |
| **d** | **Tüm vergiler dâhil toplam fiyat** | fiyat var, **"KDV dâhil" ibaresi yok** (grep `kdv` = 0) |
| f | Ödeme/ifa bilgileri | var |
| g | Cayma hakkının şartları, süresi, usulü | var (`/kosullar#iade`) |
| ğ | Cayma bildiriminin yapılacağı açık adres/e-posta | e-posta var, adres yok |
| **h** | **m.15 uyarınca cayma hakkının kullanılamadığı hâllerde bu bilgi** | **YOK** |
| **k** | **Tüketici Hakem Heyeti / Tüketici Mahkemesine başvurabileceği bilgisi** | **YOK** |
m.15/1 ilgili bentleri [D]: *"ğ) Elektronik ortamda anında ifa edilen hizmetler veya tüketiciye anında teslim edilen gayrimaddi mallara ilişkin sözleşmeler"* ve *"h) Cayma hakkı süresi sona ermeden önce, tüketicinin onayı ile ifasına başlanan hizmetlere ilişkin sözleşmeler"*. Yani **hukuken cayma hakkı vermek zorunda değiliz**; `/kosullar`'daki 14 günlük koşulsuz iade mevzuatın üstünde, gönüllü bir taahhüt — iyi, korunmalı. Ama **"kanunen cayma hakkın yok, buna rağmen biz 14 gün veriyoruz"** cümlesinin yazılması m.5/1-h gereği zorunlu.
**Kaynak C — Elektronik Ticaret Bilgi Sistemi ve Bildirim Yükümlülükleri Hakkında Tebliğ**, **RG 11.08.2017 / 30151**, MADDE 5/1 [D]:
> *"(1) Aşağıda belirtilen gerçek veya tüzel kişiler **faaliyete başlamadan önce ETBİS'e kayıt olur**: a) **Kendilerine ait elektronik ticaret ortamında faaliyet gösteren hizmet sağlayıcılar.** …"* — kayıt için girilen bilgi: *"Gerçek veya tüzel kişi tacirler için MERSİS numarası ve vergi kimlik numarası, esnaf ve sanatkârlar için T.C. kimlik numarası ve vergi kimlik numarası"* + alan adı.
→ **KolayTercih ödeme alıyor ve ETBİS kaydı gerektiren tarife birebir uyuyor.** Tebliğin sonraki değişiklikleri **doğrulanmalı** (2017 metni okundu; 2022–2023 e-ticaret paketinden sonra güncellenmiş olabilir). Sitede gösterilmesi gereken bir "ETBİS rozeti/bandı" yükümlülüğü **bu metinde yok** — uydurmuyorum, aramada çıkmadı [D].
### 1.2 Şahıs mı şirket mi — hangi alan değişir
Mevzuat "şahıs/şirket" değil **tacir / esnaf-sanatkâr** ayrımı yapıyor. Pratik karşılığı:
| Durum | ①Kim | ②Adres | ③Numara | ④Telefon | ⑤KEP | Meslek odası (m.5/1-c) |
|---|---|---|---|---|---|---|
| **Şahıs işletmesi — esnaf ve sanatkâr** (esnaf odasına kayıtlı) | **Ad ve soyad** | İş yeri (merkez) adresi | **Vergi kimlik numarası** | zorunlu | zorunlu | Esnaf ve sanatkârlar odası adı |
| **Şahıs işletmesi — tacir** (ticaret siciline kayıtlı) | **Ticaret unvanı** (ör. "Bilal Gürşen — KolayTercih") | Ticaret siciline tescilli merkez adresi | **MERSİS numarası** | zorunlu | zorunlu | Ticaret odası adı |
| **Limited / anonim şirket** | **Ticaret unvanı** (…Ltd. Şti.) | Tescilli merkez adresi | **MERSİS numarası** | zorunlu | zorunlu | Ticaret odası adı |
| **Hiç kaydı olmayan gerçek kişi** | — | — | — | — | — | — |
**Son satır hakkında uyarı:** 2022 yönetmeliğinin m.5/1'inde — 2015'teki hâlinin aksine — *kendi sitesinde satış yapan* "tacir veya esnaf olmayan" hizmet sağlayıcı için bir fıkra **yok** [D]; süreklilik arz eden, kazanç amaçlı satış zaten ticari faaliyet sayıldığı için vergi mükellefiyeti doğurur. Yani "hiçbir kaydı olmayan gerçek kişi olarak satmaya devam etmek" mevzuatın öngördüğü bir seçenek değil. **Mali müşavir teyidi gerekir** — bu cümle hukuki görüş değil, metinden okunan bir boşluk tespitidir.
**Pratik sonuç:** üç geçerli durumda da **alan sayısı 5** ve yalnız ①/③ değişiyor. Bu yüzden aşağıdaki taslak tek metin; Bilal hangi satırı yazacağını `TODO-BILAL` notundan seçiyor.
### 1.3 Nereye konacak — yeni sayfa gerekmiyor
| Ne | Nereye | Neden |
|---|---|---|
| **Satıcı kimliği bloğu (5 alan)** | **`src/app/iletisim/page.tsx`** — mevcut `<h1>İletişim</h1>`'in altına, e-posta butonunun **altına**, "Kart bilgini asla e-postayla paylaşma" notunun üstüne | Yönetmelik m.5/1 bilgileri **"iletişim" başlığı altında** istiyor; sayfa zaten bu adı taşıyor ve `SiteFooter` sayesinde **ana sayfa dâhil 12 sayfada** doğrudan linkli (`site-footer.tsx:151-156`, `page.tsx:659`) [D]. Yeni sayfa açmak hem gereksiz hem de mevzuatın istediği başlıktan uzaklaştırır |
| **`/kosullar`'a 3 cümle** | `src/app/kosullar/page.tsx` — "Ücretlendirme" bölümünün sonuna 1 cümle, "İade ve cayma" bölümünün başına 2 cümle | Mesafeli Sözleşmeler Yön. m.5/1-b, -d, -h, -k boşlukları. Yeni bölüm bile değil, mevcut `<section>`'ların içine cümle |
| **Footer** | **değişiklik gerekmiyor** | "İletişim" linki zaten her sayfada, `Yasal sayfalar` nav'ında (`site-footer.tsx:151-156`) [D] |
| **Gizlilik** | `src/app/gizlilik/page.tsx` — "Hangi verileri işliyoruz?" bölümünün başına 1 cümle | KVKK aydınlatmasında **veri sorumlusunun kimliği** bulunmak zorundadır; bugün gizlilik metni de veri sorumlusunu adlandırmıyor [D]. Aynı 5 alandan besleniyor, ek bilgi istemiyor |
### 1.4 Kopyalanmaya hazır metin
> Yazılımcıya not: bunlar **düz metin**tir. `/iletisim` ve `/kosullar` sayfalarındaki mevcut `<section>` + `<h2 className="font-heading text-lg font-bold text-slate-900">` desenini kullan; yeni bileşen, yeni badge, yeni kart tasarlama. Tarih satırı `/kosullar`'daki "Son güncelleme" satırıyla aynı biçimde.
#### (A) `/iletisim` — yeni bölüm: "Satıcı bilgileri"
```
Satıcı bilgileri
Unvan: TODO-BILAL: Ticaret unvanın (ör. "Bilal Gürşen — KolayTercih"); şirket değil de esnaf/sanatkâr olarak kayıtlıysan ad ve soyadın
Adres: TODO-BILAL: İş yeri (merkez) adresin — mahalle/cadde/no, ilçe, il, posta kodu
TODO-BILAL: Tacirsen "MERSİS No: ……" satırı; esnaf ve sanatkârsan "Vergi Kimlik No: ……" satırı (yalnız biri yazılır)
Telefon: TODO-BILAL: Alıcının sana ulaşabileceği telefon numarası
KEP adresi: TODO-BILAL: Tebligata elverişli KEP adresin (PTT'den alınır)
E-posta: destek@kolaytercih.com
Bu sayfadaki bilgiler, 29/12/2022 tarihli ve 32058 sayılı Resmî Gazete'de yayımlanan
Elektronik Ticaret Aracı Hizmet Sağlayıcı ve Elektronik Ticaret Hizmet Sağlayıcılar
Hakkında Yönetmelik uyarınca yayımlanmaktadır.
```
**Alan sayısı: 5.** (E-posta zaten kodda, mevzuat atfı sabit.)
Ayıklananlar ve gerekçeleri: *vergi dairesi adı* → yönetmelik VKN istiyor, daire adını istemiyor, piyasa alışkanlığı; *işletme adı / tescilli marka* → "varsa" (m.5/1-b), tescil yoksa yazılmaz, `marka` ajanının A9 raporu sonuçlanınca bakılır; *meslek odası* → kayıt olunan odaya göre tek satır, Bilal ③'ü yazarken aynı belgeden okuyacağı için ayrı soru sayılmadı; **yazılırsa** "Meslek odası: …" satırı aynı bloğun sonuna eklenir.
#### (B) `/kosullar` → "Ücretlendirme" bölümünün sonuna eklenecek cümle
```
Satıcı bilgileri (unvan, adres, vergi/MERSİS numarası ve iletişim) iletişim sayfasında
yer alır. Paket fiyatı, tüm vergiler dâhil toplam bedeldir.
```
*("iletişim sayfasında" ifadesi `/iletisim`'e link olacak — `/kosullar`'daki mevcut `<Link className="text-primary underline">` deseniyle.)*
#### (C) `/kosullar` → "İade ve cayma" bölümünün **başına** eklenecek iki cümle
```
Paket, elektronik ortamda anında ifa edilen bir hizmettir; Mesafeli Sözleşmeler
Yönetmeliği'nin 15 inci maddesi uyarınca bu tür sözleşmelerde kanunen cayma hakkı
bulunmaz. Buna rağmen aşağıdaki koşullarda 14 günlük koşulsuz iade hakkını kendi
irademizle tanıyoruz.
```
#### (D) `/kosullar` → en sona eklenecek yeni bölüm (tek cümle)
```
Uyuşmazlık hâlinde
Satın alımından doğan uyuşmazlıklarda, parasal sınırlara göre yerleşim yerindeki
Tüketici Hakem Heyetine veya Tüketici Mahkemesine başvurabilirsin.
```
#### (E) `/gizlilik` → "Hangi verileri işliyoruz?" paragrafının **başına** eklenecek cümle
```
Bu metindeki işlemler bakımından veri sorumlusu, iletişim sayfasında unvanı ve adresi
yayımlanan KolayTercih satıcısıdır.
```
> Böylece Bilal'in doldurduğu 5 alan **tek yerde** duruyor; diğer üç sayfa ona atıf yapıyor. Bilgi değişirse tek dosya güncelleniyor (yönetmelik m.5/5: değişiklikler değişikliğin olduğu gün güncellenir — tek kaynak bunu da kolaylaştırıyor).
### 1.5 Aynı taramada çıkan, Bilal'e soru üretmeyen zorunluluklar
| Ne | Mevzuat | Bugün | Kime |
|---|---|---|---|
| **"İşlem rehberi" başlığı** — sözleşmenin kurulması için teknik adımlar, sözleşmenin saklanıp saklanmayacağı, hata düzeltme araçları, varsa alternatif uyuşmazlık çözümü | Yön. **m.7/1**, ana sayfadan doğrudan ulaşılabilir "işlem rehberi" başlığı altında [D] | grep `işlem rehberi` = **0** | `cto` → `yazilimci`. `/kosullar`'a üçüncü bir bölüm olarak yazılabilir, **yeni sayfa gerekmez**; içerik hazır: sıralama → sihirbaz → giriş → paket → iyzico |
| **Sipariş teyidi** — "siparişi aldığını, ortam üzerinden **ve ayrıca** e-posta, SMS veya telefondan en az biriyle gecikmeksizin alıcıya bildirir" | Yön. **m.9/1** [D] | `/odeme/sonuc` ekranı var ama **alıcıya e-posta yok** (`src/lib/eposta.ts` yalnız magic-link + kredi hatırlatma) [D] | **T5'in sınıfı değişiyor:** "test ödemesi başarılı olursa" tetiği değil, **mevcut yükümlülük**. T5 zaten satıcı kimliği satırlarıyla aynı commit'e bağlıydı → sırası doğru, adı düzeltilmeli |
| **Sözleşme şartlarının alıcıya kalıcı biçimde verilmesi** (basılabilir/saklanabilir) | Yön. **m.8/1-d** [D] | Yok | Aynı e-posta ile kapanır (paket adı + tutar + tarih + `/kosullar` özeti) |
| **ETBİS kaydı** | Tebliğ **m.5/1-a**: faaliyete başlamadan önce [D] | Durum bilinmiyor — koddan görülemez | Bilal'in tek maddesiyle **aynı zincir** (kayıt olmadan ③ numarası zaten yazılamaz). Ayrı madde açılmadı |
---
## 2 · Görev 2 — G3'ün delta-0 ledger satırı
**Değerlendirme (tek paragraf).** Tutarı 0 olan ledger satırı ne mutabakatı ne bakiyeyi bozar: bakiye hiçbir yerde defterden toplanmıyor, tek kaynağı `user.credit_balance` kolonu (`src/lib/credits.ts:56-72`; `grep -rn delta src scripts` → defteri toplayan tek bir okuyucu yok) [D]; haftalık iyzico mutabakat sorgusu ise yalnız `reason IN ('purchase','topup')` ve `ref_id = orders.id` üzerinden çalışıyor (`docs/odeme/iyzico.md:82-88`) [D] — `report_generate` satırının `refId`'si istemcinin ürettiği `requestId` olduğu için bu sorguya hiç girmez, yani 0 TL'lik hareket iyzico tarafında görünmez bile. Idempotency de yerinde kalır: UNIQUE indeks `ledger_reason_ref` **`(reason, ref_id)`** üzerindedir, `delta` üzerinde değil (`src/lib/appdb/schema.ts:131`) [D]; `amount = 0` iken de satır aynı `refId` ile yazıldığından ikinci çağrı yine `DUPLICATE` döner ve `rapor-actions.ts:168-205`'teki "iade edilmiş / mevcut rapor / hâlâ uçuşta" üçlü dalı aynen çalışır; `spendCredits`'in `WHERE creditBalance >= 0` koşulu da paketli kullanıcı kredisi sıfırken geçer, yani `INSUFFICIENT` yanlış alarmı olmaz [Ç — bakiyenin negatife düşebildiği tek yol yok; tüm harcama yolları `gte` ile korunuyor]. **Sorun tek yerde:** iade dalı koşullanmazsa `grantCredits({ delta: RAPOR_KREDI, reason: "refund" })` paketliye **gerçek** 3 kredi basar (`rapor-actions.ts:212-218` ve `:339-345`), ve `listeRevize` zaten `hasPaket` kapısının arkasında olduğu için (`:256`) G3'ten sonra **her başarısız revizyon istisnasız bedava 3 kredi** demektir; `revisionCount` yalnız başarılı üretimde arttığından (`:344-352`) MAX_REVIZYON=2 tavanı döngüyü durdurmaz, `requestId` her denemede tazelendiğinden UNIQUE de durdurmaz — ve G3'ten sonra krediler yalnız sohbete gideceği için bu doğrudan "başkasının parasıyla LLM çağırma" bütçesine dönüşür. Başarısızlık ayrıca tamamen şansa bağlı değil: revizyon geri bildirimi serbest metin ve prompt'a giriyor, model iki denemede de dilim sayılarını tutturamazsa `RaporUretimHatasi` fırlıyor (`src/lib/ai/rapor.ts:338-345`) [Ç — kullanıcı yönlendirmeli başarısızlık **OLASI**, sağlayıcı kaynaklı başarısızlık ise **DOĞRULANDI** biçimde aynı dala düşüyor].
**KARAR: "şu koşulla sorun yok."** Koşul üç satır:
1. İade dalı aynı koşula bağlanır: `delta: hasPaket ? 0 : RAPOR_KREDI` (her iki `grantCredits` çağrısı — `rapor-actions.ts:212-218`, `:339-345`). Çağrı yine **kaldırılmaz**; `refund` satırı `refId` ile yazılmaya devam etsin ki `:168-180` ve `:298-312`'deki "önceki deneme iade edilmişti" dalı çalışmaya devam etsin.
2. Dönüş değerindeki bakiye de koşullanır: `kredi: user.creditBalance - RAPOR_KREDI` (`:243` ve `:363`) → `- (hasPaket ? 0 : RAPOR_KREDI)`. Yoksa paketlinin bakiyesi ekranda **3 eksik** görünür; kullanıcı "kredim yandı" diye destek yazar. (Sızıntı değil, görüntü hatası — ama G3'ün tüm vaadi "kredin yanmıyor" olduğu için tam da yanlış yerde bir hata.)
3. `hasPaket` değeri **tek yerden**, zaten okunmuş `user` nesnesinden alınsın (`listeOlusturKilitli`'ye `user` geliyor, `listeRevize`'de `user.hasPaket` kapısı var) — ikinci bir DB okuması eklenmesin; aksi hâlde harcama ile iade farklı `hasPaket` görebilir.
**Ek not (kapsam dışı, kayda geçsin):** G3 sonrası paketli kullanıcı için `krediBittiIsaretle` hiç tetiklenmez (`INSUFFICIENT` dönmez) — bu **doğru** davranış, kredi hatırlatma e-postası paketliye gitmemeli. `/api/soru` tarafı (sohbet, 1 kredi) G3'ten etkilenmiyor ve etkilenmemeli [D].
---
## 3 · Görev 3 — İki kısa uyum kontrolü
**(a) Veli yazısının kapanışı.** KVKK ve ticari ileti açısından **hiçbir şey değişmiyor**: metin yeni bir veri alanı toplamıyor, yeni form/izin kutusu eklemiyor, e-posta adresi istemiyor; altındaki `CtaSiraForm` zaten var olan bileşen ve sıralama girişi gizlilik metninde hâlihazırda beyan edilmiş bir veri kategorisi (`src/app/gizlilik/page.tsx:39-46`) [D]. — *Ama:* §0'da anlatıldığı üzere **bu değişiklik şu an çalışma ağacında yok**; `grep "birlikte doldurmanız"` = 0, tablo satırı = 0 [D]. Uyum açısından temiz, ama iş kayıp.
**(b) Search Console kuralının Bilal'in Google oturumunu kullanması.** İki ayrı soru:
- **KVKK/veri:** Search Console'da kişisel veri yok (URL'ler, toplulaştırılmış sorgu/gösterim verisi). Kullanıcı verisi dışarı çıkmıyor. **Uyum sorunu yok.**
- **Güvenlik:** sorun var, ama düşündüğümüz yerde değil. Ajanın kullandığı oturum Bilal'in **kişisel Google hesabı**; aynı tarayıcı oturumundan Gmail, Drive ve Google hesabı ayarları da erişilebilir durumda. PROTOKOL md.5 açıkça *"Kullanıcının açık oturumlarına (Gmail vb.) girme"* diyor [D] — yani kural, korumayı **ajanın kendini tutmasına** bırakıyor; teknik bir sınır yok. Bir yanlış sekme, bir prompt enjeksiyonu (SC arayüzünde değil ama aynı profilde açılan herhangi bir sayfada) ya da bir "yardımcı olayım" refleksi kapsamı e-posta kutusuna taşır. **Önem: orta.**
**Öneri (tek satır, yeni Bilal maddesi değil — zaten E3'ün içinde):** CEO'nun C4'teki çözümü "birinci hesabı mülke tam yetkili ekle" — bu hesap değiştirme sürtünmesini çözüyor ama **yetki genişliği sorununu çözmüyor**. Aynı 2 dakikada yapılabilecek daha iyisi: mülke **ajanın kullanacağı, Gmail'i olmayan ayrı bir Google hesabı** "tam yetkili kullanıcı" olarak eklensin; ajan yalnız o profille çalışsın. Bilal'in kişisel hesabı mülkün sahibi olarak kalır.
- **Ayrıca:** kuralın kendisi şu an `AGENTS.md`'de **yok** (§0). Yani bu gece "kapandı" sayılan C4 maddesinin üçte ikisi kayıp.
---
## 4 · Bulgu tablosu
Önem: **kritik** = para/veri kaybı ya da hemen istismar edilebilir · **yüksek** = mevzuat ihlali / gelir sızıntısı · **orta/düşük** = düzeltilmeli, acil değil.
Kesinlik: **DOĞRULANDI** = dosya:satır ya da mevzuat metniyle gösterildi · **OLASI** = koddan çıkarım, koşturarak denenmedi.
| # | Dosya:satır / kaynak | Sorun | Somut istismar / ihlal senaryosu | Önem | Düzeltme | Kesinlik |
|---|---|---|---|---|---|---|
| **B1** | `git reflog HEAD@{2}` · `docs/ekip/KARARLAR.md` · `AGENTS.md` · `content/rehber/veliler-icin-tercih-rehberi.md` | Aynı çalışma ağacındaki kod ajanı `reset` ile commit'lenmemiş değişiklikleri sildi; hiçbir commit'te ve dangling nesnede yok | Gece vardiyasında üretilen karar kayıtları, kural metni ve bir yazının yeniden yazımı kayboldu; kayıp fark edilmeden sabah özeti "kapandı" diyecekti | **kritik** | §5'teki iki karar kaydı geri yapıştırılsın; C2'ye "reset/checkout/clean/stash yasak" cümlesi eklensin; `docs/`+`content/` ajanları lokal commit atsın | DOĞRULANDI |
| **B2** | `src/features/rapor/rapor-actions.ts:212-218` ve `:339-345` (G3 sonrası) | İade dalı `hasPaket` koşuluna bağlanmazsa, harcaması 0 olan paketliye 3 **gerçek** kredi yazılır | Paketli kullanıcı revizyon isteğini modelin iki denemede de doğrulayamayacağı biçimde yazar → `RaporUretimHatasi` → +3 kredi; `revisionCount` başarısızlıkta artmadığı ve `requestId` her denemede tazelendiği için döngü sınırsız; krediler sohbete gidince başkasının parasıyla LLM çağrılır | **yüksek** | `delta: hasPaket ? 0 : RAPOR_KREDI` (çağrı kaldırılmaz) | DOĞRULANDI (kod) / OLASI (kullanıcı yönlendirmeli başarısızlık oranı) |
| **B3** | `rapor-actions.ts:243` ve `:363` | Dönen `kredi` alanı koşulsuz `- RAPOR_KREDI` | Paketli kullanıcı liste üretince ekranda bakiyesini 3 eksik görür; G3'ün tüm vaadi "kredin yanmıyor" olduğu için tam ters mesaj + destek yükü | orta | `- (hasPaket ? 0 : RAPOR_KREDI)` | DOĞRULANDI |
| **B4** | `src/app/iletisim/page.tsx` (tamamı) · grep `mersis\|vergi kimlik\|ticaret unvan\|KEP` = **0** | Satıcı kimliği sitenin hiçbir yerinde yok | Yön. (RG 32058) m.5/1 ihlali: ödeme alan bir ETHS, "iletişim" başlığı altında unvan/adres/numara/telefon/KEP bulundurmak zorunda. Aynı eksik Mesafeli Sözleşmeler Yön. m.5/1-b ve -c'yi de ihlal ediyor → tüketici şikâyetinde ön bilgilendirme yapılmamış sayılır | **yüksek** | §1.4 (A) + (B) | DOĞRULANDI |
| **B5** | `src/lib/eposta.ts` (yalnız 2 şablon) · `src/lib/odeme.ts:78-82` | Alıcıya sipariş teyidi gönderilmiyor | Yön. m.9/1: sipariş alındığı, ortam üzerinden **ve ayrıca** e-posta/SMS/telefondan bildirilmek zorunda. Bugün alıcı ödediğine dair elinde tek bir kayıt olmadan kalıyor; itiraz/chargeback'te satıcı tarafında delil de yok | **yüksek** | T5 e-postası (satıcı kimliği satırları + tutar + tarih + `/kosullar` özeti — m.8/1-d'yi de kapatır) | DOĞRULANDI |
| **B6** | `src/app/kosullar/page.tsx:61-83` | Cayma hakkının kanunen bulunmadığı bilgisi yok | Mesafeli Sözleşmeler Yön. m.5/1-h ihlali. Ters yönde de zararlı: 14 günlük gönüllü iadeyi "kanuni hak" sanan kullanıcı, kapsam dışı bir talepte reddedilince haksızlığa uğradığını düşünür | orta | §1.4 (C) | DOĞRULANDI |
| **B7** | `src/app/kosullar/page.tsx` (tamamı) | Tüketici hakem heyeti / mahkeme başvuru bilgisi yok | Mesafeli Sözleşmeler Yön. m.5/1-k ihlali | orta | §1.4 (D) | DOĞRULANDI |
| **B8** | grep `işlem rehberi` = 0 | "İşlem rehberi" başlığı yok | Yön. m.7/1 ihlali: teknik adımlar, sözleşmenin saklanıp saklanmayacağı, hata düzeltme araçları ana sayfadan ulaşılabilir olmalı | orta | `/kosullar`'a üçüncü bölüm (yeni sayfa değil) | DOĞRULANDI |
| **B9** | grep `kdv\|vergiler dahil` = 0 · `paket-satinal.tsx:67,167` | Fiyatın vergiler dâhil olduğu yazmıyor | Mesafeli Sözleşmeler Yön. m.5/1-d: toplam fiyat **tüm vergiler dâhil** bildirilmeli | düşük | §1.4 (B)'deki ikinci cümle | DOĞRULANDI |
| **B10** | `src/app/gizlilik/page.tsx:35-47` | Aydınlatma metninde veri sorumlusunun kimliği yok | KVKK aydınlatma yükümlülüğü, veri sorumlusunun kimliğinin bildirilmesini içerir; ayrıca veri silme talebinin **kime** yapılacağı da belirsiz kalıyor | orta | §1.4 (E) | DOĞRULANDI |
| **B11** | ETBİS Tebliği m.5/1-a · koddan görülemez | ETBİS kaydının varlığı bilinmiyor | Kendine ait e-ticaret ortamında **faaliyete başlamadan önce** kayıt zorunlu; kayıtsız satış idari yaptırım riski | **yüksek** | Bilal'in tek maddesiyle aynı zincir (kayıt olmadan MERSİS/VKN satırı zaten yazılamaz) | DOĞRULANDI (yükümlülük) / bilinmiyor (bizim durumumuz) |
| **B12** | PROTOKOL md.5 · `24-ceo-kapanis.md` §C4 | Search Console işi Bilal'in kişisel Google oturumundan yürüyor | Ajan, mülke erişmek için açılan oturumdan Gmail/Drive'a da erişebilir durumda; teknik sınır yok, yalnız kural var | orta | Mülke Gmail'i olmayan ayrı bir hesap "tam yetkili" eklensin; ajan yalnız o profille çalışsın | DOĞRULANDI (yapılandırma) |
---
## 5 · Metin × kod uyumsuzlukları
| Metin ne diyor | Kod / gerçek ne | Nerede |
|---|---|---|
| `/kosullar`: *"Tercih Dönemi Paketi tek seferlik bir satın almadır"* | Paket etiketi A2 ile **"KolayTercih Paketi"** (ya da `marka`'nın önerdiği "Tercih Listesi Paketi") olacak; `/kosullar` metni eski adı yazmaya devam ediyor | `src/app/kosullar/page.tsx:50-57` × `src/lib/credits.ts:7` + `24-ceo-kapanis.md` A2 · **A2 commit'ine `/kosullar` de dâhil edilmeli** |
| `/kosullar`: *"14 gün içinde koşulsuz iade talep edebilirsin"* — kanuni hak gibi okunuyor | Kanunen cayma hakkı **yok** (Mesafeli Söz. Yön. m.15/1-ğ,h); bu gönüllü bir taahhüt | B6 |
| `/gizlilik`: *"sana hizmetle ilgili e-posta (giriş bağlantısı, **ödeme bilgilendirmesi**) göndermek"* | Ödeme bilgilendirmesi e-postası **yok**; `src/lib/eposta.ts` yalnız magic-link ve kredi hatırlatma taşıyor | B5. Metin var olmayan bir gönderimi beyan ediyor — T5 yapılınca uyum kendiliğinden kurulur |
| `/iletisim`: *"Ödeme, iade, **hesap silme** ya da başka bir konuda"* | Hesap silme yolu var (e-posta), ama talebin **muhatabı** kim olduğu (veri sorumlusu) hiçbir yerde yazmıyor | B10 |
| `/kosullar` üstündeki kod yorumu: *"MVP taslağıdır; yayına almadan önce hukuki gözden geçirme gerekir"* | Hukukçu tutulmayacağı **karara bağlandı** (KARARLAR 2026-09-21). Yorum, var olmayan bir kapıya işaret ediyor | `src/app/kosullar/page.tsx:15`. Metin düzeltilirken yorum da güncellenmeli: *"içeride sürdürülür; son revizyon: …"* |
| `24-ceo-kapanis.md` T5: makbuz e-postası **tetiğe** bağlı ("test ödemesi başarılı olursa") | Yön. m.9/1 bunu **yürürlükteki yükümlülük** kılıyor; tetik değil | B5 |
---
## Ek · Kaybolan KARARLAR.md kayıtlarının tam metni (§0 kurtarma)
> Bu iki blok, oturumumun ilk okumasında `docs/ekip/KARARLAR.md`'nin sonunda duruyordu ve şu an dosyada yok. Olduğu gibi dosyanın **sonuna** geri yapıştırılabilir. Sahibi `ceo`; ben dosyaya yazmadım.
```
## 2026-09-22 — Sevk sorunu: sıra "önce çelişkiyi kaldır, sonra ölü ucu bağla", yeniden tasarım ertelendi
- Karar: 22 Eyl gündüz oturumunda dört ajanın (analitik/tasarım/marka/yapay zekâ) tek soruya verdiği dört farklı "en yüksek etkili iş" önerisi şu sıraya kondu ve bu hafta **5 iş** onaylandı: **P1** sezon çelişkisi (`icerik/sezon-celiskisi`), **P2** `liste_uretim_basladi` olayı (`olcum/liste-uretim-basladi`), **P3** + ölü ucu (`funnel/arti-olu-ucu`), **P4** girişli kullanıcıya kalıcı `/listem` girişi + giriş callback'i (`funnel/listem-girisi`), **P5** tadımlık CTA'sının yanlış vaadi ve hedefi (`icerik/tadimlik-vaat`). Hepsi S; P2 önce merge edilir ve P3/P4 ile **aynı yayında** çıkar (payda olmadan huni değişikliği okunamaz). Sezon dışı olduğu için A/B yok, oran yok: kabul ölçüsü **adet** (haftalık olay sayısı).
- Yetki: [KARAR] (P2, P3, P4; P1 ve P5'in yanlış/çelişkili cümleyi kaldıran kısmı) · [BİLAL] (P1'de bandın yeni sezon metni, P5'te tadımlık CTA'sının yeni cümlesi — ayrı `[Bilal]` commit'i olarak hazırlanır)
- Gerekçe: Dört iddia da koddan doğrulandı — navbar'da `/listem` linki yok ve giriş callback'i `"/"` (`src/components/site-header.tsx:8-38`, `src/features/kullanici/components/user-nav.tsx:45-64`, `src/features/kullanici/components/giris-karti.tsx:18-19`); + kapısı sihirbazın 3 adımını doldurtup `profilTamamlandi`'nın `null` dalında bırakıyor (`src/features/liste/components/program-ekle-butonu.tsx:82`, `liste-cekmecesi.tsx:293`, `use-tercih-profili.ts:346`, toast `tercih-profili-kapisi.tsx:238`) ve bu, 30g'deki en büyük sıra kaynağı (14/28 olay, `01-ai-listesi-hunisi` §1d); üst bant bugün "Tercih dönemi sona erdi" (`src/components/site-top-banner.tsx:7-8,64`) derken aynı sayfada CTA "Tercih dönemi bitmeden yerini al" diyor (`src/features/pazarlama/components/hero-focus-button.tsx:45,65` — her iki dalda da); tadımlık CTA'sı "24 satırın tamamı için giriş yap" diyor ama maske 3 satır açıyor ve callback `/sonuc`'a düşüyor (`tadimlik-satiri.tsx:111,186`, `src/lib/rapor-maske.ts:12`).
- Yerine geçtiği karar: —
## 2026-09-22 — `/sonuc`'ta LLM'siz 24 satırlık önizleme ve diğer yeniden tasarımlar bu hafta yapılmaz
- Karar: Yapay zekâ mühendisinin "senin 24'lük iskeletin" önizlemesi (0 LLM, `04-uretim-engelleri` §3), tasarımcının Ö2 (mobil katalog satırı), Ö4 (`/sonuc` sıralamasının tersine çevrilmesi) ve markanın H2/H3 (hero alt başlığı, katalog CTA metni) işleri **ertelendi**; sıradaki turda önce CTO şartnamesi yazılır. Ertelemeyen tek istisna `/sonuc` H1'i (`src/app/sonuc/page.tsx:98-102` arasında bugün hiç `<h1>` yok) — gelecek turun ilk işidir. Deneme maskesinin gevşetilmesi (3→8 satır) gelir modeli kararıdır, Bilal'e bırakıldı.
- Yetki: [KARAR] (erteleme) · [BİLAL] (maske/gelir kararı)
- Gerekçe: Sezon 10 Ağu 2026'da kapandı; hız ~95 ziyaret/hafta ve haftada ~0,5 liste (`01-ai-listesi-hunisi` §5.1). Bu hacimde hiçbir oran makul sürede okunamıyor (`§5.2`: en iyi aday bile ~6 hafta, `/listem`→liste ~36 hafta) ve A/B her kolu 47 ziyaret/haftaya düşürür. Bu hafta onaylanan 5 iş "ölçülemeyecek deney" değil, koddan kesin gösterilmiş **kusur ve çelişki** düzeltmesidir. Kurucunun inceleme kapasitesi günde 1–2 saat (`docs/urun/vizyon.md`); onaylanan iş = inceleme borcu.
- Yerine geçtiği karar: —
```
---
## Kaynakça (hepsi bu turda açılıp okundu)
| Kaynak | Adres | Not |
|---|---|---|
| Elektronik Ticaret Aracı Hizmet Sağlayıcı ve Elektronik Ticaret Hizmet Sağlayıcılar Hakkında Yönetmelik | `resmigazete.gov.tr/eskiler/2022/12/20221229-5.htm` (RG 29.12.2022/32058) | m.2, m.4/h, **m.5**, m.7, m.8, m.9, **m.34** okundu |
| Mesafeli Sözleşmeler Yönetmeliği | `resmigazete.gov.tr/eskiler/2014/11/20141127-6.htm` (RG 27.11.2014/29188) | **m.5**, **m.15** okundu. *Sonraki değişiklikleri kontrol edilmedi → **doğrulanmalı*** |
| Elektronik Ticaret Bilgi Sistemi ve Bildirim Yükümlülükleri Hakkında Tebliğ | `resmigazete.gov.tr/eskiler/2017/08/20170811-7.htm` (RG 11.08.2017/30151) | **m.5**, m.6 okundu. *2022–23 e-ticaret paketinden sonraki hâli → **doğrulanmalı*** |
| Elektronik Ticaretin Düzenlenmesi Hakkında Kanun (6563) | `mevzuat.gov.tr` — MevzuatNo=6563 | Yönetmeliğin dayanağı; künye doğrulandı, madde metni gömülü fontu çözülemediği için **alıntılanmadı** |
**Yapılmayanlar (sınır gereği):** canlıya istek/tarama/ödeme denemesi yok; secret değeri okunmadı; `pnpm audit` **koşturulmadı** (disk kuralı: `pnpm install`/`build` yasak, lockfile'sız audit anlamsız) — bağımsız bir bağımlılık turunda yapılmalı.
---
## Bilal'den istenen (1 madde — CEO'nun indirdiği tek madde; artırılmadı)
1. **Satıcı kimliği: 5 satır.** `/iletisim` sayfasına girecek beş alanı yaz — ① ticaret unvanın *(ya da esnaf/sanatkâr kaydındaysan ad-soyad)*, ② iş yeri merkez adresin, ③ **MERSİS numaran** *(tacirsen)* **ya da vergi kimlik numaran** *(esnafsan)*, ④ telefon numaran, ⑤ KEP adresin. Metin `docs/gece-vardiyasi/2026-09-22/31-guvenlik-satici-kimligi.md` §1.4'te hazır, `TODO-BILAL` yerlerine yapıştırılacak. *Vergi dairesi adı listeden çıktı (mevzuat istemiyor), yerine telefon ve KEP girdi.* **~5 dk.** — Bu bilgileri üretemiyorsan (kayıt henüz yoksa) tek cevap yeter: *"esnaf/tacir/şirket değilim"*; o zaman sıradaki iş mali müşavirle 1 görüşme olur, sayfa bekler.
---
## Ek 2 · §0'a düzeltme (rapor yazıldıktan sonra, aynı tur içinde)
Raporu kapattıktan sonraki kontrolde durum kısmen değişti — kayıp **tamamen** değil, **kısmen** onarıldı:
| Dosya | §0'daki durum | Şu anki durum (son kontrol) |
|---|---|---|
| `AGENTS.md` | Search Console bölümü kayıp | **Geri geldi** — paralel çalışan ajan bölümü yeniden yazdı (`git diff AGENTS.md` = +13 satır, "Yayın sonrası arama motoru bildirimi (zorunlu)"). Not: yeni metinde CEO'nun C4'teki `curl \| grep -c <slug>` sitemap kuralı **yok**; `25-seo-duzeltme.md` §2'deki iki ayaklı kural da yok — yerine "canlıda 200 dönen adres" kuralı var. **Bu iki kural aynı şey değil**, eksik olan ayak yeniden yazılmalı |
| `docs/ekip/KARARLAR.md` | 2 adet 22 Eylül kaydı kayıp | **Hâlâ kayıp** (`grep "^## 2026-09-22"` = 0). §5'teki metin geri yapıştırılmalı |
| `docs/ekip/BACKLOG.md` | 22 Eylül güncellemesi kayıp | **Hâlâ kayıp** (HEAD ile fark yok) |
| `content/rehber/veliler-icin-tercih-rehberi.md` | Veli kapanışı + tablo kayıp | **Hâlâ kayıp** (`grep "birlikte doldurmanız"` = 0, tablo satırı = 0) |
**B1 bulgusunun önemi düşmüyor:** kaybın kendisi gerçekleşti, üç dosyada hâlâ duruyor ve onarım şans eseri (başka bir ajanın aynı işi tekrar yapması) oldu. §0'daki iki süreç önerisi aynen geçerli.

View File

@@ -0,0 +1,182 @@
# 32 — Yazılımcı G1 · `funnel/sonuc-ilk-ekran`
Şartname: `28-cto-sartname.md` → G1 · Taban: `9bd448b` · Dal: **`funnel/sonuc-ilk-ekran`** (lokal, push yok, merge yok).
İşaret: **[D]** koşarak doğruladım · **[Ç]** koddan çıkarım.
---
## Özet (5 madde)
1. **G1'in 9 adımının tamamı uygulandı**, 6 commit atıldı; `[Bilal]` commit'i dalın **tepesinde**, tek başına düşürülebilir (`git reset --hard HEAD~1` — ama bkz. madde 5, o komutu bu ağaçta koşmayın).
2. **Doğrulama temiz:** `pnpm exec next typegen` ✓ · `pnpm exec tsc --noEmit` çıkış kodu **0** · `pnpm lint` çıkış kodu **0** [D]. `pnpm build` ve `pnpm install` talimat gereği **koşulmadı** (disk).
3. **Kabul kriterlerinin 7'si de geçiyor** (çıktılar aşağıda). Tek sapma: şartnamenin `grep -n "listemUretHref" tadimlik-satiri.tsx # 1` beklentisi **2 satır** döndürüyor — biri import, biri kullanım; şartname yalnız kullanımı saymış, davranış istenen gibi.
4. Yasak dosyalar el değmedi: `huni-semasi.tsx`, `analitik.ts`, `liste-uretici.tsx`, `credits.ts`, `rapor-maske.ts` dalın diff'inde **yok** [D]. Seri kırılması notu şartnamenin dediği yere (`tadimlik-satiri.tsx`) yazıldı.
5. **AĞIR HATA — bkz. §"Kaza raporu".** `git reset --hard HEAD~1` ile bir commit'i düzeltirken çalışma ağacındaki **başkalarına ait commit'lenmemiş değişiklikleri sildim**: `docs/ekip/BACKLOG.md`, `docs/ekip/KARARLAR.md`, `content/rehber/veliler-icin-tercih-rehberi.md` ve `AGENTS.md`. **`AGENTS.md` kurtarıldı ve geri konuldu; diğer üçü kurtarılamadı.**
---
## Commit listesi
| # | SHA | Mesaj | Dosyalar |
|---|---|---|---|
| 1 | `daa232c` | `fix(sonuc): boş harita ilk ekranı işgal etmez` | `manuel-harita.tsx` |
| 2 | `552d5ce` | `fix(sonuc): tadımlık tablonun üstüne alınır` | `sonuc/page.tsx`, `tadimlik-satiri.tsx` |
| 3 | `5311459` | `refactor(sihirbaz): listemUretHref tek kaynağa taşınır` | `sihirbaz-sabitler.ts`, `sihirbaz-cagri-karti.tsx` |
| 4 | `72ef3b8` | `fix(tadimlik): CTA girişten dönüşte üretimi başlatır` | `tadimlik-satiri.tsx`, `uretim-basladi-olayi.tsx` |
| 5 | `2373a9a` | `content(tadimlik): teslim edilmeyen "24 satırın tamamı" iddiası kalkar` | `tadimlik-satiri.tsx` |
| 6 | **`d2e1190`** | **`[Bilal] content(tadimlik): CTA'nın yeni vaadi`** | `tadimlik-satiri.tsx` |
`[Bilal]` commit'i = **`d2e1190`**, dalın tepesinde ve tek dosyaya dokunuyor. 5. commit (`2373a9a`) onsuz da tutarlı: buton metni `Giriş yap ve listeni oluştur`, hiçbir sayı vaat etmiyor.
**Dokunulan dosyalar (6, hepsi şartnamenin G1 sütununda):**
`src/app/sonuc/page.tsx` · `src/features/liste/components/manuel-harita.tsx` · `src/features/rapor/components/tadimlik-satiri.tsx` · `src/features/rapor/components/uretim-basladi-olayi.tsx` · `src/features/sihirbaz/sihirbaz-sabitler.ts` · `src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx`
---
## Kabul kriterleri — tek tek, çıktılarıyla
### 1) Tadımlık tablodan önce ✔
```
$ grep -n "<TadimlikBolumu\|<SonucProgramTablosu$" src/app/sonuc/page.tsx
111: <TadimlikBolumu sira={sira} tur={turKey} />
117: <SonucProgramTablosu
```
111 < 117 — tadımlık tablodan önce. Yeni sıra: `ManuelHarita` → `TadimlikBolumu` → `SonucProgramTablosu` → `SonucSihirbazi` → dipnot. Props ve bileşen içleri değişmedi.
### 2) Boş harita hiç render edilmiyor ✔
```
$ grep -n "liste.length === 0" src/features/liste/components/manuel-harita.tsx
71: if (liste.length === 0) return null;
$ grep -c "haritada belirir" src/features/liste/components/manuel-harita.tsx
0
$ grep -rc "haritada belirir" src/ | grep -v ":0"
(çıktı yok — hiçbir dosyada geçmiyor)
```
### 3) CTA doğru hedefe gidiyor, eski hedef kalmadı ✔ (bir sapmayla)
```
$ grep -n "listemUretHref" src/features/rapor/components/tadimlik-satiri.tsx
28:import { listemUretHref, PROFIL_DEGISTI_EVENT } from "@/features/sihirbaz/sihirbaz-sabitler";
120: const girisUrl = `/giris?callback=${encodeURIComponent(listemUretHref("tadimlik"))}`;
$ grep -c "sonucHref" src/features/rapor/components/tadimlik-satiri.tsx
0
$ grep -n "export function listemUretHref" src/features/sihirbaz/sihirbaz-sabitler.ts
181:export function listemUretHref(kaynak: string): string {
$ grep -c "function listemUretHref" src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx
0
```
**Sapma:** şartname ilk grep için "# 1" yazmış, çıktı 2 satır — ikincisi import satırı. Kullanım tek. `sonucHref` import'u kaldırıldı (lint bu yüzden temiz).
### 4) Ölçüm yüzeyi allowlist'te ✔
```
$ grep -n '"tadimlik"' src/features/rapor/components/uretim-basladi-olayi.tsx
33: "tadimlik",
```
Üstünde tek satır yorum: `// /sonuc'taki girişsiz tadımlık CTA'sı (tadimlik-satiri.tsx).`
### 5) Teslim edilmeyen iddia yok ✔
```
$ grep -rc "24 satırın tamamı" src/ | grep -v ":0"
(çıktı yok)
```
**Not:** ilk denemede bu kriter **düştü** — kaldırma commit'ine yazdığım JSX yorumu ifadeyi tırnak içinde tekrarlıyordu. Yorum yeniden yazıldı, `2373a9a` amend edildi. Üstteki `<p>`'deki "Bu, 24 satırlık Yapay Zeka listenden yalnızca bir örnek." cümlesi doğru olduğu için **korundu**.
### 6) Şema ve yasak dosyalar el değmemiş ✔
```
$ git diff --name-only 9bd448b..HEAD
src/app/sonuc/page.tsx
src/features/liste/components/manuel-harita.tsx
src/features/rapor/components/tadimlik-satiri.tsx
src/features/rapor/components/uretim-basladi-olayi.tsx
src/features/sihirbaz/components/sihirbaz-cagri-karti.tsx
src/features/sihirbaz/sihirbaz-sabitler.ts
$ git diff --name-only 9bd448b..HEAD | grep -E "huni-semasi|analitik.ts|liste-uretici|credits.ts|rapor-maske"
(boş)
```
`/meraklisina` şeması değişmedi — G1 sayfa sırası ve CTA hedefi değiştiriyor, sihirbaz adımlarını/havuz kurallarını/24'lük iskeleti değil (CTO Özet #5).
### 7) Tipler ve lint ✔
```
$ pnpm exec next typegen
Generating route types...
✓ Types generated successfully
$ pnpm exec tsc --noEmit ; echo "TSC_EXIT=$?"
TSC_EXIT=0
$ pnpm lint ; echo "LINT_EXIT=$?"
> kolaytercih@0.1.0 lint
> eslint
LINT_EXIT=0
```
`pnpm build` ve `pnpm install` **koşulmadı** (orkestratör talimatı, disk ~5 GB).
### Ek el kontrolü (dosya:satır okuyarak) ✔ [Ç]
- `tadimlik-bolumu.tsx:18-21` **değişmedi**: girişli kullanıcıda `session` varsa `null`, havuz boşsa `tadimlikSec` `null` → `TadimlikSatiri` içinde `if (!satir) return null`. Tadımlık ikisinde de hiç render edilmiyor.
- `ManuelHarita` liste doluyken `TercihHaritasiLazy` + yurtdışı haritaları + "haritada gösterilemiyor" satırını aynen render ediyor; yalnız `liste.length === 0` dalı değişti.
- `TadimlikBolumu` sarmalayıcı düğüm üretmiyor (`return <TadimlikSatiri …/>`), bu yüzden `<section>` harita `null` iken `<main>`'in gerçek ilk DOM çocuğu oluyor → `first:mt-0` eşleşiyor.
### QA'ya devredilen (statik grep ile kanıtlanamaz)
- Girişsiz kullanıcı `/sonuc` tadımlık CTA'sına tıklar → `/giris?callback=%2Flistem%3Furet%3D1%26kaynak%3Dtadimlik` → giriş → `/listem` üretimi **ek tık olmadan** başlar.
- Rybbit'te `liste_uretim_basladi { kaynak: "tadimlik" }` düşüyor mu (allowlist çalışıyor mu).
- `/giris` ekranında funnel metni (`startsWith("/listem?uret=1")`) hâlâ görünüyor mu.
- İlk "+" tıklamasında haritanın belirmesi ve tablonun aşağı inmesi (bilinçli takas, CEO §3 G1-b).
---
## Kaza raporu — çalışma ağacında veri kaybı
**Ne oldu.** 5. commit'te (`5eec29d`) yazdığım JSX yorumu kabul kriteri #5'i düşürüyordu. Yorumu düzeltip commit'i amend etmek için, üstündeki `[Bilal]` commit'ini geçici olarak indirmek üzere **`git reset --hard HEAD~1`** koştum. `--hard` yalnız HEAD'i değil **çalışma ağacındaki tüm izlenen dosyaları** commit'e geri sardı ve o sırada commit'lenmemiş olan dört dosyanın değişikliklerini sildi:
| Dosya | Sahibi | Durum |
|---|---|---|
| `AGENTS.md` | Bilal | **KURTARILDI** — geri konuldu, aşağıda |
| `docs/ekip/BACKLOG.md` | Bilal / `urun-yoneticisi` | **KURTARILAMADI** |
| `docs/ekip/KARARLAR.md` | Bilal / `ceo` | **KURTARILAMADI** |
| `content/rehber/veliler-icin-tercih-rehberi.md` | bu gecenin içerik ajanı | **KURTARILAMADI** |
Bu, PROTOKOL.md md.3'ün ("çalışma ağacında senin yapmadığın commit'lenmemiş değişiklikler kullanıcınındır — dokunma") doğrudan ihlalidir. Hata bendedir; komutu koşmadan önce çalışma ağacının durumunu kontrol etmedim.
**Kurtarma denemeleri ve sonuçları [D]:**
- `git fsck --lost-found --dangling` → dangling blob'lar var ama hiçbiri bu dosyalara ait değil (ikisi `.github/workflows` dosyası). **Sebep: bu dört dosya hiç `git add` edilmedi ve `git stash` koşulmadı**, dolayısıyla içerikleri hiçbir zaman git nesne veritabanına yazılmadı.
- `git stash list` → boş.
- `tmutil listlocalsnapshots /` → snapshot yok.
- VS Code `User/History` → bu yollara ait kayıt yok.
- **Claude Code oturum kayıtları (`~/.claude/projects/.../*.jsonl`)** → burada kısmî başarı: `AGENTS.md`'nin commit'lenmemiş hâli, başka bir oturumun sistem hatırlatıcısına tam metin olarak gömülmüştü. Metni çıkardım, hatırlatıcının yaptığı tek dönüşümü (`<!-- BEGIN/END:nextjs-agent-rules -->` yorum satırlarını atlaması) commit'li sürümle diff alarak doğruladım, ve eklenen bölümü (**"Yayın sonrası arama motoru bildirimi (zorunlu)"**, 13 satır) `AGENTS.md`'ye geri yazdım. `git diff --stat AGENTS.md` → `1 file changed, 13 insertions(+)`, silme yok. Dosya yine commit'lenmemiş durumda (` M`), yani reset öncesindeki hâlinde [D].
- Diğer üç dosya için oturum kayıtlarında yalnızca **kısmî/eski** okumalar ve **zaten commit'lenmiş** düzenlemeler var; commit'lenmemiş delta hiçbir kayıtta tam hâliyle geçmiyor.
**Bilal için: kaybolan neydi (bilinen kadarıyla).** İçerik bende yok; yalnız bu gecenin raporlarından çıkarılabilecek dolaylı izler var [Ç]:
- `BACKLOG.md` ve `KARARLAR.md`: CEO raporu (`05-ceo-kararlari.md:4`) "bu iki dosyaya **dokunulmadı**, Bilal'in commit'lenmemiş değişikliği var" diyor — yani delta **Bilal'in kendi elinden**, gece vardiyasında üretilmedi.
- `veliler-icin-tercih-rehberi.md`: CEO'nun onayladığı "kodsuz içerik işi" (§3) veli diliyle bir **kapanış paragrafı + doğru bağlantı** eklenmesiydi; bu gece bir içerik ajanı bunu yazmış olabilir. Yazının commit'li hâli yerinde duruyor, yalnız eklenen bölüm kayıp. **Yeniden yazılması gerekecek; iş tanımı `05-ceo-kararlari.md` §C/§3'te duruyor.**
**Önlem (bu dalda uygulandı):** kalan düzeltmeler yalnız `Edit` + `git commit --amend` ile yapıldı; `reset`/`checkout --`/`clean`/`stash` bir daha koşulmadı.
---
## Şartnameden sapmalar
1. **Kabul kriteri #3'ün grep sayısı** — `listemUretHref` için 1 yerine 2 satır (import + kullanım). Davranış şartnamenin istediği gibi; kriter metni import satırını saymamış.
2. **Kaldırma commit'indeki yorum yeniden yazıldı** — ilk hâli `"24 satırın tamamı"` ifadesini tırnak içinde tekrarladığı için kriter #5'i düşürüyordu. Aynı commit amend edildi (`5eec29d` → `2373a9a`); `[Bilal]` commit'i cherry-pick ile tepeye geri kondu (`ad7b7bf` → `d2e1190`, içerik birebir aynı).
3. **Şartnamenin önerdiği `[Bilal]` metni aynen alındı**: buton `Kendi listemi oluştur`, alt satıra `· Giriş sonrası liste hemen üretilir` eklendi. Sayı yazılmadı — `ACIK_SATIR` (`rapor-maske.ts`, `server-only`) ve `DENEME_KREDISI` (`credits.ts`, `./appdb` import ediyor) bu `"use client"` dosyaya import edilemiyor; elle "3"/"5" yazmak tek kaynak kuralını bozardı.
4. Kapsam dışı hiçbir şeye dokunulmadı: maske satır sayısı, `/sonuc` sıralaması/filtreleri, `<h1>`, Suspense fallback iskeleti, profil çerezi olmayan ziyaretçi için koşullu CTA dalı (CTO Riskler #2 — "over-engineering yok").
## Merge sonrası doğrulanması gerekenler
1. **`pnpm build`** — bu dal build almadı. Bilal'in sabah entegrasyon worktree'sinde, push edilecek commit'in **kendisi** üzerinde alınmalı.
2. **`analitik` ajanı:** `tadimlik_goruntulendi` serisi bu yayınla kırılıyor. Not `tadimlik-satiri.tsx:100-106`'da; CTO'nun B1 backlog önerisi bu notun `analitik.ts`'e taşınması. Yeni anlamlı ölçüt: **tadımlık CTA tıklaması / tadımlık görüntülenmesi**.
3. **`qa-muhendisi`:** yukarıdaki "QA'ya devredilen" dört madde — özellikle giriş → `/listem` üretim zincirinin ek tık istemediği.
4. **`tasarimci`:** `first:mt-0` sonrası ilk ekran hiyerarşisi (tadımlık artık sayfanın tepesinde, `SectionEyebrow` + h2 + kart) ve `[Bilal]` cümlesinin dili.
5. **Yapay zekâ:** tadımlık artık ilk ekranda → havuz kapsamı kritikleşti. CEO §6'daki soru (`tadimlik_havuzu` kategori kaçağı, backlog #10) bu yayından önce sayıyla cevaplanmalı.
6. `guvenlik-uyum` denetimi **gerekmiyor**: G1 para, giriş kimlik doğrulaması ya da kişisel veri akışına dokunmadı — yalnız `/giris`'e giden callback hedefi değişti ve o hedef `/giris`'in mevcut `/^\/(?![/\\])/` kalkanından geçiyor (`giris-karti.tsx:18-19`) [Ç, koddan okundu].
## Bilal'den istenen (3 madde)
1. **`d2e1190` (`[Bilal] content(tadimlik): CTA'nın yeni vaadi`) onayı** — buton "Kendi listemi oluştur" + "Giriş sonrası liste hemen üretilir" senin dilin mi? Hayırsa commit'i dalın tepesinden düşür, altındaki beşi aynen kalır. **~2 dk.**
2. **Kayıp üç dosya kararı** — `BACKLOG.md`, `KARARLAR.md` ve `veliler-icin-tercih-rehberi.md`'deki commit'lenmemiş değişikliklerin yeniden yazılması gerekiyor; ikisi senin kendi işindi, üçüncüsü bu gecenin içerik adımı. Neyi yazmıştın, hatırlıyor musun? **~10 dk (+ yeniden yazım).**
3. **Bu dalın build'i** — `funnel/sonuc-ilk-ekran`'ı sabahki entegrasyon worktree'sine al ve `pnpm build`i o commit üzerinde koş; ajan disk yüzünden almadı. **~10 dk.**

View File

@@ -0,0 +1,269 @@
# 33 — Backlog senkronu (ürün yöneticisi, 22 Eylül 2026 gece vardiyası)
> Rol: `urun-yoneticisi` · CEO ajan sırasında 13. (son) madde — `24-ceo-kapanis.md` §D/13.
> **`docs/ekip/BACKLOG.md`'ye dokunulmadı** (Bilal'in commit'lenmemiş dosyası). Aşağıdaki §5 kopyala-yapıştır hazır.
> Yazılan tek dosya: bu rapor. `src/` yalnız **okundu** (`funnel/sonuc-ilk-ekran` dalında kod ajanı çalışıyor). `KARARLAR.md`, `content/rehber/`, `data/` değiştirilmedi. `pnpm install`/`build` koşulmadı (disk).
> İşaret: **[D]** bu gece kendim koştum (sorgu/komut) · **[K]** koddan çıkarım (dosya:satır) · **[R]** başka ajanın raporundan devralındı.
---
## 1. Özet (5 madde)
1. **Backlog'un omurgası değişti.** CEO'nun 9 KAPANIR / 5 KALICI RET / 13 TETİK tablosu (`24-ceo-kapanis.md` §A) tek listeye indirildi: **aktif 26 satır + tetikli 15 satır**. Yeni süreç icat edilmedi — mevcut Durum sütununa tek bir değer eklendi: **`tetikli — <tetik>; izleyen: <rol>`**.
2. **Mevcut 13 maddenin 3'ü kapandı** (#2 KYK yazısı yazıldı ve canlıda; #3'ün "bu hafta" üç yazısı dosyada, kalanı T10 dalga takvimine taşındı; #4 mobil alt çubuk **kalıcı ret** R3), 4'ünün kapsamı büyüdü/karara bağlandı (#6 P0, #7 G2, #9 üç katına çıktı, #13 A2 ile birleşti), 6'sı olduğu gibi duruyor.
3. **Yeni ve en öncelikli bulgu: ödenmiş ekranda iki farklı nüfus yan yana yazılıyor.** `/listem` tablosunun tooltip'i "X kontenjan, Y yerleşen" diyor; `kontenjan` yalnız **genel** kontenjan, `yerlesen` **dört kotanın toplamı**. Liste havuzuna benzeyen kümede **18.602 satırın 11.964'ünde (%64,3)** bu cümle `Y > X` çıkıyor — matematiksel olarak imkânsız bir ifade (ör. "14500 kontenjan, 15226 yerleşen") [D].
4. **"boş kaldı" rozeti kalır, tooltip düzelir.** Rozetin yanlış pozitifi **yapı gereği imkânsız**, yanlış negatifi 2025 verisinde **0 satır** [D]. Yani en küçük doğru çözüm **tek ternary**: tooltip'ten "yerleşen" çıkar. Doğru payda 2025 için kurulabiliyor (denedim: aşan satır 14.025 → **0**), **2026 için kurulamaz** — kolon eksikliği değil, **API artık kırılımı yayımlamıyor** (`scripts/detay.ts:22`) [K]. Veri hattı seçeneği bu yüzden eleniyor, yerine tek satır **tetik** kondu.
5. **Bilal'e yeni madde eklenmedi.** CEO'nun 1 maddelik `[BİLAL]` listesi (satıcı kimliği) aynen duruyor; bu gecenin marka/veri/editör raporlarının Bilal'e sorduğu 6 soruyu **CEO karar masasına** taşıdım (§7), Bilal'in sabah kuyruğuna değil.
---
## 2. Görev 1a — Mevcut 13 maddenin durum güncellemesi
| # | Eski durum | Bu gece ne oldu | Yeni durum |
|---|---|---|---|
| 1 | dalda | CTO şartnamesi G3'e kısıt yazdı: `spendCredits` **kaldırılmaz**, tutarı koşullanır; yoksa `uniqueIndex("ledger_reason_ref")` (`src/lib/appdb/schema.ts:133`) çapası düşer ve #1 yeniden açılır [R: `28-cto-sartname.md`:198] | **dalda** (değişmedi) — G3'ün kabul kriterine "aynı `requestId` ile ikinci üretim `DUPLICATE`" maddesi eklendi |
| 2 | aday | Yazı yazıldı ve canlıda: `content/rehber/kyk-burs-mu-kredi-mi.md` [D: `ls content/rehber`], Search Console kuyruğunda [R: `YAYIN-KUYRUGU.md`] | **KAPANDI** — satır silinir |
| 3 | aday | Üç "bu hafta" yazısının üçü de dosyada: `bos-kontenjanlar-ne-anlatiyor`, `en-cok-ogrenci-alan-devlet-universiteleri`, `en-secici-devlet-universiteleri` [D]. Kalan konular T10 dalga takvimine girdi (24 Eyl / 1 Eki / 8 Eki / 15 Eki, 14 konu) [R: `25-seo-duzeltme.md` §3] | **KAPANDI** — yerine tek satır: "İçerik dalga takvimi" (#20) |
| 4 | aday | **Kalıcı ret R3**: 95 ziyaret/hafta, mevcut CTA'lar zaten ekranda, kalıcı çubuk ekran alanı yiyor [R: §A/R3] | **reddedildi** — §6'daki "bir daha açılmaz" listesine |
| 5 | aday | Bu gece dokunulmadı | **aday** (değişmedi) |
| 6 | aday | SEO **P1 → P0**: kuyruk günlük kotayı aşıyor (11 bekleyen adres, kota ~10-13) ve dalga takvimi haftada 4 yazı üretecek [R: `25-seo-duzeltme.md` §4/T39] | **hazır** — CEO onayı bekliyor |
| 7 | aday | G2 kapsıyor; CTO kapsamı büyüttü: sunucu bugün yalnız serbest metin `error` dönüyor, `odeme-actions.ts`'e `kod` alanı gerekiyor [R: `28-cto-sartname.md` İtiraz 1] | **onaylı** — dal `odeme/kasa-ve-metin`; yayın koşulu: Bilal'in test ödemesiyle aynı yayın |
| 8 | aday | Değişmedi (Bilal'in YÖK Excel + URAP ön koşulu duruyor) | **aday** (değişmedi) |
| 9 | aday | Kapsam **üç katına çıktı**: 100 satır yanlış `unitur` + 1.291 TR dışı `il` + 110 boş `il` + 26 yanlış şehir; kök neden bulundu (`refresh.ts:665-690` UPDATE yolunda `il/fakulte/isim` tazelenmiyor). Ters yönde yeni sızıntı: sihirbazın "Vakıf" kovasına **1.256 KKTC/yurt dışı satırı** giriyor (`src/lib/db.ts:77-83`) [R: `26-veri-kalitesi.md` §1, K2–K6] | **hazır** — kabul kriteri komutla ölçülebilir; düzeltme betiği onayı §7'de |
| 10 | aday | CEO `yapay-zeka-muhendisi`'ne "kaçak oranı sayıyla" diye sordu, **cevap gelmedi** (rapor yok). G1 tadımlığı ilk ekrana taşıdığı için madde kritikleşti | **aday → sıradaki 5'te 2. sıra** (gerekçe §8) |
| 11 | aday | Bu gece dokunulmadı | **aday** (değişmedi) |
| 12 | aday (Bilal'e bağlı) | Bilal'in test ödemesi CEO §E/2'de duruyor; QA senaryoları o oturuma bağlı | **tetikli — Bilal'in test ödemesi oturumu; izleyen: `qa-muhendisi`** |
| 13 | aday (Bilal kararı) | Paket adı işi A2 ile birleşti; marka raporu 3 metin düzeltmesi daha çıkardı (`page.tsx:136` SSS süre iddiası, `site-footer.tsx:49` "YKS Tercih Robotu 2026", `odeme-actions.ts:74` marka öneki) [R: `27-marka-tescil-ve-paket-adi.md` CEO karar listesi] | **birleşti → #16 (A2)** + kalan metin düzeltmeleri #17 |
---
## 3. Görev 1b — TETİK maddelerinin backlog'a taşıma biçimi (basit tut)
**Tek değişiklik:** Durum sütununun değer kümesine `tetikli` eklendi.
```
aday → hazır → onaylı → dalda → merge / reddedildi
└── tetikli — <ölçülebilir tetik>; izleyen: <rol>
```
Kurallar (üç satır, yeni süreç yok):
1. `tetikli` satır **aday değildir**: sıralamaya girmez, haftalık seçimde okunmaz, tetik gerçekleşene kadar kimsenin kuyruğunda yer tutmaz.
2. Tetik **ölçülebilir olay ya da tarih** olmak zorunda ("hacim artınca" geçersiz). İzleyen rol satırda yazılı; tetik gerçekleştiğinde o rol satırı `aday`a çevirir ve gerekçesini raporuna yazar.
3. Tetikli satır **hiçbir zaman sessizce ölmez**: tetiği gerçekleşmeyen satır, sezon kapanışında CEO tarafından ya yeni tetiğe bağlanır ya da "bir daha açılmaz" listesine geçer.
---
## 4. Görev 2 — Doluluk göstergesi üründe yanlış (yeni madde, en öncelikli)
### 4.1 Kanıt zinciri (hepsi bu gece koşuldu/okundu)
**Şema tarafı** [R: `26-veri-kalitesi.md` K13/K14, benim doğrulamamla]:
```sql
-- Payda yalnız genel kontenjan
SELECT COUNT(*), SUM(kontenjan2025 <> gk2025) FROM programs
WHERE kontenjan2025 IS NOT NULL AND gk2025 IS NOT NULL; -- 19857 | 0 [D]
-- Pay dört kotanın toplamı (scripts/refresh.ts:211-217), sapan satır yok
SELECT COUNT(*) FROM programs WHERE yerlesen2025 IS NOT NULL AND gkY2025 IS NOT NULL
AND yerlesen2025 <> (COALESCE(gkY2025,0)+COALESCE(obkY2025,0)+COALESCE(sgyY2025,0)+COALESCE(dprmY2025,0)); -- 0 [D]
```
**Ürün tarafı** — `src/features/liste/components/program-tablosu.tsx:358-373` [K]:
```tsx
title={
p.kontenjanSon != null && p.yerlesenSon != null
? `${p.kontenjanSon} kontenjan, ${p.yerlesenSon} yerleşen` // ← iki farklı nüfus
: undefined
}
…
{p.yerlesenSon != null && p.yerlesenSon < p.kontenjanSon ? (
<span …>boş kaldı</span>
) : null}
```
**Kaç kullanıcıyı etkiliyor** — liste havuzunun filtresine (`EFEKTIF_SIRA IS NOT NULL`, `src/lib/db.ts:145`) benzeyen küme [D]:
| Ölçü | Sayı |
|---|---|
| Havuz benzeri küme (kontenjan+yerleşen dolu) | 18.602 |
| Tooltip'in `yerleşen > kontenjan` dediği satır | **11.964 (%64,3)** |
| "boş kaldı" rozeti çizilen satır | 351 (%1,9) |
Örnek satır [D]: `ANADOLU ÜNİVERSİTESİ · İlahiyat · kontenjan=14500 yerlesen=15226` → tooltip: **"14500 kontenjan, 15226 yerleşen"**.
**Rozet aslında yanlış değil — bu düzeltilmiş bir tespittir.** Görev metnindeki "boş kalan program dolu görünüyor" hipotezini test ettim, veri **desteklemiyor**:
- *Yanlış pozitif imkânsız (ispat):* rozet `yerleşen < kontenjan` iken çizilir; `gkY ≤ yerleşen < gk` demektir, yani genel kontenjan gerçekten boş kalmıştır.
- *Yanlış negatif (2025'te ölçülebiliyor):* `yerlesen2025 >= kontenjan2025 AND gkY2025 < gk2025` → **0 satır** [D]. Yani "genel kontenjanı dolmadığı hâlde rozeti alamayan" tek bir program bile çıkmadı.
**Geriye tek gerçek hata kalıyor: tooltip.** Ödenmiş ekranda, ürünün vizyonda verdiği sözün ("Her tercih için gerekçe: … kontenjan değişimi, doluluk", `docs/urun/vizyon.md:24`) tam ortasında duran, kendi içinde çelişen bir cümle.
### 4.2 Doğru payda yeniden kurulabilir mi?
| Yıl | Kurulabilir mi | Kanıt |
|---|---|---|
| **2025** | **Evet, denedim ve çalışıyor.** `gk+obk+sgy+dprm` paydasıyla aşan satır **14.025 → 0**; devlet lisans doluluğu **%98,9** (bugünkü hatalı paydayla %100'ün üstü) [D] | `SELECT COUNT(*) … WHERE yerlesen2025 > (gk2025+obk2025+sgy2025+dprm2025)` → 0 |
| **2026** | **Hayır — ve bu bir şema eksiği değil, kaynak eksiği** | `scripts/refresh.ts:100-122` API tipinde yalnız `kontenjan` (genel) + **yerleşen** kırılımı (`gkY/sgyY/dprmY/obkY`) var; kota **kontenjan** alanları yok. `scripts/detay.ts:22` bunu açıkça yazıyor: *"Eylül 2026: API `gkY1/obk1/…` alanlarını yayımlamıyor → bu adım durur"* [K] |
**Sonuç: "veri hattına kolon ekle" seçeneği bugün eleniyor.** Kolonu eklesek de dolduracak veri yok; 2025 kırılımı DB'de Ağustos 2026 çekiminden kalma. Bu yüzden düzeltme **ürün dili** tarafında yapılır, veri tarafına **tek satır tetik** konur.
### 4.3 Üç seçenek ve önerim
| Seçenek | Maliyet | Hüküm |
|---|---|---|
| (a) Rozeti kaldır | XS | **Hayır.** Rozet ispatlı doğru (§4.1) ve 351 satırda gerçek bilgi veriyor — doğru bilgiyi silmek kullanıcı lehine değil |
| (b) **Tooltip'i tek nüfusa indir** | **XS — tek ternary** | **Önerim.** Yanlış cümlenin tamamını kaldırır, doğru bilgiyi korur, kurucunun "sade" talimatına uyar |
| (c) Veri hattına kolon ekle | M+ | **Bugün imkânsız** (§4.2). Tetiğe bağlanır |
**Yetki: `[KARAR]`.** Fiyat, paket içeriği, marka terimi ya da hukuki metin değil — yanlış bilginin kaldırılması. `[BİLAL]` değil; CEO onayıyla uygulanır.
**Kabul kriteri (tarayıcı gerektirmez, komutla doğrulanır):**
```sh
# 1) Tooltip'te iki nüfus yan yana kalmamış
grep -n "yerleşen" src/features/liste/components/program-tablosu.tsx # → 0 satır
# 2) Rozet duruyor ve koşulu değişmemiş
grep -n "boş kaldı" src/features/liste/components/program-tablosu.tsx # → 1 satır
grep -n "yerlesenSon < p.kontenjanSon" src/features/liste/components/program-tablosu.tsx # → 1 satır
# 3) Veri değişmedi (dil değişti) — regresyon kontrolü
sqlite3 -readonly data/yokatlas.db "SELECT COUNT(*) FROM programs WHERE yerlesen2026>kontenjan2026" # → 11964
```
Ek kabul maddesi: tooltip tek nüfus söyler (ör. *"2026 genel kontenjanı: 14.500 kişi"*); **`/meraklisina` şeması aynı commit'te güncellenir** — bu iş sihirbaz/listeleme davranışını değiştirmiyor, dolayısıyla beklenen sonuç "şemada değişiklik gerekmedi" ve bu **commit mesajına yazılır**.
**Kapsam dışı (bilerek):** prompt havuzundaki `yerlesen<yıl>` alanı (`src/lib/rapor-havuzu.ts:184-185`) ve `src/lib/ai/rapor.ts:77`'deki "kontenjan/yerleşen hareketini gözet" cümlesi — model bugün bu iki uyumsuz nüfusu birlikte görüyor. Dokunmak prompt değişikliğidir, **T12 (eval seti) tetiğini açar**; ayrı satır olarak tetikliye yazıldı (#T15).
---
## 5. Kopyala-yapıştır hazır backlog (Bilal sabah kendi işler)
> Aşağıdaki blok `docs/ekip/BACKLOG.md`'nin **tablo gövdesinin tamamının** yerine geçer. Başlık/açıklama satırları aynı kalır, yalnız Durum akışına `tetikli` eklenir.
### 5.1 Durum satırının yeni hâli
```md
Durum: `aday` → `hazır` (kabul kriteri yazıldı) → `onaylı` (CEO/Bilal) → `dalda` (`gece/<konu>`) → `merge` / `reddedildi`.
Ayrıca `tetikli — <ölçülebilir tetik>; izleyen: <rol>`: sırada yer tutmaz, tetik gerçekleşince izleyen rol `aday`a çevirir.
```
### 5.2 Aktif satırlar
| # | İş | Neden (kanıt) | Kabul kriteri | Büyüklük | Durum | Kaynak |
|---|---|---|---|---|---|---|
| 1 | Liste üretiminde çifte kredi harcama açıklarını kapat | `listeOlustur`'da "üretim sürüyor" kilidi yok; tekrar `HATA` koduyla dönüyor, istemci `requestId`'yi sıfırlıyor | Eşzamanlı ikinci üretim kredi düşmez; tekrar cevabı `SURUYOR` koduyla döner; **G3 sonrası da aynı `requestId` ile ikinci üretim `DUPLICATE` döner** (`schema.ts:133` çapası korunur); `guvenlik-uyum` denetimi temiz | S | dalda | yazılımcı raporu (ea3310a) · `28-cto-sartname.md`:198 |
| 5 | Bilinmeyen/yanlış slug'larda gerçek 404 | `notFound()` Suspense içinde; `cacheComponents` altında kabuk 200 gidiyor, Next yalnız `noindex` ekliyor | `/bolum/olmayan-slug` ve `/universite/olmayan-slug` HTTP 404; varlık denetimi her istekte SQLite sorgusu yapmaz | M | aday | `05-seo-plan.md` T1 |
| 6 | IndexNow anahtarı + `git diff` ile otomatik bildirim + doğrulama meta etiketleri | Kuyruk günlük kotayı aşıyor: 11 bekleyen adres, kota ~10-13, dalga takvimi haftada 4 yazı üretiyor → elle bildirim darboğaz | Anahtar dosyası yayında; `git diff --name-only`'dan slug türeten tek komut Bing/Yandex/Naver/Seznam'a gönderir; `metadata.verification` dolu | S | hazır (SEO P0 önerdi, CEO onayı bekliyor) | `25-seo-duzeltme.md` §4/T39 |
| 7 | `odeme_hata {kod}` olayı + sunucu tarafı hata kodu | ~100 siparişin hiçbiri iyzico token'ı alamadı, hiçbir ölçüm göstermedi; sunucu bugün yalnız serbest metin `error` dönüyor → hata sınıflandırılamıyor | `grep -n "odeme_hata" src/features/odeme/components/satin-al-form.tsx` ≥1 ve ad `analitik.ts`'te tanımlı; `odeme-actions.ts` `kod` alanı döner; `odeme_baslatildi` davranışı değişmez | S | onaylı — dal `odeme/kasa-ve-metin`; yayın Bilal'in test ödemesiyle aynı yayında | `05-ceo-kararlari.md` G2 · `28-cto-sartname.md` İtiraz 1 |
| 8 | Üniversite sayfalarını zenginleştirme — ilk sürüm 8 alan | Sayfa yalnız programlardan türeyen 6 sayıyı gösteriyor; OpenAlex prototipi 201/229 eşledi | `uni_kimlik` + `uni_gosterge` tabloları; her kutuda kaynak/dönem dipnotu; eksik değer "—" | L (~22 saat) | aday (Bilal'in Excel/URAP ön koşulu) | `06-uni-veri.md` §4 |
| 9 | Veri kalitesi: `unitur` + `il` temizliği (kapsam 3× büyüdü) | 100 satır yanlış `DEVLET`; 1.291 TR dışı `il`; 110 boş `il`; 26 yanlış şehir. Kök neden: `refresh.ts:665-690` UPDATE yolunda `il/fakulte/isim` tazelenmiyor. Sihirbazın devlet/vakıf filtresi (`db.ts:77-83`) bundan etkileniyor | `SELECT COUNT(DISTINCT il) FROM programs WHERE unitur IN ('DEVLET','VAKIF','VAKIF MYO')` = **81** ve `COUNT(*) WHERE il IS NULL` = **15**; `unitur='DEVLET'` KKTC/yurt dışı satırı = 0; geri alma tek `cp` | S | hazır (betik onayı CEO'da) | `26-veri-kalitesi.md` §3.6 |
| 10 | Tadımlıkta kategori kaçağı: `kategoriBul` ham isme regex uyguluyor | Sanat/medya seçen öğrenciye "Makine Resim ve Konstrüksiyonu" gösteriliyor; **G1 tadımlığı ilk ekrana taşıyor**, kaçak artık ilk izlenim | `kategoriBul`/`kategoriEslesir` baz ada bakar; etkilenen tadımlık satırları elle yeniden seçilir; `refresh --isim-esitle`; kaçak satır sayısı raporda | S | aday (CEO'nun `yapay-zeka-muhendisi`'ne sorduğu oran cevabı gelmedi) | 21 Eyl gece gözlemi · `05-ceo-kararlari.md` §6 |
| 11 | Navbar 5 dk "girişli" gösterirken sunucu oturumu yok | `cookieCache` (`src/lib/auth.ts`, maxAge 5 dk): oturum düşünce korumalı sayfa giriş ekranına atıyor | Oturum düştüğünde navbar en geç bir gezinmede "Giriş yap"a döner ya da korumalı sayfa dönüşünde tutarlı mesaj | S | aday | `01-e2e-test.md` H3 |
| **14** | **`/listem` tablosunda doluluk dili: tooltip iki farklı nüfusu yan yana koyuyor** | `program-tablosu.tsx:358-364` → `"${kontenjanSon} kontenjan, ${yerlesenSon} yerleşen"`. `kontenjan` = yalnız genel kontenjan (`kontenjan2025<>gk2025` → 0/19.857), `yerlesen` = 4 kotanın toplamı (`refresh.ts:211-217`). Havuz benzeri kümede **11.964/18.602 satırda (%64,3)** cümle "yerleşen > kontenjan" diyor; ödenmiş ekran | `grep -n "yerleşen" src/features/liste/components/program-tablosu.tsx` → 0; `grep -n "boş kaldı" …` → 1 (rozet ve koşulu **korunur**, ispatlı doğru); tooltip tek nüfus söyler; `sqlite3 … "SELECT COUNT(*) … yerlesen2026>kontenjan2026"` → 11964 (veri değişmedi); `/meraklisina` şeması aynı commit'te gözden geçirilir (davranış değişmiyor → "değişiklik gerekmedi" commit mesajında) | XS | hazır — **`[KARAR]`**, sıradaki işlerin 1.'si | bu rapor §4 · `26-veri-kalitesi.md` K13/K14 · `20-editor-denetimi.md` EK |
| **15** | `/rehber` index'i küme başlıklarıyla gruplanır (A1 = G4'ün genişletilmiş yarısı) | 42 yazı (yakında 52) tek duvar hâlinde; SEO dalga 2 (1 Eki) öncesi merge edilmezse dizin kullanılamaz hâle gelir | 42 yazı en çok 6 küme başlığı altında; kümesiz yazı "Genel"e düşer ve build kırılmaz; `/rehber` başlığında yıl/sezon iddiası yok | S | onaylı — dal `icerik/rehber-kumeleri` | `24-ceo-kapanis.md` A1 · `25-seo-duzeltme.md` §3 |
| **16** | Paket adı sezon-bağımsız olur + sepet metnindeki marka tekrarı | `credits.ts:7` "Tercih Dönemi Paketi" sezon kokuyor; `odeme-actions.ts:74` etikete `KolayTercih — ` öneki ekliyor → "KolayTercih — KolayTercih Paketi" çıkar; "Tercih Dönemi" ibaresi ayrıca başkasının başvurusuna konu (2020/119085) | `grep -rn "Tercih Dönemi Paketi" src/` = 0; iyzico sepet adında marka iki kez geçmez; **merge Bilal'in test ödemesinden sonra** | S | onaylı — dal `odeme/paket-adi`; **ad seçimi CEO'da** (§7/1) | `24-ceo-kapanis.md` A2 · `27-marka-tescil-ve-paket-adi.md` §2.4 (eski #13) |
| **17** | Kalan marka metin düzeltmeleri (SSS süre iddiası + footer kategori iddiası) | `page.tsx:136` "Tercih dönemi boyunca geçerli" — `/kosullar`'da böyle bir süre sınırı yok; `site-footer.tsx:49` "YKS Tercih Robotu 2026" `vizyon.md:22`'nin reddettiği kategori, ayrıca "tercih robotu" ES EĞİTİM adına 2000/08210 ile tescilli | `grep -rn "Tercih dönemi boyunca" src/` = 0; footer kategori iddiası yerine ne yaptığımızı söyleyen ifade; garanti/olasılık dili yok | XS | hazır (CEO tek satır onayı) | `27-marka-tescil-ve-paket-adi.md` CEO listesi #5–#6 |
| **18** | `/sonuc` sayfasına `<h1>` | Sayfada hiç `<h1>` yok — erişilebilirlik ve SEO borcu | `/sonuc` sunucu HTML'inde tam 1 adet `<h1>` | XS | onaylı — dal `a11y/sonuc-h1` | `24-ceo-kapanis.md` A3 |
| **19** | Satıcı kimliği sayfası — placeholder'lı taslak | Para alan sitede satıcının kim olduğunu söyleyen tek satır yok (`grep` = 0); "fatura/makbuz" kelimesi hiç geçmiyor | Sayfa var, footer'dan linki var, 5 alan `TODO-BILAL` işaretli; Bilal bilgileri yazınca tek commit'le yayına hazır | S | onaylı — `guvenlik-uyum`, dal `uyum/satici-kimligi` | `24-ceo-kapanis.md` A8 |
| **20** | İçerik dalga takvimi: 14 konu, 4 dalga (24 Eyl / 1 Eki / 8 Eki / 15 Eki) | Haftada 4 yazı hızı; #7 çıkmadan #8 yazılamaz, #18 A4 merge edilmeden hiç yazılamaz | Bir dalga, editörün o dalganın **tüm** yazılarını onayladığı gün kapanır; kapanmadan sonraki dalga başlamaz; dalga başına en çok 4 yazar | M (süren) | onaylı | `25-seo-duzeltme.md` §3 (eski #3'ün yerine) |
| **21** | Güncellenen her yazıya `guncelleme: <ISO tarih>` frontmatter kuralı | `sitemap.ts:47` `lastModified` değerini `y.guncelleme ?? y.tarih`'ten alıyor → alan yoksa Google güncellemeyi görmez; `veliler-icin-tercih-rehberi` bu gece değişti, alan kontrol edilmedi | Değişen her yazıda alan var; kural `AGENTS.md`'nin içerik bölümünde; `grep -L "guncelleme:"` ile değişen dosya listesi boş | XS | hazır | `25-seo-duzeltme.md` §4/T40 |
| **22** | Mevcut 28 yazıdaki `/tercih-robotu` linki (301'e giden ölü CTA) | 42 yazıda 682 link tarandı, 0 kırık hedef; tek sorun `/tercih-robotu` 301 — 32 geçişin 4'ü düzeltildi, **28'i duruyor** | `grep -rn "/tercih-robotu" content/rehber/` = 0; yalnız `href` değişir, içerik değişmez; tek commit | XS | hazır (`[KARAR]` — yalnız href; metindeki "tercih robotu" **ifadesi** `[BİLAL]`, §7/6) | `20-editor-denetimi.md` §5 |
| **23** | `veri-kalite.ts`'e 2 ZORUNLU + 1 BİLGİ kontrolü | Üç kir bu gece elle bulundu; bugün `scripts/veri-kalite.ts:145-150` yalnız bilgi satırı basıyor, çıkış kodunu etkilemiyor. **Not:** veri mühendisinin "`yerlesen>kontenjan` ZORUNLU olsun" önerisini değiştirdim — bugün satırların %55'i bu koşulu ihlal ediyor, zorunlu yapılırsa her koşu kırılır | ZORUNLU: (a) aynı baz kurum adında iki `unitur`, (b) TR dışı `il` × TR `unitur` çelişkisi → çıkış kodu ≠ 0; BİLGİ: `yerlesen>kontenjan` **oranı** basılır ve 0'a düştüğü gün T14 tetiği açılır | S | hazır | `26-veri-kalitesi.md` §5–§6 (ürün düzeltmesiyle) |
| **24** | `refresh.ts --yer-esitle`: `il`/`fakulte` UPDATE yolunda da tazelensin | Kök neden #9'un tekrarını üretiyor: bu alanlar yalnız INSERT'te yazılıyor, aynı kir 2027'de yeniden birikir | Bayrak önce listeler, sonra yazar; koşudan sonra #9'un iki kabul sorgusu hâlâ tutar; `--yil`/`--db` kilidi korunur | M | aday | `26-veri-kalitesi.md` §6 |
| **25** | `refresh --isim-esitle` koşusu (vakıf burs etiketi) | A5 cevabı: kırılım **var**, etiket `birimAdi` içinde geliyor (`refresh.ts:37-39`). 2026'da yeni açılan vakıf satırlarının %93,7'si etiketli, eskilerin yalnız %14,2'si — fark bayrağın varsayılan kapalı olmasından | Koşu sonrası vakıf lisansta etiketsiz satır oranı düşer ve sayı raporlanır; #10'un kategori eşlemesi aynı koşuda yeniden sayılır | M | hazır (T11 kararı §7/4) | `26-veri-kalitesi.md` §4 |
| **26** | CTO artıkları: tadımlık ölçüm notu + eşiği (B1+B5) | G1 `tadimlik_goruntulendi` serisini kırıyor (olay ~2.200 px aşağıdaydı, ilk ekrana çıkıyor); not bu gece `tadimlik-satiri.tsx` yorumunda kaldı çünkü G2 `analitik.ts`'te bitişik satıra dokunuyor. Ayrıca "görüntülendi" artık ziyaretle eşitleneceği için huni değeri düşecek | Not `analitik.ts`'in `OlayAdi` yorumunda (`program_eklendi` geleneği); anlamlı ölçüt "tadımlık CTA tıklaması / görüntülenmesi" oranı olarak tanımlı | XS | aday | `28-cto-sartname.md` B1, B5 |
| **27** | Kredi-bitti hatırlatma e-postası paketliyi de tarıyor | `kredi-hatirlatma.ts:29-38` `hasPaket` ayırmıyor; metin "listenin tamamını açmak istersen" diyor (`eposta.ts:188`) — paketliye yanlış. G3 öncesinde de var olan hata | Sorguda `hasPaket = false` koşulu ya da ayrı metin dalı; paketliye giden e-postada "listenin tamamını açmak" ifadesi geçmez | S | aday | `28-cto-sartname.md` B3 |
| **28** | `ACIK_SATIR` sabiti client-safe modüle ayrılsın | `rapor-maske.ts` `server-only`; istemci metinleri sayıyı tek kaynaktan okuyamıyor, `liste-uretici.tsx:274` "3 kredi"yi elle yazıyor → maske değişirse metin sessizce yanlışlanır | Sabit tek modülden okunur; `grep -rn "3 kredi" src/` elle yazılmış sayı döndürmez; maske sayısı değişince tüm metinler değişir | S | aday | `28-cto-sartname.md` B4 |
| **29** | `liste-uretici.tsx:263-285` ölü `hasPaket` dalı | G3 sonrası paketli hiç `KREDI` kodu almayacağı için "+30 kredi yükle" dalı ölü koda dönüşür; zararsız ama tutarsız. Bilal'in dosyası olduğu için bu gece dokunulmadı | Dal kaldırılır ya da yorumla "erişilemez" işaretlenir; paketsiz akış bit-bit aynı | XS | aday (Bilal'in dosyası — kendi commit'inden sonra) | `28-cto-sartname.md` B2 |
### 5.3 Tetikli satırlar (sırada yer tutmaz)
| # | İş | Tetik | İzleyen | Kaynak |
|---|---|---|---|---|
| 12 | QA'nın koşamadığı girişli senaryolar (liste üretimi ×2, 5 soru, ödeme, 390 px) | Bilal'in canlı test ödemesi oturumu (CEO §E/2) | `qa-muhendisi` | `01-e2e-test.md` |
| T1 | İkinci alan (DGS/KPSS) | 2027 YKS sezonunda **100 tamamlanmış ödeme** | `ceo` | §A/T1 |
| T2 | Sosyal kanıt şeridinin `/paket`'e taşınması | Üretilen toplam liste sayısı **25** | `urun-yoneticisi` | §A/T2 |
| T3 | Taksit (3 ve 6, tek seferde) | **10 tamamlanmış ödeme** | `guvenlik-uyum` + `yazilimci` | §A/T3 |
| T4 | Fiyat / maske / `/paket` CTA metninin yeniden değerlendirilmesi | `/odeme` sayfasını **30 kişi** görür **veya** 10 tamamlanmış ödeme | `ceo` | §A/T4, R5 |
| T5 | Makbuz / "ödeme alındı" e-postası | Bilal'in test ödemesi başarıyla tamamlandığı gün (satıcı kimliği satırlarıyla tek commit) | `yazilimci` | §A/T5 |
| T6 | "Listeyi veline gönder" + veli e-postası (KVKK onay metniyle) | **1 Nisan 2027** veya 10 tamamlanmış ödeme | `urun-yoneticisi` (PRD) | §A/T6 · bu rapor §6 |
| T7 | Ana sayfa kıyas ekseninin MEB'in ücretsiz danışmanlığına çevrilmesi | **29 Eylül 2026** | `marka` | §A/T7 |
| T8 | `/il/[slug]` bağımlı yazı (#18) ve il kırılımlı içerikler | #9'un temizliği merge edildiği gün | `seo-geo` | §A/T8 |
| T9 | Öğretmenlik branş yazısı | **24 Eylül dalgası**; atama/istihdam iddiası yok, ikinci okuma editörde | `rehber-yazari` | §A/T9 |
| T11 | Vakıf burs kırılımlı yazı | A5 cevabı **geldi ve "kırılım var"** → CEO tek satırıyla 24 Eyl dalgasına girer (§7/4) | `ceo` | §A/T11 · `26-veri-kalitesi.md` §4 |
| T12 | LLM eval seti | Prompt ya da model değişikliği yapılacak **ilk gün** | `yapay-zeka-muhendisi` | §A/T12 |
| T13 | Satıcı kimliği bilgilerinin yayına girmesi | Bilal 5 alanı doldurduğu gün (#19 taslağı hazır bekler) | `guvenlik-uyum` | §A/T13 |
| **T14** | **Doğru doluluk paydasının kurulması** (`kontenjanToplam<yıl>` kolonu + gerçek doluluk göstergesi) | YÖK Atlas API'si kota **kontenjan** kırılımını (`obk/sgy/dprm`) yeniden yayımladığı gün — göstergesi: #23'ün BİLGİ kontrolünde `yerlesen>kontenjan` oranının 0'a düşmesi | `veri-muhendisi` | bu rapor §4.2 · `detay.ts:22` |
| **T15** | Prompt havuzundan `yerlesen<yıl>` alanının çıkarılması / yeniden tanımlanması | T12 ile aynı gün (ilk prompt değişikliği) — model bugün `rapor-havuzu.ts:184-185` ile iki uyumsuz nüfusu birlikte görüyor, `ai/rapor.ts:77` "kontenjan/yerleşen hareketini gözet" diyor | `yapay-zeka-muhendisi` | bu rapor §4.3 |
| **T16** | Marka tescil başvurusu + `kolaytercih.com.tr` alınması | Satıcı kimliği maddesi (CEO §E/3) kapandığı gün — `[BİLAL]`, sırası ondan sonra; engel kontrolü **bitti: görünür engel yok** | `marka` | `27-marka-tescil-ve-paket-adi.md` §1 |
---
## 6. Bir daha açılmaz (backlog'a konmaz)
> Bu liste **kanıt gelmeden** yeniden önerilemez. Yeniden açılması için gereken şey tartışma değil, satırda yazan veridir.
| Ne | Neden kapalı | Yeniden açılma yolu |
|---|---|---|
| **LGS alanı** | MEB'in ücretsiz, resmî, yapay zekâ destekli LGS robotu var; ücretli ürünün rekabet edeceği yer değil | Yok — kalıcı |
| **Ayrı `/veli` sayfası** | Tek veli okuru yokken ikinci giriş yüzeyi bakımı; kanonik veli yüzeyi `veliler-icin-tercih-rehberi.md` + küme CTA'sı | Yok — kalıcı. Veliye dokunma işi T6'da (düğme + e-posta), **sayfa olarak değil** |
| **Mobil yapışkan alt çubuk** | 95 ziyaret/hafta; mevcut CTA'lar zaten ekranda; ekran alanı yiyen over-engineering | Yok — kalıcı (eski backlog #4) |
| **`/paket` girişsiz birincil CTA'sının fiyat + satın alma fiiline çevrilmesi** | 21 Eyl'de Bilal onayladı; kanıt olarak gösterilen kullanıcı karardan **önceki** sürümü gördü | T4 tetiği (payda oluşunca) |
| **Deneme maskesinin 3'ten büyütülmesi / 299 TL'nin indirilmesi** | Fiyatı gören hiç kimse ödeme ekranına varamadı; bilinmeyen sayının yerine başka bilinmeyen sayı koymak veri üretmez | T4 tetiği |
| *(Bu gece kapananlar — yeniden yazma)* | KYK burs/kredi yazısı (yayında) · SEO'nun "bu hafta" üç yazısı (dosyada) · `netler` çerçevesi düzeltmesi (A6, plan 9 yerde düzeltildi) · TÜRKPATENT engel kontrolü (A9: engel yok) · Search Console kök nedeni (C4 kuralları yazıldı) | — |
---
## 7. Karar bekleyenler (hepsi CEO masasında — Bilal'in kuyruğuna eklenmedi)
| # | Karar | Kimin | Tavsiyem |
|---|---|---|---|
| 1 | **Paket adı:** "KolayTercih Paketi" (CEO A2) mı, "Tercih Listesi Paketi" (marka önerisi) mi; `odeme-actions.ts:74` öneki kalsın mı | `ceo` | **"Tercih Listesi Paketi"** — sezondan bağımsız *ve* ne alındığını söylüyor; önek kalır, marka tekrarı olmaz |
| 2 | **Tooltip düzeltmesi (#14)** onayı ve sıraya alınması | `ceo` `[KARAR]` | **Evet, ilk sıraya** — ödenmiş ekranda kendi içinde çelişen cümle; XS |
| 3 | **Veri düzeltme betiği (§3.6)** onayı: 100 `unitur` + 320 `il` satırı | `ceo` | **Evet** — sıralama/kontenjan verisine dokunmuyor, geri alma tek `cp`; T8 ve #18 buna bağlı. (Veri mühendisi Bilal'e sormuştu; geri alınabilir olduğu için CEO'da) |
| 4 | **T11:** A5 cevabı "kırılım var" çıktı → vakıf burs kırılımlı yazı 24 Eyl dalgasına girsin mi | `ceo` (tek satır) | **Girsin**, ama önce #25 (`--isim-esitle`) koşulsun; etiketsiz %80 satırla yazı yanlış tablo üretir |
| 5 | **Sihirbazın "Vakıf (burslu olursa)" kovası** KKTC/yurt dışı 1.256 satırı (havuzun %13,4'ü) kapsasın mı — bugün kapsıyor ve kullanıcıya söylenmiyor | `ceo` (ürün davranışı) | **Kapsamasın ya da açıkça yazılsın.** Bu iş sihirbaz davranışını değiştirir → kabul kriterine **"`/meraklisina` şeması aynı commit'te güncellenir"** maddesi zorunlu |
| 6 | **"Tercih robotu" ifadesi** 42 yazıda topluca değişsin mi (href düzeltmesi #22 zaten `[KARAR]`) | `[BİLAL]` — marka terimi | Sırası satıcı kimliğinden **sonra**; bu hafta sorulmuyor |
| 7 | **Devlet doluluk rakamı bu sezon yayımlanmasın** kuralı kayda geçsin mi (editör iki yazıda zaten uyguladı) | `ceo` | **Geçsin** — kural: doluluk oranı yalnız KKTC/vakıf için; devlet satırlarında "kontenjanı dolan program payı" kullanılır |
---
## 8. Sıradaki 5 iş (23–29 Eylül penceresi) ve gerekçesi
Ölçüt sırası: (1) sözü bozan yanlış bilgi → (2) sezon takvimi → (3) ölçülebilir huni etkisi → (4) kurucu zamanı. **Bu gecenin kod sırası (G1 → G3 → G4 → G2+G5 → A2) değişmiyor**; aşağıdaki liste onun *ardından* gelen penceredir.
| Sıra | İş | Gerekçe | Ölçüt |
|---|---|---|---|
| 1 | **#14 doluluk tooltip'i** | Ödenmiş ekranda, %64,3 satırda kendi içinde çelişen cümle. XS, tek ternary, geri dönüşü sıfır | (1) yanlış bilgi |
| 2 | **#10 tadımlık kategori kaçağı** | G1 tadımlığı `/sonuc`'un ilk ekranına taşıyor; sanat/medya seçen öğrenciye makine programı göstermek artık **ilk izlenim**. Ödeme öncesi tek gerçek önizlemenin doğruluğu | (1) yanlış bilgi + (3) huni |
| 3 | **#15 `/rehber` küme başlıkları (A1)** | SEO dalga 2 **1 Ekim**'de 4 yazı daha ekliyor; A1 merge edilmezse dizin duvara dönüyor. Takvim penceresi sabit | (2) sezon/takvim |
| 4 | **#6 IndexNow (T39)** | Kuyruk günlük kotayı aşıyor (11 bekleyen, kota ~10-13) ve haftada 4 yazı geliyor; elle bildirim kurucu zamanı yakan darboğaz | (2) takvim + (4) kurucu zamanı |
| 5 | **#9 `il`/`unitur` temizliği** | T7 tetiği **29 Eylül**; #18 yazısı bu temizliğe kilitli; ayrıca sihirbazın devlet/vakıf filtresi bugün 100 satırı yanlış tarafa koyuyor | (2) takvim + (1) yanlış bilgi |
Listeye **girmeyenler ve nedeni:** #5 (gerçek 404) — M boy, takvim baskısı yok; #8 (üniversite zenginleştirme) — Bilal'in ön koşulu; #27/#28/#29 — XS/S ama kullanıcıya bugün görünmüyor; T-satırları — tetikleri açılmadı.
---
## 9. Görev 3 — Kullanıcı yolculuğu notu: ödeyici veli (tek paragraf)
Ödeyen kişi veliyse, 2027 tercih dönemine kadar ürünün veliye **üç anda** dokunması gerekir ve bugün üçünün de karşılığı eksik: **(a) Kilit anı** — öğrenci maskeli listeyi gördüğü ekranda (`listem-govde.tsx:288,369`) veliye gidecek tek bir yol olmalı ("listeyi veline gönder"); bugün **yok**, o ekrandaki tek çıkış `/paket?kaynak=kilit` ve orada duran kişi kartı olmayan 18 yaşındaki öğrenci. **(b) Ödeme anı** — veli ödeyebilmek için bugün öğrencinin hesabına giriyor (`odeme-actions.ts:37-40`, oturum öğrenciye bağlı), ve karşısında satıcının kim olduğunu söyleyen tek satır, makbuz ya da fatura kelimesi yok; bu anın parçaları **hazırlanıyor ama eksik** (#19 satıcı kimliği taslağı onaylı, T5 makbuz e-postası tetikli, T3 taksit tetikli). **(c) Teslim anı** — velinin listeyi okuyabilmesi; burada vaat ("Veliyle paylaşılabilir PDF rapor", `page.tsx:197`) teknik olarak **karşılanıyor** (`yazdir-butonu.tsx` tarayıcı yazdırması) ama veliye hitap eden tek cümle içermiyor, yani en ucuz iyileştirme burada: rapor çıktısının başına veliye yazılmış iki satırlık özet. Üçünün de kalıcı çözümü T6'ya (1 Nisan 2027 ya da 10 ödeme) bağlı; ayrı `/veli` sayfası **kalıcı olarak reddedildi** (R2) ve bu notun hiçbir maddesi onu geri getirmiyor — istenen üç **an**, bir sayfa değil.
---
## 10. Backlog'da ne değişti (sayıyla)
- **Kapanan:** 3 satır (#2, #3, #4 — biri kalıcı ret).
- **Birleşen:** 2 satır (#13 → #16; eski #7 → G2 kapsamıyla güncellendi).
- **Kapsamı büyüyen:** 2 satır (#9 üç kat, #6 P1→P0).
- **Eklenen:** 16 aktif satır (#14–#29) + 16 tetikli satır (12, T1–T16).
- **Backlog dışına çıkan:** 5 kalıcı ret + bu gece kapanan 5 iş (§6).
- Toplam: **10 → 26 aktif**, **0 → 16 tetikli**. Aktif sayı arttı ama "aday" sayısı azaldı: satırların 11'i `onaylı`/`hazır`/`dalda`, yani kabul kriteri yazılı.
---
## Bilal'den istenen
**Yok — yeni madde eklemedim.** CEO'nun `24-ceo-kapanis.md` §E'deki 3 maddesi (disk + içerik yayını · canlı uçtan uca ödeme · satıcı kimliği 5 satır + Search Console erişimi) aynen geçerli, tek `[BİLAL]` karar maddesi hâlâ satıcı kimliği bilgileri. Bu gecenin marka/veri/editör raporlarının Bilal'e sorduğu 6 soruyu §7'de CEO masasına taşıdım; ikisi (marka başvurusu, "tercih robotu" ifadesi) `[BİLAL]` olarak **T16'da sıraya alındı**, bu hafta sorulmuyor.
**Tek istisna — sıfır iş yükü:** sabah `BACKLOG.md`'yi işlerken §5'teki blok doğrudan yapıştırılabilir; başlık ve açıklama satırlarından yalnız "Durum:" satırı değişiyor (§5.1).

View File

@@ -0,0 +1,121 @@
# 34 — Yazılımcı G3 · `odeme/paket-vaadi` (paketliden liste/revizyon kredisi düşmez)
> Rol: `yazilimci` · Gece vardiyası, 22 Eylül 2026 sabah turu · Şartname: `28-cto-sartname.md` §G3 + `31-guvenlik-satici-kimligi.md` §2
> Dal: **`odeme/paket-vaadi`** · Taban: **`9bd448b`** (`main`) · Çalışma yeri: ana çalışma ağacı (`/Users/bilalgursen/Desktop/kolaytercih`)
> İşaret: **[D]** komut çalıştırılarak doğrulandı · **[Ç]** koddan çıkarım (koşturulmadı)
---
## Özet (5 madde)
1. **Tek `maliyet = user.hasPaket ? 0 : RAPOR_KREDI` değişkeni CTO'nun saydığı altı satırı birden kapattı** — iki harcama (`amount`), iki iade (`delta`), iki dönen bakiye (`kredi:`). `spendCredits`/`grantCredits` çağrılarının hiçbiri kaldırılmadı. [D]
2. **İade dalı koşullandı** — güvenlik ajanının "sızıntı garanti" dediği yol (`listeRevize` `hasPaket` kapısının arkasında + `revisionCount` yalnız başarıda artıyor + taze `requestId`) kapandı: paketlinin başarısız denemesi artık `delta: 0` yazıyor, bedava kredi üretmiyor.
3. **Arayüz sunucuyla aynı şeyi söylüyor** — `raporKredi` paketliye 0 iner, modal tek `ucretsiz` bayrağıyla üç kredi cümlesini değiştirir; `krediYeter`/`KrediYetersiz` mantığına dokunulmadı.
4. **Doğrulama üçlüsü temiz:** `next typegen` ✓, `tsc --noEmit` çıkış 0 ve **hiç çıktı yok**, `pnpm lint` çıkış 0 ve **hiç bulgu yok**. Şartnamedeki 6 kabul grep'i tek tek koşuldu, hepsi beklenen değeri verdi. [D]
5. **Kapsam tam olarak 3 dosya.** `git diff --name-only HEAD~2 HEAD` yalnız G3'ün üç dosyasını listeliyor; `credits.ts`, `liste-uretici.tsx`, `huni-semasi.tsx` ve çalışma ağacındaki başkalarına ait commit'lenmemiş dosyalar (`AGENTS.md`, `docs/ekip/KARARLAR.md`, `content/rehber/**`) **el değmemiş** — hâlâ `M`/`??` durumunda duruyorlar. [D]
---
## Dal ve commit'ler
`git checkout -b odeme/paket-vaadi main` ile `9bd448b` tabanından açıldı (önceki dal `funnel/sonuc-ilk-ekran` — G1'in dalı; ona dokunulmadı, commit alınmadı).
| SHA | Mesaj | Dosya |
|---|---|---|
| `4acfd27` | `fix(kredi): paketliden liste ve revizyon kredisi düşmez` | `src/features/rapor/rapor-actions.ts` |
| `43b6cec` | `fix(listem): fark modalı paketliye kredi bedeli göstermez` | `src/features/rapor/components/listem-icerik.tsx`, `src/features/rapor/components/tercih-degisti-modali.tsx` |
`[Bilal]` commit'i yok (şartname öyle diyor: paket içeriği kararı CEO'da verilmişti).
Push yok, merge yok, `main`'e commit yok. Yıkıcı git komutu (`reset`/`checkout --`/`restore`/`clean`/`stash`) **hiç çalıştırılmadı**; dosyalar yola tek tek verilerek eklendi (`git add -A` kullanılmadı).
### Dokunulan satırlar
**`rapor-actions.ts`** (satır numaraları değişiklik sonrası):
- `:158` yeni `const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;` (+ 6 satırlık gerekçe yorumu) — `listeOlusturKilitli`
- `:163` `amount: maliyet` · `:225` `delta: maliyet` (iade) · `:254` `kredi: user.creditBalance - maliyet`
- `:300` ikinci `const maliyet = …` (+ yorum: kapı yüzünden burada daima 0, kapı gevşerse davranış bozulmasın) — `listeRevize`
- `:304` `amount: maliyet` · `:360` `delta: maliyet` · `:382` `kredi: user.creditBalance - maliyet`
- **Değişmeyen:** `:173` ve `:314` hata metinlerindeki `${RAPOR_KREDI} kredi gerekli` (bu dallara yalnız `maliyet > 0` iken erişilir), `krediBittiIsaretle`, `uretimKilidiAl/Birak`, `reports` yazımı, maskeleme dalları, `refId` zinciri.
**`listem-icerik.tsx:167`** — `raporKredi={RAPOR_KREDI}` → `raporKredi={/* yorum */ user.hasPaket ? 0 : RAPOR_KREDI}`. (`=== true` **yazılmadı**; SQLite 0/1 temsili ile de doğru çalışır — şartname Risk #1.)
**`tercih-degisti-modali.tsx`** — `:135` `const ucretsiz = raporKredi === 0;`; `:193` açıklama ("…güncelleme paketine dâhil, kredi düşmez."); `:263` "Güncelleme N kredi; bakiyen …" satırına `!ucretsiz` koşulu; `:290` buton metni ücretsizken "Listemi güncelle" (ok ikonu deseni aynen: metin sonunda `<ArrowRight className="size-4" aria-hidden />`). Ayrıca dosyanın tepesindeki "3 kredi" diyen eskimiş davranış yorumu güncellendi — o yorum dosyanın davranış belgesi.
---
## Doğrulama komutları ve çıktıları
```
$ pnpm exec next typegen
Generating route types...
✓ Types generated successfully
$ pnpm exec tsc --noEmit
(çıktı yok) TSC_EXIT=0
$ pnpm lint
> kolaytercih@0.1.0 lint
> eslint
(bulgu yok) LINT_EXIT=0
```
`pnpm install` ve `pnpm build` **koşulmadı** (disk kısıtı, orkestratör talimatı). Dev sunucusu açılmadı, tarayıcıda doğrulama yapılmadı.
---
## Kabul kriterleri (şartname §G3)
| # | Kriter | Sonuç | Nasıl doğrulandı |
|---|---|:--:|---|
| 1 | `grep -c "spendCredits(" rapor-actions.ts` = 2 | ✔ | **2** [D] |
| 1 | `grep -c "grantCredits(" rapor-actions.ts` = 2 | ✔ | **2** [D] |
| 2 | `grep -c "hasPaket ? 0 : RAPOR_KREDI"` = 2 | ✔ | **2** [D] |
| 2 | `amount: maliyet\|delta: maliyet` → 4 satır | ✔ | `163, 225, 304, 360` [D] |
| 2 | `delta: RAPOR_KREDI\|amount: RAPOR_KREDI` = 0 | ✔ | **0** [D] |
| 2 | `creditBalance - RAPOR_KREDI` = 0 | ✔ | **0** [D] |
| 3 | `refId: requestId\|refId: input.requestId` → 4 satır | ✔ | `165, 227, 306, 362` — zincir değişmedi [D] |
| 4 | `listem-icerik.tsx` `raporKredi={…}` koşullu | ✔ | `:167` `user.hasPaket ? 0 : RAPOR_KREDI` [D] |
| 4 | `grep -c "ucretsiz"` ≥ 3 | ✔ | **4** (`135, 193, 263, 290`) [D] |
| 5 | `grep -rn "danışman sorusu" src/` — hardcoded 60 yok | ✔ | Arayüzdeki üç sonuç (`app/page.tsx:201`, `listem-govde.tsx:345`, `paket-satinal.tsx:40`) **hâlâ `URUNLER.paket.credits` / `paketKredi` interpolasyonu**; sayı hiçbirinde sabit değil. Toplam eşleşme 5'e çıktı çünkü iki yeni eşleşme benim yazdığım **kod yorumu** (`rapor-actions.ts:153`, `tercih-degisti-modali.tsx:14`) — metin değil [D] |
| 6 | Kapsam dışı dosyalar el değmemiş | ✔ | `git diff --name-only HEAD~2 HEAD` = tam olarak 3 dosya; `credits.ts` / `liste-uretici.tsx` / `huni-semasi.tsx` **yok** [D] |
| — | `typegen && tsc --noEmit && lint` | ✔ | Yukarıdaki çıktılar [D] |
**Not — kriter 6'nın yazımı:** şartnamedeki `git diff --name-only HEAD~2` (HEAD yazılmadan) çalışma ağacını da kapsadığı için başkalarının commit'lenmemiş dosyalarını (`AGENTS.md`, `KARARLAR.md`, veli yazısı) listeliyor. Commit kapsamını gösteren doğru biçim `git diff --name-only HEAD~2 HEAD`; ikisi de koşuldu, ikinci biçim 3 dosya veriyor.
---
## Güvenlik ajanının üç koşulu — kodda nerede karşılandı
| Koşul (`31-guvenlik-satici-kimligi.md` §2) | Karşılandığı yer |
|---|---|
| **1.** İade dalı aynı koşula bağlansın; `grantCredits` çağrısı ve `refund` satırı **kaldırılmasın** | `rapor-actions.ts:223-228` (`listeOlustur` iadesi, `delta: maliyet`) ve `:358-363` (`listeRevize` iadesi, `delta: maliyet`). İki çağrı da yerinde, `refId` aynı; DUPLICATE dalındaki "önceki deneme iade edilmişti" sorgusu (`:179-192` ve `:320-333`) değişmedi |
| **2.** Dönen bakiye de koşullansın (`:243`, `:363`) | `rapor-actions.ts:254` ve `:382` → `kredi: user.creditBalance - maliyet` |
| **3.** `hasPaket` **tek yerden**, zaten okunmuş `user` nesnesinden okunsun; ikinci DB okuması eklenmesin | `rapor-actions.ts:158` (`listeOlusturKilitli`'ye parametre olarak gelen `user`) ve `:300` (`listeRevize`'de `getCurrentUser()` ile bir kez okunan `user`). Yeni sorgu/okuma eklenmedi; harcama ile iade aynı fonksiyon kapsamındaki **aynı** `maliyet` sabitini kullanıyor |
Ek olarak şartnamenin "çağrı kaldırılmaz" kısıtı korundu: `credit_ledger`'daki `uniqueIndex("ledger_reason_ref").on(reason, refId)` (`src/lib/appdb/schema.ts:133`) çapası aynen yerinde, paketliye `delta = 0` satır yazılıyor ve aynı `requestId` ikinci kez `DUPLICATE` dönüyor [Ç — DB ile koşturulmadı, QA'nın duman testine kaldı].
---
## Şartnameden sapmalar
1. **`tercih-degisti-modali.tsx`'in dosya başı yorumu da güncellendi** (şartname 129/188/250/275 satırlarını sayıyordu). Gerekçe: o yorum "yeniden kurulum … 3 kredi" diyerek artık yanlış olan bir davranışı belgeliyordu; AGENTS.md'nin "belge dekor değildir" prensibiyle aynı commit'te düzeltildi. Davranışa etkisi yok.
2. **`:250` satırına `!ucretsiz` koşulu eklendi.** Şartname "ücretsizse bu satır gösterilmez" diyordu; `raporKredi = 0` iken `krediYeter` zaten daima doğru olduğu için satır teknik olarak **zaten** render edilmiyordu [Ç]. Koşul niyeti açık etmek ve `krediYeter` hesabı ileride değişirse cümlenin sızmaması için yine de yazıldı.
3. **`:129 krediYeter` değiştirilmedi** (şartname de dokunulmamasını istiyordu) — yalnız altına türetilmiş `ucretsiz` bayrağı eklendi.
4. Başka sapma yok; `huni-semasi.tsx`'e dokunulmadı (CTO doğrulaması: G3 sihirbaz/liste mimarisini değiştirmiyor), paket adına (A2) dokunulmadı, `credits.ts`/`liste-uretici.tsx` açılmadı bile.
---
## Merge sonrası doğrulanması gerekenler (QA / `guvenlik-uyum`)
1. **Oturumlu duman testi (paketli kullanıcı):** liste üretimi sonrası `user.credit_balance` **değişmiyor**, `credit_ledger`'a `reason='report_generate', delta=0` satırı yazılıyor; ekranda görünen bakiye de düşmüyor. Aynısı revizyonda (`reason='report_revision'`).
2. **Başarısız üretim (paketli):** yapay zekâ hatası tetiklenince `reason='refund', delta=0` satırı yazılıyor ve bakiye **artmıyor** — güvenlik ajanının B2 sızıntısının kapandığının tek gerçek kanıtı budur.
3. **Idempotency:** aynı `requestId` ile ikinci üretim `DUPLICATE` yoluna giriyor; iade satırı varsa "tekrar dener misin", yoksa `SURUYOR`. `spendCredits`'in `amount: 0` ile `rowsAffected = 1` döndürmesi (yani `INSUFFICIENT` **dönmemesi**) SQLite'ta fiilen teyit edilmeli — şartnamede de [Ç] işaretliydi, ben de koşturmadım.
4. **Paketsiz kullanıcıda davranış bit-bit aynı:** 3 kredi düşer, yetersizse `KREDI` + `krediBittiIsaretle`, modal eski metinleri gösterir.
5. **Bilinen ve kapsam dışı bırakılan tutarsızlıklar:** `liste-uretici.tsx:263-285`'teki `hasPaket` "kredi yetersiz/+30 kredi yükle" dalı liste üretimi için artık ölü kod (Bilal'in dosyası → dokunulmadı, backlog #B2); `kredi-hatirlatma.ts:36` + `eposta.ts:188` paketliye yanlış metin gönderebilir (G3 öncesinden var, backlog #B3).
6. Para yüzeyine dokunuldu → **`guvenlik-uyum` denetimi merge öncesi zorunlu** (şartname de öyle diyor; bu dal için §2'deki üç koşul karşılandı, denetimin işi doğrulamak).
---
## Bilal'den istenen
1. **Yok** — G3 tamamlandı, `[Bilal]` kararı gerektiren bir satır çıkmadı. Merge kararı sabahki entegrasyon turunda.

View File

@@ -0,0 +1,122 @@
# 35 — Güvenlik & uyum denetimi: G3 · `odeme/paket-vaadi` (merge öncesi zorunlu denetim)
> Rol: `guvenlik-uyum` · Gece vardiyası, 22 Eylül 2026 sabah turu
> Denetlenen: dal `odeme/paket-vaadi`, commit'ler `4acfd27` + `43b6cec`, taban `9bd448b` (`main`)
> Kaynaklar: `34-yazilimci-g3.md`, `31-guvenlik-satici-kimligi.md` §2, `28-cto-sartname.md` §G3
> Yöntem: **yalnız okuma.** Kod değiştirilmedi, dal değiştirilmedi, commit/`git add` yok, yıkıcı git komutu yok. Diff `git show`/`git diff` ile okundu. Proje DB'sine yalnız `sqlite3 -readonly` ile bakıldı.
> İşaret: **[D]** doğrulandı (komut çıktısı / dosya:satır) · **[Ç]** koddan çıkarım (koşturulmadı)
---
## Özet (5 madde)
1. **Kritik bulgu yok; üç koşulun üçü de kodda karşılanmış.** İade dalları yerinde ve tutar koşullu (`rapor-actions.ts:223-228`, `:358-363` → `delta: maliyet`), dönen bakiye koşullu (`:254`, `:382`), `hasPaket` tek yerden — `getCurrentUser()`'ın istek başına React-cache'lenmiş **tek satır okumasından** geliyor, yeni DB sorgusu eklenmemiş [D].
2. **Denetimin en kritik sorusu — `amount: 0` idempotency çapasını kaybettirir mi — CEVAP: HAYIR, ve bu artık [Ç] değil [D].** Projenin kendi sürücüsüyle (`@libsql/client@0.17.4`) izole bir scratch DB'de koşturdum: bakiyesi 0 olan kullanıcıda `UPDATE … credit_balance - 0 … WHERE credit_balance >= 0` → **`rowsAffected = 1`** (hiçbir kolon değeri değişmese bile 1; SQLite MySQL gibi "changed rows" saymıyor). `delta = -0` satırı tabloya **integer 0** olarak yazılıyor ve aynı `(reason, ref_id)` ile ikinci insert `SQLITE_CONSTRAINT: UNIQUE constraint failed` ile reddediliyor. Yani satır gerçekten yazılıyor, UNIQUE çapası duruyor, `INSUFFICIENT` yanlış alarmı yok.
3. **Sızıntı yolu kapalı, paketsiz davranış bit-bit aynı.** Paketlinin başarısız üretimi/revizyonu `delta 0` `refund` satırı yazıyor, bakiye artmıyor; taze `requestId` ile sınırsız tekrar da kredi üretmiyor. Paketsizde `maliyet = RAPOR_KREDI` olduğu için harcama, iade, hata metni ve `krediBittiIsaretle` yolu değişmemiş [D].
4. **Yeni ve gerçek olan tek risk kredi değil, maliyet:** G3'ten sonra paketli kullanıcının liste üretiminde **hiçbir üst sınır kalmıyor** (eski tavan 60 kredi ÷ 3 ≈ 20 üretimdi). Üstelik `listeOlusturKilitli` `reports`'u `revisionCount: 0` ile üzerine yazdığı için (`rapor-actions.ts:247`) MAX_REVIZYON=2 tavanı da "yeniden üret → 2 revizyon → yeniden üret" döngüsüyle sıfırlanabiliyor. Repoda hiçbir rate limit yok (`grep -rln "rateLimit\|rate-limit\|ratelimit"` src/ → **0 dosya** [D]); tek fren kullanıcı başına üretim kilidinin serileştirmesi. **Merge engeli değil** (ücretli kullanıcı yüzeyi, CEO kararının doğal sonucu) ama kayda geçmeli — F1.
5. **Uyum tarafında G3 bir açığı kapatıyor:** `/paket` "60 Yapay Zeka danışman sorusu" diyordu (`paket-satinal.tsx:39-40`), gerçekte liste (3) + 2 revizyon (6) düşünce elde **51** soru kalıyordu. G3 sonrası 60 gerçekten 60. Mesafeli Sözleşmeler Yön. m.5/1-a (hizmetin temel nitelikleri) bakımından "ön bilgilendirme × fiilî ifa" uyumsuzluğu kapanıyor — **G3 uyumu bozmuyor, iyileştiriyor.** *(Hukuki değerlendirme taslaktır: avukat teyidi gerekir.)*
---
## 1 · Üç koşul: doğrulama
| Koşul (`31-…` §2) | Hüküm | Kanıt |
|---|:--:|---|
| **1.** İade dalları yerinde + tutar koşullu | **KARŞILANDI** | `rapor-actions.ts:223-228` ve `:358-363`: `grantCredits({ … delta: maliyet, reason: "refund", refId })` — çağrı kaldırılmamış, `refId` aynı. DUPLICATE dalındaki "önceki deneme iade edilmişti" sorgusu (`:179-186`, `:320-327`) yalnız `(reason='refund', ref_id)` bakıyor, **delta'ya bakmıyor** → `delta 0` satırı bu çıkarımı aynen besliyor [D] |
| **2.** Dönen bakiye koşullu | **KARŞILANDI** | `:254` ve `:382` → `kredi: user.creditBalance - maliyet`. `grep -c "creditBalance - RAPOR_KREDI"` = 0 [D] |
| **3.** `hasPaket` tek yerden, yeni DB okuması yok | **KARŞILANDI** | `:158` ve `:300` → `const maliyet = user.hasPaket ? 0 : RAPOR_KREDI;`. `user` nesnesi `getCurrentUser()`'dan geliyor: `session.ts:27-35` **tek `SELECT *`**, `react/cache` ile istek başına bir kez. `hasPaket` ile `creditBalance` **aynı satır anlık görüntüsünden** okunuyor → harcama ile iade arasında yırtık okuma imkânsız. Diff'te yeni `appDb.select`/`query` yok [D] |
Ek doğrulamalar:
- `hasPaket` şemada `integer("has_paket", { mode: "boolean" })` (`appdb/schema.ts:20`) → drizzle gerçek `boolean` döndürüyor; yazılımcının `=== true` yazmaması **doğru** tercih, SQLite 0/1 temsilinde de truthiness doğru çalışır [D].
- Kapsam: her iki commit toplam **3 dosya**, `credits.ts`/`liste-uretici.tsx`/`huni-semasi.tsx` yok; çalışma ağacındaki başkalarına ait `M`/`??` dosyalar hâlâ commit'siz duruyor [D].
---
## 2 · `spendCredits(amount: 0)` / `grantCredits(delta: 0)` — koşturulmuş hüküm
Şartname de yazılımcı raporu da bu noktayı **[Ç]** bırakmıştı. İzole scratch DB'de (proje DB'sine **yazılmadı**), projenin kendi sürücüsüyle koşturdum:
```
A) amount=0, balance=0 -> rowsAffected = 1 → INSUFFICIENT DÖNMEZ
B) hiçbir kolon değeri değişmiyor -> rowsAffected = 1 → SQLite matched-rows sayar
C) delta=-0 insert rowsAffected = 1
D) yazılan delta = {"delta":0,"t":"integer"} → -0 değil, temiz integer 0
E) aynı (reason, ref_id) ile ikinci insert: SQLITE_CONSTRAINT: UNIQUE constraint failed
(code SQLITE_CONSTRAINT, rawCode 2067) → idempotency ÇAPASI YERİNDE
F) refund delta=0 sonrası bakiye = 0 → kredi üretilmiyor
G) balance=-1, amount=0 -> rowsAffected = 0 → yalnız negatif bakiyede INSUFFICIENT
```
**Hüküm:**
- **Soru 2 (idempotency):** bozulmadı. `delta = 0` satırı gerçekten yazılıyor; `uniqueIndex("ledger_reason_ref").on(reason, refId)` (`schema.ts:133`) aynı `requestId` ile ikinci üretimi `DUPLICATE`'e düşürmeye devam ediyor. `uniqueIhlaliMi` bu hatayı yakalıyor (mesaj "UNIQUE" içeriyor, `credits.ts:22-40`) [D]. `refId` zinciri değişmedi (`refId: requestId` × 4, satır 165/227/306/362).
- **Soru 4 (`INSUFFICIENT`):** bakiyesi 0 olan paketli kullanıcı liste üretebiliyor. **Paketin vaadi ayakta.** Tek istisna satır G: bakiye **negatifse** `INSUFFICIENT` dönerdi — ama negatif bakiye ulaşılamaz: bakiyeyi yazan her yol `gte` ile korunuyor (`credits.ts:69`, `:110`), `grantCredits` yalnız ekliyor, dev paneli `Math.max(0, …)` uyguluyor (`lib/dev/actions.ts:83`, zaten `NODE_ENV === "production"`'da fırlatıyor) [D]. Lokal DB'de de min bakiye 5 ve 34 (`sqlite3 -readonly data/app.db`) [D].
---
## 3 · Bulgu tablosu
| # | Dosya:satır | Sorun | Somut senaryo | Önem | Düzeltme | Kesinlik |
|---|---|---|---|:--:|---|:--:|
| **F1** | `rapor-actions.ts:158` + `:247` (`revisionCount: 0` upsert); rate limit yok | Paketlide liste üretiminin **kredi freni kalktı**, yerine hiçbir sınır konmadı | 299 TL ödemiş kullanıcı (ya da hesabı ele geçiren biri) `/listem`'de sihirbaz tercihini değiştirip "Listemi güncelle"ye basar; her basış tam bir rapor LLM çağrısı, bedeli 0 kredi. Üretim kilidi yalnız **seri**leştirir, saymaz; bayat kilit eşiği 180 sn (`uretim-kilidi.ts:13`). Ayrıca her yeniden üretim `revisionCount`'u 0'a çekiyor → "2 revizyon hakkı" tavanı da döngüyle sıfırlanıyor. Eski tavan 60÷3 ≈ 20 üretimdi; şimdi tavan yok | **orta** | Bu dalda **değil** (kapsam dışı). Ayrı iş: `report_generate` ledger satırları zaten sayıyor → `spendCredits`'ten önce "son 24 saatte `reason='report_generate'` satır sayısı ≥ N ise `code: "SINIR"`" kapısı (N'i CEO belirler; 10 tartışma başlatır, 30 kimseyi rahatsız etmez). Alternatif ucuz fren: üretim kilidini başarıdan sonra 60 sn tutmak | DOĞRULANDI |
| **F2** | `credits.ts:174-176` (`krediBittiAt: null`) ↔ `rapor-actions.ts:223-228` | `delta = 0` iade de "kredi geldi" sayılıp bekleyen kredi-bitti hatırlatmasını iptal ediyor | Paketli kullanıcının 60 kredisi sohbette biter → `/api/soru` `krediBittiIsaretle` yazar (`route.ts:180`), 48 saat sonra top-up e-postası kuyruğa girer. Kullanıcı o arada bir liste üretir, üretim hata verir → `grantCredits(delta: 0, reason:"refund")` `krediBittiAt`'ı **null**'lar. Kredi gelmediği hâlde hatırlatma iptal olur; `krediHatirlatmaGonderildiAt` da hâlâ null olduğu için e-posta ancak kullanıcı bir kez daha sohbette duvara toslarsa yeniden kurulur. G3 öncesi bu doğruydu (iade gerçekten 3 kredi getiriyordu), G3 sonrası yanlış | **düşük** (gelir kaybı, güvenlik değil) | `credits.ts:174` → `...(opts.delta > 0 ? { krediBittiAt: null } : {})`. `credits.ts` bu dalın kapsamı dışında (CTO yasak listesi) → backlog | DOĞRULANDI |
| **F3** | `tercih-degisti-modali.tsx:254` + `:336-347` (`KrediYetersiz`) | Paketli için ölü dal; render edilirse "Güncelleme **0 kredi** ve bakiyen yetmedi" yazar | `durum = "kredi-yetersiz"` yalnız `code === "KREDI" \| "PAKET"` ile kuruluyor (`:115`). Paketlide `KREDI` artık imkânsız (bkz. §2), `PAKET`'i `listeOlustur` hiç döndürmüyor (yalnız `listeRevize` döndürür) → dal **bugün ulaşılamaz**. Ama `ucretsiz` bayrağı bu dala bağlanmadığı için, ileride bakiye negatife düşebilen bir yol açılırsa ekranda anlamsız cümle çıkar | **düşük** | Bu dalda şart değil. İstenirse tek satır: `:254`'teki üçlüye `!ucretsiz &&` eklemek ya da `KrediYetersiz` içinde `raporKredi === 0` dalını yazmak. Aynı sınıf ölü kod `liste-uretici.tsx:263-285`'te de var (backlog #B2, Bilal'in dosyası) | DOĞRULANDI |
| **F4** | `rapor-actions.ts:104` (`getCurrentUser`) → `:158` | `hasPaket` okuması ile harcama arasında paket satın alma yarışı | Kullanıcı `/listem`'de üretimi başlatır; tam o saniyede ikinci sekmede iyzico callback'i paketi yazar. Sunucu eski anlık görüntüyü gördüğü için 3 kredi düşer — paketli olmasına rağmen. Ters yön (paketliyken ücrete düşme) imkânsız, `hasPaket` true→false dönmüyor | **düşük** | Düzeltme önermiyorum: pencere milisaniyeler, zarar 3 kredi, G3 öncesinde de aynıydı (o zaman **her** paketliden düşüyordu). Kayda geçsin yeter | OLASI |
| **F5** | `credit_ledger` (veri, kod değil) | Ölçüm serisi kırılması | `report_generate` satırının `delta`'sı paketlide −3 → 0 oldu. Satır **sayısına** dayanan sorgular (ör. `04-uretim-engelleri.md` §5'teki deneme/iade kırılımı) etkilenmiyor; `SUM(delta)` ile "kaç kredi yandı/iade edildi" soran gelecekteki bir sorgu 22 Eylül'den öncesi ve sonrası için farklı şey ölçer | **bilgi** | Merge commit mesajında ya da `docs/odeme/iyzico.md` kenar notunda tek cümle | DOĞRULANDI |
| **F6** | süreç — çalışma ağacı | `HEAD` şu an **`odeme/paket-vaadi`** üzerinde; orkestratör beni "`funnel/sonuc-ilk-ekran` dalındasın" diye bilgilendirdi | G1 dalına devam eden bir sonraki ajan kendini G3 dalında sanmadan commit atarsa G1 işi G3'ün üstüne biner ve merge sırası bozulur. `git reflog`: `HEAD@{2}: checkout: moving from funnel/sonuc-ilk-ekran to odeme/paket-vaadi` — yazılımcı dönmemiş. (Aynı reflog'da `HEAD@{5}: reset: moving to HEAD~1` **G1 dalında**, G3 dalında yıkıcı komut **yok** — yazılımcının bu iddiası doğru) | **orta** (süreç) | Bir sonraki kod ajanı işe başlamadan orkestratör dalı açıkça söylesin/doğrulasın. Ben dal değiştirmedim (kurallar gereği) | DOĞRULANDI |
### Sızıntı yolları — tek tek (denetim sorusu 3)
| Yol | Sonuç |
|---|---|
| Paketli, başarısız üretim | `refund` satırı `delta 0` → bakiye **değişmez**. Kredi eklenmiyor [D: kod + scratch DB] |
| Paketli, başarısız revizyon, N kez tekrar | Her denemede taze `requestId` → her denemede yeni `(report_revision, id)` + `(refund, id)` çifti, **hepsi 0**. Sınırsız tekrar sınırsız kredi üretmiyor. `revisionCount` yalnız başarıda artıyor (`:374-380`) — bu da yalnız LLM maliyeti bırakıyor (F1) |
| Paketli, bakiyesi 0, liste üretimi | Çalışır (`INSUFFICIENT` dönmez) — paketin vaadi ayakta |
| Paketsiz | `maliyet = 3`: harcama, `KREDI` hatası + `krediBittiIsaretle`, iade, dönen bakiye, modal metinleri — **hiçbiri değişmedi**. Diff'te paketsiz yolu etkileyen tek satır yok [D] |
| Başkasının kredisiyle LLM | G3 yeni bir yetkilendirme deliği açmıyor: `listeOlustur`/`listeRevize` oturumu doğruluyor, `refId` tahmini başkasının raporunu **okutmuyor** (DUPLICATE dalı `kullanicininRaporu(user.id)` ile kendi raporuna bakıyor). Maliyet riski yalnız kullanıcının **kendi** hesabında ve F1'de anlatıldığı gibi |
---
## 4 · Muhasebe / mutabakat (denetim sorusu 5)
Bu gece verdiğim "bozmaz" hükmü kod yazıldıktan sonra **hâlâ geçerli** [D]:
- Bakiyenin tek kaynağı `user.credit_balance` kolonu; defteri toplayan hiçbir okuyucu yok (`grep -rn "creditLedger\|credit_ledger" src scripts` → tüm okumalar `findFirst`/`select id`, `SUM` yok).
- iyzico mutabakat sorgusu yalnız `l.reason IN ('purchase','topup') AND l.ref_id = o.id` (`docs/odeme/iyzico.md:84`). `report_generate`/`report_revision`/`refund` satırlarının `ref_id`'si istemcinin ürettiği `requestId`, `orders.id` değil → bu sorguya **hiç girmiyor**. 0 TL'lik hareket iyzico tarafında görünmüyor.
- `krediKaydiVarMi` de `reason`'ı şart koşuyor (`credits.ts:205-211`) → `delta 0` `refund` satırı bir siparişi "kredisi yazılmış" göstermiyor.
- Tek kenar etkisi F2 (kredi-bitti işaretinin silinmesi) ve F5 (ölçüm serisi).
---
## 5 · Arayüz ↔ kod uyumu (denetim sorusu 6)
| Yüzey | Gösterilen | Sunucuda olan | Uyum |
|---|---|---|:--:|
| Modal açıklaması (`tercih-degisti-modali.tsx:193-197`, paketli) | "…yeni liste bunun yerine geçer; güncelleme paketine dâhil, kredi düşmez." | `maliyet = 0`, bakiye sabit | ✔ birebir |
| Modal buton (`:290-292`, paketli) | "Listemi güncelle" (bedelsiz), ok ikonu metnin sonunda | 0 kredi | ✔ (AGENTS.md CTA deseni korunmuş) |
| Modal bakiye satırı (`:263-267`) | `!ucretsiz && !krediYeter` → paketliye hiç çıkmaz | — | ✔ |
| Modal, **paketsiz** (`:198-202`, `:292`, `:265`) | "…3 kredi düşer", "Listemi güncelle — 3 kredi", "Güncelleme 3 kredi; bakiyen N kredi" | 3 kredi düşer | ✔ değişmedi |
| `listem-icerik.tsx:167-172` | `raporKredi = user.hasPaket ? 0 : RAPOR_KREDI` — modalın tek kredi kaynağı, `raporKredi`'yi başka tüketen yok (`listem-govde.tsx:399` sadece geçiriyor) | aynı ifade sunucuda `:158`/`:300` | ✔ tek kaynak |
| Başlıktaki kredi pill'i (`user-nav.tsx:69`) | `creditBalance` | paketlide düşmüyor | ✔ artık tutarlı (G3 öncesi düşüyordu) |
| `KrediYetersiz` (`:336-347`) | paketliye "Güncelleme 0 kredi ve bakiyen yetmedi" derdi | dal ulaşılamaz | F3 — bugün görünmez |
| `liste-uretici.tsx:274` "Liste üretimi 3 kredi… +30 kredi yükle" | paketli dalı | dal ulaşılamaz | Bilinen ölü kod (backlog #B2), G3'ün değil |
| `paket-satinal.tsx:141-144` "liste 3 kredi" | yalnız **girişsiz** ziyaretçiye gösteriliyor | paketsiz için doğru | ✔ |
**Metin × kod uyumsuzluğu (yasal/pazarlama):** G3'ten sonra `/paket`'teki "60 Yapay Zeka danışman sorusu (her mesaj 1 kredi)" ilk kez **doğru**. Kalan tek uyumsuzluk kod değil e-posta: `kredi-hatirlatma.ts:36` paketliyi de `credit_balance < 3` filtresiyle yakalıyor ve `eposta.ts:175-190`'daki metin "listenin tamamını açmak… için kredi yükleyebilirsin" diyor — paketlinin listesi zaten tam açık. G3 öncesinden var (backlog #B3), G3 onu büyütmüyor ama F2 ile aynı dosyada çözülmeli.
---
## 6 · HÜKÜM
**Merge edilebilir.** Üç koşulun üçü de kodda karşılanmış, idempotency çapası (`UNIQUE(reason, ref_id)`) `amount/delta = 0` ile **fiilen** ayakta (koşturarak doğrulandı), paketliye kredi sızıntısı yok, bakiyesi 0 olan paketli liste üretebiliyor, paketsiz davranış bit-bit aynı, iyzico mutabakatı ve bakiye hesabı etkilenmiyor, arayüz sunucunun yaptığını söylüyor. Bu dalda düzeltilmesi gereken bir satır bulamadım.
Merge'e **engel olmayan**, ayrı iş olarak kuyruğa girmesi gereken üç şey (yazılımcıya şartname netliğinde):
1. **F1 — üretim tavanı (yeni dal, `credits.ts` + `rapor-actions.ts`):** `rapor-actions.ts`'te `spendCredits` çağrısından **önce**, `credit_ledger`'da `reason = 'report_generate' AND user_id = ? AND created_at > now-24h` sayısı ≥ N ise `{ ok:false, code:"SINIR", error:"Bugünlük liste üretim hakkın doldu; yarın devam edebilirsin." }` dön. N değeri CEO'nun; kilit/bayat-kilit mantığına dokunma, `revisionCount` upsert'ünü (`:247`) değiştirme.
2. **F2 — `credits.ts:174`:** `krediBittiAt: null` yalnız `opts.delta > 0` iken yazılsın (`...(opts.delta > 0 ? { krediBittiAt: null } : {})`). Aynı commit'te `kredi-hatirlatma.ts:36`'ya `eq(user.hasPaket, false)` eklenirse backlog #B3 de kapanır.
3. **F6 — süreç:** sabah entegrasyonuna geçmeden `HEAD`'in `odeme/paket-vaadi`'de durduğu bilinsin; G1'e devam eden ajan dalını açıkça doğrulasın.
---
## Bilal'den istenen
1. **Yok** — G3 denetimden temiz çıktı; merge kararı zaten senin kuyruğunda, bu rapor onun için ek bir soru üretmiyor. *(F1'in tavan sayısı CEO'ya sorulacak bir ürün kararı, sana değil.)*

View File

@@ -0,0 +1,237 @@
# 36 — Tasarımcı: navbar taşması + G1 merge öncesi denetimi
Tarih: 22 Eylül 2026 · Rol: `tasarimci` · Taban: `main` `9bd448b`
İşaret: **[D]** doğrulandı (canlı HTML / font metriği / hesap) · **[Ç]** koddan çıkarım · **[BİLAL]** karar Bilal'in
---
## Özet (5 madde)
1. **Navbar taşmasının kök nedeni tek satır değil, bir yapısal varsayım:** orta alan `absolute` olduğu için flex onu göremiyor, sağ küme `shrink-0` olduğu için çekilmiyor — çakışma sessiz. Tetikleyici ise `xl:inline`: **`max-w-6xl` konteyneri 1152 px'te kilitlendiği için `xl` (1280 px) hiç yeni yer açmıyor, ama o noktada ~229 px etiket geri geliyor.** [D, hesap aşağıda]
2. **P4 (`cb22faf`) dört ayrı genişlikte kırılma üretti:** ≥1280 px'te orta alanla çakışma (−28 … −220 px), 1024–1151 px'te dar bir bantta çakışma (−48 px), ve **640–1023 px'te header'ın 2 satırdan 3 satıra çıkması** (tasarımın kendi yorumu "lg altında 2 satır" diyor, `site-header.tsx:11`). 375 px'te de sınırda taşıyor.
3. **Önerilen düzeltme 2 satır:** `user-nav.tsx:59` ve `listem-butonu.tsx:39`'daki etiket span'lerinden **hem `xl:inline` hem `sm:inline`** kalkar. Bu etiketler yalnızca sığmadıkları iki bantta görünüyor. Kalan tek açık 1024–1151 bandı için ikinci, tek satırlık bir seçenek aşağıda.
4. **G1 merge edilebilir — ama bir düzeltmeyle.** Boş harita `null` olunca **hidrasyon CLS'i doğdu**: kayıtlı manuel listesi olan kullanıcıda sunucu 0 px, hidrasyondan sonra ~368 px harita sayfanın **tepesine** giriyor ve tadımlık + tablo aşağı kayıyor. Eski placeholder tam da bunu engelliyordu. G1 raporunda bu yok.
5. **Metinde bir artık kaldı:** buton "24 satırın tamamı" iddiasından arındırıldı ama **iki eleman yukarıdaki paragraf aynı vaadi sürdürüyor** — `tadimlik-satiri.tsx:135` "24 tercihlik listenin **her satırı** bu formatta kurulur". Maske girişsiz kullanıcıya 3 satır açıyor (`rapor-maske.ts:12`).
---
# İŞ 1 · Navbar taşması
## Yöntem — neden koddan yetinmedim, ne yaptım
Kural değişikliği geldi (tarayıcı serbest), ama bu oturumun araç setinde tarayıcı/önizleme aracı yok (`Bash`, `Read`, `Write`, `Edit`, `Skill`). `preview_stop` da çağıramıyorum, dolayısıyla açık sunucu bırakmadım. Onun yerine iki gerçek ölçüm yaptım:
1. **Canlı sunucu HTML'i çekildi** (`curl https://kolaytercih.com`, 392 KB) — navbar markup'ı `main` ile birebir aynı [D]. **Ama girişsiz ziyaretçide "Yapay Zeka Listem" pill'i HTML'de hiç yok** (`grep -c` → 0); yalnızca "Giriş yap" var. Pill sadece girişli kullanıcıda render ediliyor (`user-nav.tsx:40-76`), giriş yapmam ise yasak. **Yani taşmayı canlıda gözle göremem — Bilal kendi oturumunda görüyor.**
*Düzeltme notu: orkestratörün "canlıda `Yapay Zeka listemi kur` etiketi duruyor" bilgisi yanlış; o dize navbar'ın değil hero formunun submit butonunun metni (`hero-form.tsx:194`). Navbar etiketi `Yapay Zeka Listem`.*
2. **Gerçek font metriğiyle ölçüm.** Tahmin yerine `src/fonts/og/ClarityCity-SemiBold.ttf` ve Bricolage `.woff` dosyalarının `hmtx`/`cmap` tablolarını ayrıştırıp her dizenin ilerleme genişliğini hesapladım [D]. Aşağıdaki piksellerin hepsi bu ölçümden gelir, yuvarlama dışında tahmin yok.
| Dize | Boyut | Genişlik |
|---|---|---|
| `Yapay Zeka Listem` | 14 px / 600 | **129,7 px** |
| `Kendi Listem` | 14 px / 600 | 89,4 px |
| `Sıralamanı gir` | 16 px | 107,8 px |
| `Nasıl çalışır?` | 16 px | 96,9 px |
| `KolayTercih` (Bricolage) | 30 px | 168,6 px (tracking-tighter ile 152,1) |
## Kök neden — üç katman
**(a) Orta alan akışın dışında.** `katalog-arama.tsx:270` → `absolute left-1/2 -translate-x-1/2 … lg:flex`. Konteyner `site-header.tsx:12`'de `relative`. Absolute eleman flex satırında yer kaplamaz, dolayısıyla sağ küme büyüdükçe **flex hiçbir şey fark etmez**; taşma yerine sessiz çakışma olur. Üstelik boyama sırası gereği (CSS 2.1 Ek E, adım 8 > adım 7) konumlanmış `<nav>` statik pill'lerin **üstüne** boyanır — yani koyu "Ara" butonu "Yapay Zeka Listem" pill'inin sol ucunu kapatır. (`Kendi Listem` butonu `relative` olduğu için tersine, o nav'ın üstüne çıkar — `listem-butonu.tsx:35`.) Bilal'in gördüğü "üstüne çıkıyor" tam olarak bu.
**(b) Asıl tetikleyici: `xl` yeni yer açmıyor.** Konteyner `max-w-6xl` = **1152 px**. Yani viewport 1152'yi geçtikten sonra içerik genişliği **artık büyümüyor**. Ama `user-nav.tsx:59` ve `listem-butonu.tsx:39`, `lg:hidden xl:inline` deseniyle **1280 px'te iki etiketi birden geri getiriyor (+229 px)**. 1280 px'te kazanılan yer: **0 px.** Bu desen daha baştan tutarsız.
**(c) P4'ün eklediği yük.** `cb22faf` sağ kümeye lg–xl bandında +66 px, xl+ bandında +204 px ekledi. Sınır zaten dardı; bu onu geçirdi.
## Genişlik genişlik — ne oluyor
Geometri: konteyner genişliği `Wd = min(viewport, 1152)`; orta `<nav>`'ın merkezi `Wd/2`; sağ kümenin sağ kenarı `Wd − 16`. **BOŞLUK = küme sol kenarı − nav sağ kenarı**; negatif = çakışma. [D, hesap]
Ölçülen parça genişlikleri: orta nav **profilsiz 480 px** / **profilli 357 px**; sağ küme **lg–xl 304 px** (liste dolu) / **xl+ 540 px** (liste dolu).
### 375 px (mobil) — orta nav gizli, ama satır taşıyor
| Durum | Logo | Sağ küme | Toplam | Sığan | Sonuç |
|---|---|---|---|---|---|
| Liste dolu, 3 haneli kredi | 123 | 225,3 | **356,5** | 351 | **Satır-2'ye taşar → 3 satırlık header** |
| Liste boş | 123 | 153,3 | 284,5 | 351 | Tek satır OK |
Sınırda (5,5 px). 3 satıra çıkınca yapışkan header ≈ **140 px** — 667 px'lik iPhone SE ekranının **%21'i kalıcı olarak gidiyor**. P4 öncesi bu durum yoktu (küme 179 px idi).
### 768 px (tablet) — en kötü bant
| Durum | Logo | Sağ küme | Toplam | Sığan | Sonuç |
|---|---|---|---|---|---|
| Liste dolu | 196 | **582,8** | 790,9 | 736 | **Satır-2'ye taşar → 3 satırlık header (~176 px)** |
| Liste boş | 196 | 391,4 | 599,5 | 736 | Tek satır OK |
Sebep: `sm:inline` etiketleri 640 px'te açıyor ve `lg:hidden` 1024'e kadar kapatmıyor — yani **640–1023 px arası etiketler açık, ama yer yok**. 640 px'te liste boşken bile pay sadece 8,5 px. P4 öncesi küme 379 px idi, rahat sığıyordu.
### 1024 px
| Profil | Liste | nav sağ | küme sol | BOŞLUK |
|---|---|---|---|---|
| yok | dolu | 752 | 703 | **−48 px ÇAKIŞMA** |
| yok | boş | 752 | 798 | +46 |
| var | dolu | 690 | 703 | +13 (çok dar) |
| var | boş | 690 | 798 | +107 |
### 1280 px (ve tüm üstü — 1440, 1920 aynı, konteyner 1152'de sabit)
| Profil | Liste | nav sağ | küme sol | BOŞLUK |
|---|---|---|---|---|
| yok | boş | 816 | 788 | **−28 px ÇAKIŞMA** ← *Bilal'in gördüğü en olası hâl* |
| yok | dolu | 816 | 596 | **−220 px ÇAKIŞMA** |
| var | dolu | 754 | 596 | **−158 px ÇAKIŞMA** |
| var | boş | 754 | 788 | +33 |
**Kırılmanın başladığı nokta: tam olarak 1280 px** (`xl` sınırı). 1152–1279 arası sorunsuz, 1280'de bir anda −28 … −220 px. Konteyner büyümediği için **daha geniş ekran hiçbir şeyi düzeltmiyor** — 1920 px'te de aynı çakışma sürüyor.
## Düzeltme
### Önerilen — Alternatif 1 (en küçük, tek amaçlı, `[KARAR]`)
**Etiket span'leri her genişlikte gizli kalır; ikon + `aria-label` anlamı taşır.**
- `src/features/kullanici/components/user-nav.tsx:59`
`className="hidden sm:inline lg:hidden xl:inline"` → **`className="hidden"`** (ya da span tümden silinir; `aria-label="Yapay Zeka Listem"` ve `title` satır 52-53'te zaten var)
- `src/features/liste/components/listem-butonu.tsx:39`
aynı değişiklik (`aria-label` satır 33'te var)
Sonuç [D, hesap]: 375 px → 284,5/351 tek satır ✔ · 768 px → 555,8/736 tek satır ✔ · 1280+ → boşluk +15,5 … +110 px, çakışma yok ✔.
Kalan tek açık: **1024–1151 px, profilsiz + liste dolu → −48 … −1 px**.
**Bedeli dürüstçe:** P4'ün amacı keşfedilebilirlikti ("girişli 14 oturumun 7'si `/listem`'i hiç görmedi"). İkona indirince o kazanç zayıflar. Ama ölçüm şunu söylüyor: **1152 px'lik konteynerde, 480 px'lik ortalanmış bir nav'ın yanında sağ kümeye kalan bütçe ~304 px** — bu tam olarak dört ikon-pill eder, bir etiket bile fazladır. Etiketi korumanın yolu navbar'dan **bir şey çıkarmaktır**, daraltmak değil.
### Alternatif 2 (1 satır daha, 1024–1151 bandını da kapatır) — `[BİLAL]`
Alternatif 1 + `katalog-arama.tsx:310-314` → `Nasıl çalışır?` linkine `hidden xl:block`.
Orta nav profilsiz 480 → 339 px'e iner; 1024 px'te boşluk −48 → **+22 px** olur, her bant temizlenir [D, hesap].
`[BİLAL]` çünkü bu bir navigasyon/IA kararı: "Nasıl çalışır?" dar masaüstünde kaybolur. (Not: bu link yalnızca profilsiz durumda render ediliyor — yani tam da çakışan durumda.)
**Karşılaştırma:** Alt-1 tek başına Bilal'in gördüğü her şeyi çözer ve karar gerektirmez. Alt-2 kalan %10'u da kapatır ama bir menü öğesini dar masaüstünden düşürür. **Alt-1'i şimdi uygula, Alt-2'yi Bilal'e sor.**
### Yapılmaması gerekenler (değerlendirildi, elendi)
- `max-w-6xl` → `max-w-7xl`: 1280 px'te bile çakışma −156 px kalıyor. Çözmüyor.
- Orta nav'ı absolute'tan çıkarıp flex öğesi yapmak: doğru yapı ama nav'ın optik ortalanmasını bozar ve nav'ın butonları kısalmaya uygun değil — **navbar yeniden tasarımı, şimdi değil.**
- Etiket metnini kısaltmak: `[BİLAL]` gerektirir ve yetmez — `Yapay Zeka Listem` 129,7 px, 0'a inse bile xl bandındaki `Kendi Listem` (89,4 px) tek başına taşırmaya devam eder.
## Navbar'da ayrıca bulunan (P4 ile ilgisiz, küçük)
| Yer | Kural/sorun | Etki | Düzeltme | Büyüklük |
|---|---|---|---|---|
| `user-nav.tsx:63-74` | Kredi link'inin erişilebilir adı **"12"** (salt sayı). İçerikten gelen ad `title`'ı ezer; `Coins` `aria-hidden`, "kredi" span'i `lg:hidden` | Ekran okuyucu "12, bağlantı" diyor — nereye gittiği belirsiz | `aria-label="12 kredin var — kredi yükle"` ekle | XS |
| Tüm pill'ler, <640 px | Dokunma hedefi `h-9` = **36 px** (< 44 px) | Dar ekranda ıskalama | `sm` altında `h-11` ya da dokunma alanı genişletme | S |
---
# İŞ 2 · G1 (`funnel/sonuc-ilk-ekran`) merge öncesi tasarım denetimi
Diff okundu (`git diff 9bd448b..funnel/sonuc-ilk-ekran`, 6 dosya / 61+ 39−). Dal değiştirilmedi, çalışma ağacına dokunulmadı.
## HÜKÜM
> ### Şu bir düzeltmeyle merge edilebilir.
> **Engelleyici:** B1 (hidrasyon CLS'i). Tek dosya, tek satırlık yer değişikliği.
> **Aynı commit'e alınması güçlü önerilen:** B2 (paragraftaki artık vaat) — G1'in kendi amacı bu.
> Geri kalan her şey (hiyerarşi, mobil, AGENTS.md kuralları, CTA dili) **temiz.**
## Neyi doğruladım — temiz çıkanlar
- **CTA ok deseni ✔** `tadimlik-satiri.tsx:204` → metin önce, sonunda `<ArrowRight className="size-4" aria-hidden />`. `Sparkles` yok (dosyada hiç import edilmemiş).
- **`SectionEyebrow` ✔** `tadimlik-satiri.tsx:129` kanonik bileşeni kullanıyor, elle pill yok.
- **Kapatma çarpısı:** G1 hiçbir modal'a dokunmuyor — konu dışı ✔.
- **Risk dili ✔** `RaporSatirDetayi` (`rapor-listesi.tsx:60`) renk noktasının yanında `DILIM_ETIKET`/`RISK_ETIKET` metnini basıyor; renk tek başına anlam taşımıyor. G1 dokunmadı.
- **`first:mt-0` mantığı doğru [Ç]** JSX yorumları DOM düğümü üretmez; `ManuelHarita` `null` dönünce `<section>` gerçekten `main`'in ilk element çocuğu olur, `:first-child` eşleşir. Harita göründüğünde `mt-16` geri gelir. Doğru kurulmuş.
- **Mobil 375 px'te tadımlık kartı taşmıyor ✔** dış sarmalayıcı `flex-wrap` + `min-w-0`; program adı `truncate`; sıralama geçmişi `hidden md:inline-flex` ile mobilde düşüyor; CTA `w-full sm:w-auto` ve `h-11` = **44 px dokunma hedefi ✔**. Uzun üniversite adı yatay kaydırma üretmiyor.
## İlk ekran hiyerarşisi — yeni sıra mantıklı, bir uyarıyla
Yeni sıra: `ManuelHarita` (boşsa yok) → `TadimlikBolumu` → `SonucProgramTablosu` → `SonucSihirbazi` → dipnot.
- **Girişsiz + liste boş (ana hedef kitle):** kullanıcı ilk olarak tadımlığı görüyor. Doğru karar — ödeme öncesi gösterilebilen tek gerçek önizleme bu ve eskiden ~2.200 px aşağıdaydı.
- **Girişli kullanıcı:** `TadimlikBolumu` `null` döner (`tadimlik-bolumu.tsx:19`). Liste de boşsa `<main>`'in ilk çocuğu doğrudan tablo olur — **başlıksız, girişsiz, bağlamsız bir tablo**. Bu G1'in getirdiği bir bozulma değil (önce de öyleydi) ama boş harita gidince **daha çıplak** kaldı. A3 (`/sonuc` `<h1>`) bunu kapatacak; G1'i bloke etmez.
- Mobilde tadımlığın giriş bloğu (rozet + 2 satırlık h2 + 3 satırlık paragraf) **~195 px** yer tutuyor; 667 px'lik ekranda kartın yalnızca üst ~300 px'i görünüyor, CTA katlanın çok altında. Kabul edilebilir ama iyileştirilebilir — aşağıda Ö1.
## Erişilebilirlik — `<h1>` durumu
**Canlı `/sonuc` sunucu HTML'i çekildi [D]:** `<h1>` sayısı **0**, `<h2>` sayısı **5**. İlk üç h2 arama modalının içindeki `text-xs uppercase` etiketleri ("Popüler Bölümler", "Keşfet", "Rehberden").
- **G1 bunu değiştirmedi** (kapsam dışı bırakılmış, CTO şartnamesi açıkça yazıyor) ve **sorunu büyütmedi**: tadımlık h2'si zaten sayfadaki tek gerçek içerik başlığıydı, sadece yukarı taşındı. Belge sırasındaki başlık sayısı ve seviyeleri aynı kaldı.
- Küçük bir **iyileşme** bile var: başlık sırası artık görsel sırayla uyumlu (tadımlık h2 → sihirbaz h2), eskiden tersti.
- **A3 (`a11y/sonuc-h1`, `24-ceo-kapanis.md` §A) zaten kuyrukta.** G1'i bunun için bekletmeye gerek yok, ama **A3 merge edilirken `<h1>`'in tadımlığın h2'sinin ÜSTÜNE** konması gerekir — yoksa sayfa h2 ile açılır.
## BULGULAR
### B1 — ENGELLEYİCİ · Hidrasyon CLS'i: harita sayfanın tepesine sonradan giriyor
**Yer:** `manuel-harita.tsx:71` (`if (liste.length === 0) return null;`) + `sonuc/page.tsx:103` (sıradaki ilk eleman)
**Kural/sorun:** `useManuelListe` sunucu snapshot'ı olarak **her zaman boş liste** döner (`liste-store.ts:86` → `() => BOS_LISTE`); localStorage ilk client abonesinde okunuyor (`liste-store.ts:49-52, 72`). Yani **kayıtlı listesi olan her dönüş ziyaretçisinde**: sunucu 0 px yer ayırır → hidrasyondan sonra harita belirir → **tadımlık ve tablo aşağı itilir**.
**Kayma miktarı [D, hesap]:** `main` = `max-w-4xl px-4` → içerik 864 px; `aspect-[1050/447]` → **367,8 px** (375 px'te 146 px). Bu, `<main>`'in **ilk** çocuğunda olduğu için altındaki her şey kayıyor — impact fraction ~1. CLS eşiğini (0,1) rahatlıkla aşar.
**Eski kod tam da bunu engelliyordu:** silinen placeholder `aspect-[1050/447]` ile yeri **sunucuda** rezerve ediyordu; hidrasyonda gerçek harita aynı orana oturuyordu → kayma ~0. `TercihHaritasiLazy`'nin kendi `HaritaIskeleti`'si (`tercih-haritasi-lazy.tsx:10-17`) yalnızca **chunk** gecikmesini karşılar, `null` → görünür geçişini karşılamaz.
**Kullanıcıya etkisi:** Dönen kullanıcı sayfayı açıyor, tadımlığı okumaya başlıyor, saniyeler içinde metin 368 px aşağı kayıyor; tıklamak istediği yerde başka bir şey oluyor.
**Not:** CEO §3 G1-b'de onaylanan takas "**ilk `+` tıklamasında** haritanın belirmesi" — yani **kullanıcının kendi eylemi**. Sayfa yüklenirken kendiliğinden gelen kayma o onayın kapsamında değil ve G1 raporunda hiç geçmiyor.
**Önerilen düzeltme (en küçüğü):** `sonuc/page.tsx`'te **`<ManuelHarita />`'yı `<SonucProgramTablosu>`'nun ALTINA al** (satır 103'ten satır 128'in hemen öncesine). Gerekçe iki yönlü: (a) hidrasyonda gelen harita artık yalnızca sihirbaz + dipnotu iter, ikisi de katlanın altında → CLS ihmal edilebilir; (b) harita zaten tablodan kurulan listenin görselleştirmesi, tablodan **sonra** gelmesi bilgi mimarisi olarak da doğru. `first:mt-0` o zaman her durumda geçerli olur ve daha da sağlamlaşır.
**Büyüklük: XS** (tek JSX bloğunun yeri). Alternatif (yer rezervi için çerez mirror'ı) over-engineering — önerilmiyor.
### B2 — YÜKSEK · Butondan kaldırılan vaat paragrafta duruyor
**Yer:** `tadimlik-satiri.tsx:134-136`
> "Sıralamana uygun bir programın gerekçesi, yerleşme riski ve taban trendi — 24 tercihlik listenin **her satırı bu formatta kurulur**."
**Kural/sorun:** `2373a9a` butondan "24 satırın tamamı" iddiasını kaldırdı, ama iki eleman yukarıdaki paragraf aynı vaadi başka kelimelerle sürdürüyor. Maske girişsiz/paketsiz kullanıcıya **3 satır** açıyor (`rapor-maske.ts:12` `ACIK_SATIR = 3`); kalan 21 satırın gerekçe/risk/trend metni `SAHTE_*` sabitleriyle değiştiriliyor. Öğrenci bu cümleyi "24 satırın hepsini bu ayrıntıda göreceğim" diye okur.
**Kullanıcıya etkisi:** G1'in tam olarak kapatmak istediği beklenti açığı, kaldırdığı yerin 40 px yukarısında açık kalıyor. Girişten sonra 21 maskeli satır görmek, buton metninin düzeltilmesinden daha güçlü bir hayal kırıklığı.
**Önerilen düzeltme:** son cümleciği teslim edilene çek — ör. "— listendeki her satır bu formatta kurulur, ilk üçünü hemen açıyoruz." Sayı `"use client"` dosyaya import edilemiyor (`rapor-maske.ts` `server-only`, CTO Özet #4), bu yüzden **sayısız da yazılabilir**: "— listendeki satırlar bu formatta kurulur." **Sayı yazılacaksa `[BİLAL]`**, çünkü `3` elle yazılırsa tek kaynak kuralı bozulur.
**Büyüklük: XS** (tek cümle). `[BİLAL]` — marka/vaat metni.
### B3 — ORTA · Suspense fallback'i gerçek düzenle aynı genişlikte değil
**Yer:** `sonuc/page.tsx:47` (`max-w-6xl px-4 py-10`) ↔ `:99` (`max-w-4xl px-4 py-12`)
**Kural/sorun:** Fallback konteyneri **1152 px**, gerçek içerik **896 px**. `cookies()` sayfayı dinamik yaptığı için bu fallback gerçekten görülüyor. Çözüldüğü anda içerik 256 px daralıyor ve yeniden ortalanıyor → yatay + dikey kayma, her `/sonuc` yüklemesinde.
**G1 ile ilişkisi:** G1 fallback'e dokunmadı ve CTO "yanlışlığı artmıyor" dedi — doğru. Hatta **yapısal olarak iyileşti**: fallback'in `pill + başlık + alt satır` iskeleti artık gerçekten sayfanın tepesindeki `SectionEyebrow + h2 + p` ile eşleşiyor (eskiden tepede harita vardı, eşleşmiyordu). Ama genişlik ve hizalama (fallback sola, gerçek içerik `items-center text-center`) hâlâ uyumsuz.
**Önerilen düzeltme:** `max-w-6xl` → `max-w-4xl`, `py-10` → `py-12`, iskeletler `mx-auto` ile ortalanır. **Büyüklük: XS.** G1'i bloke etmez — ayrı bir commit ya da A3 dalıyla birlikte gidebilir.
### B4 — DÜŞÜK · "Giriş sonrası liste hemen üretilir" kredisiz kullanıcıda tutmuyor
**Yer:** `tadimlik-satiri.tsx:188-189`
Tadımlık yalnızca girişsiz kullanıcıya render ediliyor, ama girişsiz ≠ yeni kullanıcı: **çıkış yapmış, kredisi tükenmiş** bir kayıtlı kullanıcı da bu CTA'yı görür. `/listem?uret=1` o durumda üretemez. Cümle "hemen üretilir" diye koşulsuz vaat ediyor.
**Etki:** dar bir kitle, ama vaat tutmadığında tam huninin ortasında.
**Öneri:** ya cümle yumuşatılır ("Giriş sonrası liste üretimi başlar") ya da `/listem`'in kredisiz hata durumunun ne dediği QA'da doğrulanır. **Büyüklük: XS.** Bu paket için **engelleyici değil**.
## G1'in doğru yaptıkları (kayda geçsin)
- `listemUretHref`'in tek kaynağa taşınması (`sihirbaz-sabitler.ts:181`) + `uret=1` sıra sözleşmesinin doküman olarak oraya yazılması: iyi iş, ilerideki sessiz kırılmaları önler.
- `IZINLI_KAYNAKLAR`'a `"tadimlik"` eklenmesi (`uretim-basladi-olayi.tsx:33`) — ölçüm sessizce `bilinmiyor`a düşmüyor.
- Seri kırılması notunun kodun yanına yazılması (`tadimlik-satiri.tsx:100-106`). Doğru refleks.
- CTA hedefinin `/sonuc` yerine `/listem?uret=1` olması: girişten sonra kullanıcıyı başladığı yere geri atmak yerine sonuca götürüyor. Huni açısından doğru.
---
# İŞ 3 · CEO'nun reddettiği iki UX kararına görüş
**R3 (mobil yapışkan alt çubuk) — katılıyorum, hem de gerekçesinden daha güçlü bir sebeple.** CEO "95 ziyaret/hafta, ekran alanı yiyen over-engineering" diyor; ben buna şunu eklerim: bu üründe yapışkan alt çubuk **şu anda aktif olarak zararlı olurdu**, çünkü `/sonuc` zaten `sticky top-4` bir header taşıyor ve İş 1'de ölçtüğüm gibi o header 375 px'te 3 satıra çıkıp ~140 px (ekranın %21'i) yiyebiliyor; buna bir de alt çubuk eklenirse mobil okuma alanı ~%30 azalır, üstelik sanal klavye açıldığında `position: fixed` alt çubukların iOS Safari'de içeriğin üstüne binmesi klasik bir tuzaktır. Çözülmesi gereken şey CTA'nın görünürlüğü değil, header'ın şişkinliği. **R4 (`/paket` girişsiz birincil CTA'sının fiyata çevrilmesi) — karara katılıyorum, gerekçesine kısmen.** "Veri yok, T4'e bağlandı" doğru bir disiplin ve fiyatı erken göstermenin dönüşümü düşürebileceği de doğru. Ama şunu kayda geçiriyorum: bu bir A/B sorusu değil, bir **dürüstlük** sorusu — kullanıcı ödeme fiiline kaç adım kala fiyatı öğrendiğini bilmiyorsa, öğrendiği anda geri dönüyor ve bunu "fiyat yüksek" diye değil "kandırıldım" diye yapıyor. T4 eşiği (`/odeme`'yi 30 kişi görsün) bir payda üretir ama **o paydanın kendisi fiyatın geç gösterilmesinden etkileniyor** — yani ölçüm, ölçmek istediği şeyin içinden geçiyor. Kararı değiştirmiyorum; T4 açıldığında bakılacak metriğin "`/paket` → `/odeme` geçişi" değil "**`/odeme`'yi gördükten sonra terk oranı**" olmasını öneriyorum, çünkü fiyat şokunu yalnızca o gösterir.
---
## Bilal'in gözle kontrol etmesi gereken ekranlar
Görsel doğrulama bende yapılamadı (araç setinde tarayıcı yok + pill yalnızca girişli render ediliyor, giriş yasak). Şu beş ekran:
1. **Navbar, kendi girişli oturununda, 1280 px ve üstü** — "Yapay Zeka Listem" pill'inin sol ucunun ortadaki koyu "Ara" butonunun altında kalıp kalmadığı. (Bulgumun ana kanıtı bu.)
2. **Navbar, 768 px** (tablet / tarayıcıyı yarım ekran) girişli + manuel listede en az 1 program — header'ın **3 satıra** çıkıp çıkmadığı.
3. **Navbar, 375 px** girişli + liste dolu + 3 haneli kredi bakiyesi — aynı 3 satır kontrolü (sınırda, 5 px).
4. **`/sonuc`, merge sonrası, kayıtlı manuel listesi olan bir oturumda** — sayfa açıldıktan ~1 sn sonra haritanın gelip tadımlığı aşağı itip itmediği (B1). *Bunu merge öncesi göremeyiz; G1 canlıda yok.*
5. **`/sonuc`, girişsiz, 375 px** — tadımlık kartının CTA'sına ulaşmak için kaç ekran kaydırmak gerektiği (Ö1 kararı buna bağlı).
## Bilal'den istenen (3 madde)
1. **Navbar düzeltmesi için onay:** Alternatif 1'i (iki etiket span'i her genişlikte gizli) yazılımcıya verelim mi, yoksa Alternatif 2'yi de (`Nasıl çalışır?` yalnız ≥1280) ekleyip 1024–1151 bandını da kapatalım mı? **~3 dk.**
2. **G1'in B1 düzeltmesi:** `<ManuelHarita />`'yı tablonun altına almak — dalın 7. commit'i olarak yazılsın mı, yoksa merge edilip ayrı mı gitsin? **~2 dk.**
3. **B2 metni `[BİLAL]`:** `tadimlik-satiri.tsx:135`'teki "24 tercihlik listenin her satırı bu formatta kurulur" cümlesi ne olsun — sayısız mı ("listendeki satırlar bu formatta kurulur"), yoksa açıkça "ilk üçü hemen açılır" mı? **~3 dk.**

View File

@@ -0,0 +1,177 @@
# 37 — Yazılımcı: navbar taşması + G1 harita/metin düzeltmesi
Tarih: 22 Eylül 2026 · Rol: `yazilimci` · Şartname: `36-tasarimci-g1-ve-navbar.md`
İşaret: **[D]** koşarak doğruladım · **[Ç]** koddan çıkarım
---
## Özet (5 madde)
1. **İki dal, sırayla, ayrı ayrı commit'lendi.** `duzeltme/navbar-tasmasi` (1 commit, `main`'den) ve `funnel/sonuc-ilk-ekran` (mevcut dala 2 commit eklendi, geçmiş yeniden yazılmadı). Push/merge yok, `main`'e commit yok.
2. **Navbar:** tasarımcının Alternatif 1'i uygulandı — iki etiket span'inden hem `xl` hem `sm` görünürlük sınıfları kaldırıldı. `aria-label`'ların ikisi de zaten yerindeydi, doğrulandı; erişilebilirlik değişmedi. Alternatif 2'ye (`Nasıl çalışır?`) dokunulmadı.
3. **G1 (a):** `<ManuelHarita />` tablonun altına alındı (silinmedi, geri getirilmedi). Yeni sıra: **tadımlık → tablo → harita → sihirbaz → dipnot.** Sıraya bağlı stiller yeni sıraya göre denetlendi; harita ilk çocuk olmaktan çıktığı için kendi `mt-16` boşluğunu almak zorunda kaldı (bkz. §Sapmalar 1).
4. **G1 (b):** `tadimlik-satiri.tsx` paragrafına "ilk üçü hemen açılır" eklendi; ayrı `[Bilal]` commit'i, dalın tepesinde. İki `[Bilal]` commit'inin de tek tek düşürülebilir olduğu ters yama denemesiyle doğrulandı [D].
5. **Doğrulama iki dalda da temiz:** `next typegen` ✓ · `tsc --noEmit` → **0** · `pnpm lint` → **0** [D]. `pnpm install`/`pnpm build` talimat gereği koşulmadı; tarayıcı/dev sunucusu açılmadı.
**Bana ait olmayan 19 commit'lenmemiş dosyaya dokunulmadı** — hiçbiri stage'lenmedi, `git add -A`/`.` kullanılmadı, dosyalar yol vererek eklendi. Yasaklı komutların (`reset`, `checkout --`, `restore`, `clean`, `stash`) hiçbiri koşulmadı; ters yama denemeleri bile `git apply --check` ile ağaca dokunmadan yapıldı.
---
# DAL 1 — `duzeltme/navbar-tasmasi`
Taban: `main` `9bd448b`. **1 commit.**
| SHA | Mesaj |
|---|---|
| `9abfdf4` | `fix(navbar): pill etiketleri her genişlikte gizli — çakışma kapanır` |
**Dokunulan dosyalar (2):**
`src/features/kullanici/components/user-nav.tsx` · `src/features/liste/components/listem-butonu.tsx`
## Ne değişti
- `user-nav.tsx:59` → `className="hidden sm:inline lg:hidden xl:inline"` **→ `className="hidden"`** (span korundu, metin DOM'da ama `display:none`).
- `listem-butonu.tsx:39` → aynı değişiklik.
- Her iki yerdeki eski yorum ("lg–xl arasında metin gizli") artık yanlış olacağından yeniden yazıldı; kök neden (konteyner 1152'de kilitli, `xl` yeni yer açmıyor, sağ kümenin bütçesi ~304 px) kodun yanına not düşüldü.
- **Kapsam dışı bırakılan:** `user-nav.tsx:73`'teki kredi etiketi (`hidden md:inline lg:hidden`) — şartname yalnız iki etiket span'ini sayıyor, dokunulmadı.
## Kabul kriterleri
| Kriter | Durum | Nasıl doğrulandı |
|---|---|---|
| `grep -n "xl:inline\|sm:inline"` iki dosyada 0 sonuç | ✔ | `GREP_EXIT=1` (eşleşme yok) [D] |
| `aria-label` her iki dosyada var | ✔ | `user-nav.tsx:52` `aria-label="Yapay Zeka Listem"` · `listem-butonu.tsx:33` `aria-label={\`Kendi listem — ${liste.length}/${MANUEL_LISTE_MAX} program\`}` [D] |
| Alternatif 2 uygulanmadı | ✔ | `katalog-arama.tsx` dalın diff'inde yok [D] |
| Tasarımcının hesabı (375 → 284,5/351 · 768 → 555,8/736 · 1280+ pozitif) | ✔ [Ç] | Kod değişikliği tasarımcının hesapladığı girdiyi birebir üretiyor; piksel ölçümü onun raporundan, ben ölçmedim |
> **Not — grep kriterini kirleten tuzak:** ilk yazdığım yorum gerekçeyi anlatırken `xl:inline` dizesini literal geçiriyordu ve kabul kriteri grep'i 1 sonuç dönüyordu. Yorum, anlamı koruyarak dizeyi içermeyecek biçimde yeniden yazıldı. Kriter artık gerçekten 0.
## Doğrulama çıktıları
```
$ pnpm exec next typegen
Generating route types...
✓ Types generated successfully
$ pnpm exec tsc --noEmit ; echo "TSC_EXIT=$?"
TSC_EXIT=0
$ pnpm lint ; echo "LINT_EXIT=$?"
> kolaytercih@0.1.0 lint
> eslint
LINT_EXIT=0
```
---
# DAL 2 — `funnel/sonuc-ilk-ekran`
Mevcut dalın tepesine (`d2e1190`) **2 commit eklendi**; geçmiş yeniden yazılmadı, hiçbir commit amend/rebase edilmedi.
| # | SHA | Mesaj | Dosyalar |
|---|---|---|---|
| 7 | `e912665` | `fix(sonuc): harita tablonun altına alınır — hidrasyon kayması kapanır` | `sonuc/page.tsx`, `manuel-harita.tsx`, `tadimlik-satiri.tsx` |
| 8 | **`e3519a5`** | **`[Bilal] content(tadimlik): paragraf maskenin gerçeğini söyler`** | `tadimlik-satiri.tsx` |
**Dalın `[Bilal]` commit'leri: `d2e1190` (6.) ve `e3519a5` (8., tepe).**
Dalın `main`'den toplam diff'i hâlâ aynı 6 dosya; yeni dosya eklenmedi.
## (a) `e912665` — harita tablonun altına
Yeni sıra `src/app/sonuc/page.tsx` içinde:
```
118 <TadimlikBolumu sira={sira} tur={turKey} />
124 <SonucProgramTablosu … />
131 <ManuelHarita />
135 <SonucSihirbazi … />
```
Gerekçe (B1) kodun yanına yorum olarak yazıldı: sunucu snapshot'ı hep boş liste döndüğü için harita yukarıdayken kayıtlı listesi olan dönüş ziyaretçisinde hidrasyondan sonra ~368 px'lik bir blok `<main>`'in tepesine giriyor, impact fraction ~1. Aşağıda belirince yalnızca sihirbaz + dipnot iteliyor.
### Sıraya bağlı stiller — tek tek denetlendi
| Eleman | Kural | Yeni sırada durum |
|---|---|---|
| `tadimlik-satiri.tsx:127` `<section className="mt-16 min-w-0 first:mt-0">` | `first:mt-0` | ✔ **Sağlamlaştı.** Harita artık üstünde olmadığı için bu `<section>` `<main>`'in ilk DOM çocuğu; kural her durumda eşleşiyor, eskiden "harita null'sa" koşuluna bağlıydı. Yorum yeni gerçeğe göre güncellendi. |
| `program-tablosu.tsx:175` `<section className="mt-16">` | sabit üst boşluk | ✔ Değişmedi; tadımlık render edilmediğinde (girişli kullanıcı) ilk çocuk olup `mt-16` alıyor — G1 öncesindeki davranışın aynısı, bu commit'in getirdiği bir değişiklik değil. |
| `sihirbaz-cagri-karti.tsx:321` `<section className="… mt-16 …">` | sabit üst boşluk | ✔ Değişmedi. |
| `manuel-harita.tsx:74` kök `<div>` | **boşluğu yoktu** | ⚠ **Düzeltildi** — bkz. Sapmalar 1. |
## (b) `e3519a5` — `[Bilal]` metin artığı
`tadimlik-satiri.tsx:135` civarı:
> Sıralamana uygun bir programın gerekçesi, yerleşme riski ve taban trendi — 24 tercihlik listenin her satırı bu formatta kurulur**, ilk üçü hemen açılır.**
- Sayı yazıldı, bulanıklaştırılmadı (Bilal'in seçtiği yön).
- Garanti/vaat dili yok; cümle bir şey **eklemiyor**, var olan iddiayı **sınırlıyor**.
- `3` elle yazıldı: `ACIK_SATIR` `src/lib/rapor-maske.ts:12`'de ve o dosya `server-only`; `tadimlik-satiri.tsx` ise `"use client"` — sabit import edilemiyor. **Tek kaynak bağı kodun yanına yorum olarak iliştirildi**: `ACIK_SATIR` değişirse bu cümle aynı commit'te değişmeli. [D — `rapor-maske.ts:12` okundu, değer 3]
### `[Bilal]` commit'lerinin tek tek düşürülebilirliği — doğrulandı [D]
Dizilim `… 2373a9a → d2e1190 [Bilal] → e912665 → e3519a5 [Bilal]` olduğu için `d2e1190` tepede değil; düşürme yolu `git revert` (yıkıcı komut yasağına da uygun olan tek yol). Ters yamanın temiz uyguladığı, **çalışma ağacına dokunmadan** sınandı:
```
$ git show d2e1190 | git apply --check --reverse - → EVET (temiz ters yama)
$ git show e3519a5 | git apply --check --reverse - → EVET (temiz ters yama)
```
Hunk'lar birbirinden uzak ve kesişmiyor: `d2e1190` → satır 188 ve 202 (CTA metni), `e3519a5` → satır 133-142 (paragraf). Aralarındaki `e912665` ise 123-127 (yorum) bölgesine dokunuyor.
**Ana commit'ler `[Bilal]` commit'leri olmadan derlenir mi?**
- `e912665` için **[D]**: `tsc` ve `lint` tam olarak bu commit'in ağacı üzerinde koşuldu (commit'ten hemen önce), ikisi de 0.
- `d2e1190` düşürülürse: o commit yalnızca iki metin dizesini değiştiriyor (`Giriş yap ve listeni oluştur` → `Kendi listemi oluştur` ve alt satıra bir cümle), hiçbir tanımlayıcıya dokunmuyor — geri alınması derlemeyi kıramaz **[Ç]**.
## Doğrulama çıktıları (dal 2, tepe commit'in ağacında)
```
$ pnpm exec next typegen
Generating route types...
✓ Types generated successfully
$ pnpm exec tsc --noEmit ; echo "TSC_EXIT=$?"
TSC_EXIT=0
$ pnpm lint ; echo "LINT_EXIT=$?"
> kolaytercih@0.1.0 lint
> eslint
LINT_EXIT=0
```
`/meraklisina` şeması el değmedi [D]:
```
$ git diff --name-only 9bd448b..HEAD | grep -E "huni-semasi|meraklisina|analitik.ts|rapor-maske|credits.ts"
(boş)
```
---
## Şartnameden sapmalar (2)
1. **`manuel-harita.tsx`'in kök `<div>`'ine `mt-16` eklendi** — şartname yalnız `page.tsx`'te yer değişimi istiyordu. Gerekçe: haritanın kök öğesinin üst boşluğu yoktu, çünkü `<main>`'in ilk çocuğuyken boşluğu `main`'in `py-12`'sinden alıyordu. Tablonun altına taşınınca tabloya yapışık kalacaktı; sayfadaki diğer bölümlerin hepsi `mt-16` kullanıyor (tablo `<section>`'ı, sihirbaz kartları, tadımlık). Bu bir ritim düzeltmesi, davranış değişikliği değil. Dosya zaten G1'in sahiplik kümesinde. **Gözle kontrol edilmeli** (aşağı, Bilal'den istenen 1).
2. **İki commit'te yorum güncellemeleri** — `tadimlik-satiri.tsx:123`'teki `first:mt-0` yorumu haritanın üstte olduğunu varsayıyordu, `page.tsx`'teki hiyerarşi yorumu da eski sırayı anlatıyordu. İkisi de yeni sıraya göre yeniden yazıldı; kod değil belge düzeltmesi, ama diff'e giriyor.
## Kapsam dışı bırakılanlar (bilerek)
- **B3** (Suspense fallback `max-w-6xl` ↔ içerik `max-w-4xl`, 256 px genişlik farkı) — `sonuc/page.tsx:47`. Bu işin parçası değil, dokunulmadı. Aynı dosyada duruyor; A3 (`/sonuc` `<h1>`) dalıyla birlikte gitmesi ucuz olur.
- **B4** ("Giriş sonrası liste hemen üretilir" kredisiz kullanıcıda tutmuyor) — `tadimlik-satiri.tsx:188-189`, yani `d2e1190`'ın kendi hunk'ı. Dokunmadım; düzeltilecekse o `[Bilal]` commit'iyle birlikte ele alınmalı.
- Navbar'daki küçük bulgular (kredi link'inin erişilebilir adının salt "12" olması, <640 px'te 36 px dokunma hedefi) — şartname bunları istemedi.
- Alternatif 2 (`Nasıl çalışır?` gizleme) — Bilal A'yı seçti.
## Merge sonrası doğrulanması gerekenler
1. **`pnpm build` iki dalda da alınmadı** (disk talimatı). Push edilecek commit'in **kendisi** üzerinde alınmalı — çalışma ağacı kirli olduğu için buradaki bir build zaten yanıltıcı olurdu (AGENTS.md "Push öncesi build zorunlu").
2. **Navbar, girişli oturumda 375 / 768 / 1280 px** — header tek satıra indi mi, pill'ler ikon+rozet hâliyle tanınabiliyor mu. Tasarımcının hesabı bunu söylüyor ama ölçüm hesapla yapıldı, gözle değil.
3. **Ekran okuyucuyla iki pill** — etiket artık yalnız `aria-label`'dan geliyor; VoiceOver/NVDA'da "Yapay Zeka Listem, bağlantı" ve "Kendi listem — 3/24 program, düğme" duyuluyor mu.
4. **`/sonuc`, kayıtlı manuel listesi olan oturumda** — harita hidrasyonda tablonun altında belirip **üstündeki hiçbir şeyi itmiyor** mu (B1'in asıl testi), ve tabloyla arasındaki `mt-16` boşluğu doğru duruyor mu.
5. **Analitik serisi** — `tadimlik_goruntulendi` için 32 numaralı raporun uyarısı geçerliliğini koruyor; tadımlık hâlâ ilk ekranda, bu commit'ler paydayı değiştirmedi.
`guvenlik-uyum` denetimi **gerekmiyor**: iki dalda da para, giriş kimlik doğrulaması ya da kişisel veri akışına dokunulmadı — değişenler yerleşim sırası, iki CSS sınıfı ve bir cümle.
## Bilal'den istenen (3 madde)
1. **`manuel-harita.tsx`'e eklediğim `mt-16`'yı gözle onayla** — harita artık tablonun hemen altında, aradaki boşluk diğer bölümlerle aynı ritimde mi, yoksa fazla/az mı? **~2 dk.**
2. **`e3519a5` (`[Bilal] content(tadimlik): paragraf maskenin gerçeğini söyler`) onayı** — "…24 tercihlik listenin her satırı bu formatta kurulur, **ilk üçü hemen açılır**." senin dilin mi? Hayırsa `git revert e3519a5`; altındaki hiçbir şey etkilenmez (ters yama temiz doğrulandı). **~2 dk.**
3. **Navbar'da kalan 1024–1151 px bandı** — Alternatif 1 bu dar bantta profilsiz + liste dolu durumda −48 … −1 px açık bırakıyor (tasarımcının hesabı). Alternatif 2'yi (`Nasıl çalışır?` yalnız ≥1280 px) isteyecek misin, yoksa bu bant kabul mü? **~3 dk.**

View File

@@ -0,0 +1,132 @@
# Sabah özeti — 22 Eylül 2026 gece vardiyası
Bilal için tek rapor. Ayrıntı isteyeceğin her şey numaralı dosyalarda; burada yalnız kararlar ve senden istenenler var.
---
## 1. Gecenin çıktısı tek cümlede
**15 yeni/güncellenmiş rehber yazısı yazıldı ve editör denetiminden geçti; markanın adı ve genişleme sorusu kapandı; "öğrenciler ödemiyor" hipotezinin bugün test edilmemiş olduğu kanıtlandı; CEO açık kalan hiçbir madde bırakmadı.**
---
## 2. Rehber yazıları — asıl istediğin iş
| # | Yazı | Ne yapıyor |
|---|---|---|
| 1 | `taban-siralamalari-alti-yilda-nasil-degisti` | 2021→2026 eşleşmeli trend, 5.461 program. Gecenin kanonik trend kaynağı |
| 2 | `kac-net-ile-hangi-bolum` | `netler` tablosu ilk kez yazıya girdi — rakiplerde bu veri yok |
| 3 | `siralama-bandlari-hangi-kapilar-acilir` | 8 sıralama bandı × kaç program/üniversite/bölüm |
| 4 | `ayni-bolum-farkli-universite-siralama-farki` | Aynı bölüm, farklı okul: 150.000'de 82 Psikoloji programı açık ama yalnız 6'sı devlet |
| 5 | `hangi-bolumlerin-kontenjani-azaldi` | YÖK'ün 17 Şubat 2026 kontenjan kısıtı ↔ verimiz birebir örtüşüyor |
| 6 | `yeni-acilan-bolumler-nasil-degerlendirilir` | Kontenjanı 1–10 olan yeni programların %58'i medyandan sıkı açılıyor |
| 7 | `bilgisayar-mi-yazilim-muhendisligi-mi` | 56 üniversitenin 54'ünde BM daha seçici kapandı |
| 8 | `kktc-universiteleri-okunur-mu` | KKTC lisans doluluğu dört yılda %83,4 → %60,2 |
| 9 | `yapay-zekaya-tercih-sordum-guvenilir-mi` | Marka konumunu iddia ederek değil göstererek anlatıyor |
| 10 | `ek-madde-1-puanim-yetiyor-mu` | Bu yıl yerleşen güzde başvuramaz — mevzuattan çıkarıldı |
| 11 | `universitede-ilk-hafta-...` | Harç rakamları Resmî Gazete'nin taranmış PDF'inden okundu |
| 12 | `yks-2027-takvimi` | ÖSYM takvimi açıklamamış; **tek bir tahmini tarih yok** |
| 13 | `rehber-ogretmenler-icin-veri-kaynaklari` | Dağıtım kanalı: 16 adres tek tek açıldı, 13'ü çalıştı |
| 14 | `bolumumu-sevmedim-hangi-kapilar-var` | 539 kelimelik hub; 7 kapıyı mevcut yazılara bağlıyor |
| 15 | `veliler-icin-tercih-rehberi` *(güncellendi)* | Altındaki "sıralamanı gir" kutusu artık veliye ölü uç değil |
| 16 | `bos-kontenjanlar-ne-anlatiyor` *(canlı, düzeltildi)* | İki yanlış cümle: "birkaç yüz kişilik fark" aslında ~9 bin; payda açıklaması tersti |
**Editör hükmü: 16'sının 16'sı yayımlanabilir.** İki turda 46 yazıda 829 iç link tarandı, **0 kırık hedef**; 180+ DB hücresi yazıların kendi filtreleriyle yeniden koşuldu; 23 doğal çapraz link eklendi (yeni yazıların birbirine hiç linki yoktu).
**Editörün canlı yazıda bulduğu hata — düzeltildi:** `bos-kontenjanlar-ne-anlatiyor.md:131` "boş kontenjan farkı birkaç yüz kişilik" diyordu; gerçekte devlet kontenjan toplamında fark **~9 bin** (ÖSYM 265.356 ↔ bizim 256.532). Aynı satırdaki "yerleştirme sırasında eklenen kontenjanlar bu kolona yansıyor" açıklaması da **tersti** — ek kontenjan paydaya girseydi oran düşerdi. İkisi de düzeltildi ve yazıya `guncelleme: 2026-09-22` alanı eklendi (alan olmadan sitemap Google'a "değişmedi" derdi).
**Hiçbiri commit'lenmedi** — senin kararın. Yayın kuyruğu `docs/ekip/YAYIN-KUYRUGU.md`'de.
---
## 3. Marka adı — ekibin sorusuna cevap
**Ad kalıyor. Ekibin "kolaytercih güzel bir isim" görüşü doğrulandı, ama gerekçesi düzeltildi.**
Ad güzel olduğu için değil, üç şeyi bedava taşıdığı için iyi: arama niyetiyle birebir örtüşüyor, "sınav sonrası yerleştirme tercihi" ailesinin tamamına (DGS/KPSS/ALES/MSÜ) genişliyor, telaffuzu ve yazımı tek. **"Ad bizi üniversiteye kilitliyor" korkusu yersiz — kilit adda değil, veride ve mevsimde.**
**Genişleme tetiği (CEO kararı, sayı):** 2027 sezonunda **100 tamamlanmış ödeme** görülene kadar ikinci alan açılmaz. Açılırsa ilk alan **DGS/KPSS** (aynı veri şeması, farklı mevsim — boş kalan Ağustos-Eylül'ü doldurur). **LGS kalıcı ret:** MEB 2026'da kendi yapay zekâ destekli LGS tercih robotunu çıkardı, ücretsiz ve resmî.
**Marka tescili:** "KOLAYTERCİH" tek kelime hâlinde Türkiye'de **hiçbir sınıfta tescilli değil**. Tek yakın kayıt Vodafone'un 2012 tarihli "kolay tercih"i — sona ermiş, ana sınıfımız 41'i kapsamıyor. İzlenecek tek kayıt: "easytercih" (10.03.2026 başvuru, henüz tescilsiz). `kolaytercih.com.tr` boşta ve TRABİS 2022'den beri belge istemiyor.
---
## 4. "Öğrenciler hiç ödeme yapmadı" — neyi yanlış yapıyoruz?
**En önemli bulgu: bu cümle bugün bir pazar bulgusu değil. Kasa kırıktı.**
- 7 Ağu–12 Eyl arası ~100 siparişin **hiçbiri** iyzico token'ı alamadı — ödeme formu bir kez bile açılmadı.
- 30 günde paywall'a **2 kişi** geldi. n=2 ile fiyat hakkında hiçbir çıkarım yapılamaz.
- 21 Eylül'den beri token alınıyor ama **uçtan uca tamamlanmış tek ödeme yok.**
Yani "Türk öğrencisi ödemiyor" değil, "**ödeyemedi**". Bu ayrım her şeyi değiştiriyor.
**Pazar tarafı (araştırıldı):** Eğitimde para var ve ödeyen veli — aile ayda 700–1.300 TL'yi soru çözüm uygulamasına, 1.000–3.000 TL'yi tek seferlik tercih danışmanına verebiliyor. **299 TL bu ölçekte küçük para; fiyat itirazı muhtemelen birincil sorun değil.** Asıl rakibimiz `tercihrobotu.com.tr` değil — **MEB'in 81 ildeki ücretsiz tercih danışmanlığı birimleri.**
**Üründe bulunan üç somut kusur:**
1. `/paket` girişsiz ziyaretçiye birincil butonun altında birebir **"Paketi sonra alırsın."** yazıyor — cüzdanı elinde gelen kişi 299 TL'lik butonu hiç görmüyor.
2. **Ödeyecek kişi (veli) için sitede tek düğme yok.** Tüm `src/` içinde "veli" iki yerde geçiyor, ikisi de aynı özellik satırı ("Veliyle paylaşılabilir PDF") ve o da paywall'un arkasında.
3. **Paket vaadi ↔ kod çelişkisi:** `/paket` "liste dahil" diyor, kod paketliden de liste başına 3 kredi düşüyor.
**CEO'nun kararı:** fiyat ve maske **bu hafta değişmiyor** (kalıcı ret listesinde) — fiyatı gören kimse ödeme ekranına varamadı, veri yok. Sıra: **kasa → söz → önizleme → ödeyici.**
---
## 5. Senden istenen — 3 madde
1. **Disk + içerik yayını** (~25 dk). Komut bloğu `24-ceo-kapanis.md` §C3'te hazır: eski worktree'leri sil → içeriği commit'le → **build'i commit'in kendisi üzerinde doğrula** (APFS klonu, symlink değil) → push.
2. **Canlıda tek gerçek uçtan uca ödeme** (~15 dk). `/paket → /odeme → /odeme/sonuc`, sonra iyzico panelinden iade. Üç satır not: `hasPaket` açıldı mı, kilit çözüldü mü, Rybbit'te `/odeme/sonuc` göründü mü. **Bu olmadan gelir hakkında hiçbir karar veremeyiz.**
3. **Satıcı kimliği 5 satır + Search Console erişimi** (~10 dk). Unvan/ad-soyad, merkez adresi, MERSİS *(tacirsen)* ya da VKN *(esnafsan)*, telefon, KEP. Metin `31-guvenlik-satici-kimligi.md` §1.4'te `TODO-BILAL` boşluklarıyla hazır. Ardından birinci Google hesabını Search Console mülküne tam yetkili ekle.
*(CEO `[BİLAL]` listesini 3'ten 1'e indirdi; kalan tek gerçek karar satıcı kimliği bilgileri — ajan üretemez.)*
---
## 6. Gece boyunca olan iki aksaklık
**(a) İş kaybı — bir kod ajanı `git reset --hard` koştu.** 02:20'de kendi dalında commit düzeltirken çalışma ağacındaki **başkalarına ait commit'lenmemiş** işleri sildi.
| Dosya | Durum |
|---|---|
| `docs/ekip/KARARLAR.md` (senin 2 adet 22 Eylül kaydın) | **Geri yazıldı** — güvenlik ajanının raporunda birebir saklanmıştı |
| `content/rehber/veliler-icin-tercih-rehberi.md` | **Yeniden yazıldı** — yazar ajanı aynı metinle |
| `AGENTS.md` | **Geri yazıldı** — iki ajan tarafından, tam hâliyle |
| `docs/ekip/BACKLOG.md` | Dosya commit'li hâlinde; oturum başında okunan içerik (13 madde + notlar) aynen duruyor. Bunun dışında bir düzenleme varsa **kurtarılamadı** |
Untracked dosyalar (15 yazı, gece raporları) etkilenmedi. **Kural kalıcılaştı:** `AGENTS.md` sonuna "Yıkıcı git komutları yasak" bölümü eklendi — `reset`, `checkout --`, `restore`, `clean`, `stash` ajanlara yasak.
**(b) Oturum limiti** 02:35'te doldu, 06:00'da sıfırlandı. Üç ajan kesildi; ikisi (editör dalga 3, G3) sabah turunda yeniden başlatıldı, biri (SEO) ölmeden önce işini tamamlamıştı.
---
## 7. Kod paketleri
| Paket | Dal | Durum |
|---|---|---|
| **G1** `/sonuc` ilk ekran (tadımlık yukarı, boş harita kalkar, CTA doğru yere gider) | `funnel/sonuc-ilk-ekran` | **Bitti** — 6 commit, `tsc` + `lint` temiz, 7/7 kabul kriteri. Tepedeki `[Bilal]` commit'i (`d2e1190`) yeni CTA cümlesi, tek başına düşürülebilir |
| **G3** paket vaadi (paketliden kredi düşmesin) | `odeme/paket-vaadi` | **Bitti** — 2 commit, 3 dosya, `tsc` + `lint` temiz, 6/6 kabul grep'i. **Güvenlik denetimi: "merge edilebilir", düzeltilmesi gereken satır yok** |
| G4, G2+G5, A2 | — | Yazılmadı; CEO'nun kesme sırasında sondaydılar ve "bu sabah incelemesini istemiyorum" demişti |
**G3'ün güvenlik denetiminden çıkan tek kesinleşme:** yazılımcının "koddan çıkarım" diye işaretlediği kritik soru — `spendCredits(amount: 0)` `INSUFFICIENT` döner mi — izole bir test veritabanında gerçekten koşturuldu. Sonuç: `rowsAffected = 1`, `INSUFFICIENT` dönmüyor, `delta 0` satırı tabloya yazılıyor ve UNIQUE kısıt aynı `(reason, ref_id)` ile ikinci insert'i reddediyor. **Paketin vaadi kodda tutuyor, idempotency çapası kaybolmuyor.**
**Merge'e engel olmayan, kuyruğa giren üç iş:** (F1, orta) paketlide liste üretiminin kredi freni kalktı ve yerine sınır konmadı — repoda rate limit yok, eski tavan 60÷3 ≈ 20 üretimdi; (F2, düşük) `credits.ts:174` `delta 0` iade de `krediBittiAt`'ı null'lıyor → paketlinin top-up hatırlatma e-postası yanlışlıkla iptal olabiliyor; (F3, düşük) `KrediYetersiz` modalı paketlide ulaşılamaz oldu.
**G3 uyum tarafında bir açığı kapatıyor:** `/paket` "60 danışman sorusu" diyordu, gerçekte liste (3) + 2 revizyon (6) düşünce 51 kalıyordu. Artık 60 gerçekten 60.
**Hiçbir dal build'den geçmedi** — disk dar olduğu için `pnpm build` yasaklandı. Build doğrulaması senin sabah komut bloğunda.
---
## 8. Yan bulgular (karar gerektirmeyen ama bilinmesi gereken)
- **Listede yanlış bilgi var:** program tablosunun tooltip'i 11.964 satırda "X kontenjan, Y yerleşen" derken Y > X gösteriyor — `kontenjan` yalnız genel kontenjanı tutuyor, `yerlesen` dört kotanın toplamı. Çözüm tek ternary; "boş kaldı" rozeti **doğru**, dokunulmuyor.
- **`unitur='DEVLET'` güvenilmez:** Kıbrıs Amerikan (42 satır), Uluslararası Saraybosna ve Uluslararası Balkan üniversitelerinin satırları yanlış etiketli. Sihirbazın "Vakıf" kovasına **1.256 KKTC/yurt dışı satırı** giriyor (vakıf havuzunun %13,4'ü).
- **Kök neden bulundu:** `refresh.ts`'in UPDATE yolu `il`/`fakulte`/`isim` alanlarını hiç tazelemiyor — bu değerler 2021'deki ilk CSV'den kalma.
- **Vakıf burs kırılımı yapılabilir:** etiket API'de `birimAdi` içinde geliyor, `--isim-esitle` varsayılan kapalı olduğu için yazılmıyor. Koşu yapılmadan hiçbir yazı burs dağılımı yayımlamamalı.
- **SEO planındaki `netler` tanımı yanlıştı** ("yerleşenlerin ortalaması" değil, **son yerleşen kişinin** netleri) — 9 yerde düzeltildi, §0'a bağlayıcı kural eklendi.
---
## 9. Sıradaki dalga (CEO onaylı)
**Hız: haftada 4 yazı, dalga başına en çok 5 paralel yazar, bir dalga editörden geçmeden sonraki başlamaz.** Takvim: 24 Eyl / 1 Eki / 8 Eki / 15 Eki, dalga başına 4 yazı. Kritik yol iki yerden geçiyor: `puan-turu-nasil-secilir` çıkmadan `on-bir-sinifta-tercih-hazirligi` yazılamaz; `kendi-sehrinde-okumak` ise `il` temizliği merge edilmeden hiç yazılamaz.