/** * Danışman cevabının deterministik (anahtarsız) çıktı denetimi. * * Jev denetimi (jev.ts) anahtar yoksa, zaman aşımında ya da hata olursa * atlanır ve "olasılığın düşük" türü cümlelere eşiğin altında değer * verebiliyor (5 Eki 2026 eval: gri bölgedeki 18 kararın 13'ü gerçek ihlaldi). * Buradaki kalıplar her cevapta, ağ çağrısı olmadan koşar; sohbet-akisi.ts * ikisinden biri yakalarsa düzeltme notunu ekler. * * Ürün kuralı (KARARLAR.md: olasılık vermiyoruz): yerleşme garantisi YOK, * yerleşmeyi olasılık / yüzde / ihtimal / şans diliyle tahmin etmek YOK — * "olasılığın düşük" de buna dahil. İhlal SAYILMAYANLAR: reddeden cümleler * ("garanti verilemez", "'kesin yerleşirsin' diyemem"), Güvenli / Az riskli / * Riskli etiketleri, burs / doluluk / istihdam yüzdeleri. * * Saf modül: DB'ye ve ağa dokunmaz, Next dışından da çalışır. */ const tr = (s: string) => s.toLocaleLowerCase("tr-TR"); /** * Reddeden / olumsuzlayan söz. Türkçede olumsuzluk yüklemin sonundadır; bu * yüzden yalnız eşleşmeden SONRA ve aynı yan cümlede aranır ("garanti yok ama * şansın yüksek" cümlesindeki "yok" ikinci yarıyı aklamaz). */ const RED = /verme[mzy]|verem|verilem|vermiyor|veremiyor|değil|yok(?!sa)|diyem|demem|demiyor|denem|denilem|denmez|söyleyem|söylenem|söylemiyor|olmaz(?!sa)|edem|etmiyor|hesaplam|tahmin etm|anlamına gelm|kullanm|kullanam|yapam|yapmıyor|sunam|bilinem|bilem|yanlış|yerine|doğru olmaz/; /** Yan cümle sınırı: nokta, satır sonu ve "ama / ancak / fakat" bağlaçları. */ const YAN_CUMLE_SONU = /[.!?;\n]|\s(?:ama|ancak|fakat|yine de|lakin)\s/; /** "girersin" bunların hemen ardından geliyorsa yerleşme değil, sisteme/sınava giriştir. */ const GIRIS_BAGLAMI = /ais|sınav|sistem|site|sayfa|hesab|panel|oturum/; /** "iş bulma şansı", "istihdam olasılığı": yerleşme tahmini değil. */ const ISTIHDAM_BAGLAMI = /iş bulma|işe girme|istihdam|mezun/; const VAAT_KALIPLARI: RegExp[] = [ // kesinlik zarfı + yerleşme fiili: "kesin yerleşirsin", "rahatça girersin", "en rahat yerleşeceğin" /(?:kesin(?:likle)?|rahat(?:ça|lıkla)?|garanti(?:li)?|mutlaka|yüzde yüz|%\s?100)\s+(?:olarak\s+|bir\s+şekilde\s+)?(?:yerleş|gir(?:er|ebil|ecek)|kazan|tut(?:ar|acak)|gel(?:ir|ecek))/g, // yalın vaat fiilleri /(?:yerleşirsin|yerleşeceksin|yerleşirsiniz|yerleşeceksiniz|girersin|gireceksin|kazanırsın|kazanacaksın|açıkta kalmazsın|açıkta kalmayacaksın|açıkta kalman imkânsız)/g, /(?:söz veriyorum|garanti (?:veriyorum|ediyorum|veriyoruz|ediyoruz))/g, // olasılık dili (yüksek de düşük de): "yüksek ihtimal", "düşük bir olasılık", "büyük ihtimalle" /(?:yüksek|büyük|güçlü|kuvvetli|düşük|zayıf|az|küçük)\s+(?:bir\s+)?(?:ihtimal|olasılık)/g, /(?:yerleşme|yerleşebilme|girme|kazanma|tutma|gelme)\s+(?:şans|ihtimal|olasılı[kğ])\p{L}*/gu, /(?:ihtimal|olasılı[kğ]|şans)\p{L}*\s+(?:çok\s+|daha\s+|oldukça\s+|epey\s+)*(?:yüksek|düşük|iyi|fazla|az|zayıf|güçlü|yarı yarıya)/gu, /şans(?:ın|ınız)\s+var(?!\s*m[ıi])/g, // sayıyla olasılık: "%80 ihtimalle", "yüzde seksen şans" /(?:%\s?\d+|yüzde\s+[\p{L}\d]+)\s*(?:ihtimal|olasılık|şans)/gu, // eski dilim adı /garanti\s+(?:dilim|tercih|liste|seçenek)/g, ]; /** * Metindeki garanti / olasılık dili adayları (çevresiyle birlikte kısa alıntı). * Reddeden yan cümledekiler ve istihdam / sisteme giriş bağlamındakiler elenir. * Boş dizi = temiz. */ export function vaatDiliBul(metin: string): string[] { const m = tr(metin); const bulunan: string[] = []; for (const kalip of VAAT_KALIPLARI) { for (const e of m.matchAll(kalip)) { const i = e.index ?? 0; const son = i + e[0].length; const kalan = m.slice(son, son + 90); const sinir = kalan.search(YAN_CUMLE_SONU); const ardi = sinir < 0 ? kalan : kalan.slice(0, sinir); if (RED.test(e[0]) || RED.test(ardi)) continue; // Tırnak içinde anılan ifade ("kesin tutar" gibi bir söz…) kullanım değil, alıntıdır if (/["'“”‘’«]$/.test(m.slice(Math.max(0, i - 1), i)) && /^["'“”‘’»]/.test(kalan)) continue; const once = m.slice(Math.max(0, i - 30), i); if (/^gir/.test(e[0]) && GIRIS_BAGLAMI.test(once)) continue; if (ISTIHDAM_BAGLAMI.test(once)) continue; bulunan.push(m.slice(Math.max(0, i - 25), son + 25).replace(/\s+/g, " ").trim()); } } return bulunan; } /** * Cevap "kaydettim" türü bir kayıt beyanı içeriyor mu. Kayıt yalnız * profil_guncelle aracıyla olur; model aracı çağırmadan "Kaydettim" diyebiliyor * (QA H4, 5 Eki 2026). Olumsuzlar ("kaydetmedim", "kaydedemedim") ve soru * ("kaydedeyim mi?") eşleşmez. */ const KAYIT_BEYANI = /(? m.includes(ad.toLocaleLowerCase("tr-TR"))).length >= 3; }