# SESSION HANDOFF — iddaai sistem durumu

**Son güncelleme**: 2026-05-25 ~23:00 (Windows'tan Mac'e geçiş öncesi)
**Hedef**: Başka makinede / yeni Claude session'ında bu doc tek başına okunup işin nerede kaldığı anlaşılabilmeli.

---

## 🚨 EN SON DURUM (Mac'e geçmeden önce oku)

### Validation backtest ÖLDÜ
- Pencere: 2026-05-01 → 2026-05-14, 1500 maç
- **1200/1500'de SSH tunnel düşünce process sessizce öldü**
- **CSV kayıp** — script eski versiyondu, sadece sonda yazıyordu
- Sebep: localhost:5432 erişimi kayboldu, psycopg2 connection error

### Script DÜZELTILDI (Mac'te kullanılabilir)
`scripts/diagnostic_backtest.py` artık **crash-safe**:
- `--checkpoint-every 100` → her 100 maçta partial CSV diske yazılır
- Crash sonrası tekrar koşulunca **otomatik kaldığı yerden devam**
- Checkpoint dosyası: `reports/_checkpoint_<window-key>.csv`
- `--no-resume` flag fresh başlamak için

### Git push BEKLİYOR
- 36 dosya **commit edildi (local)** — bkz "Bu seansta yapılan KOD değişiklikleri"
- Push **auth hatası** verdi (gitea credentials cached değil)
- **User Mac'te push yapacak** (Gitea Personal Access Token gerekli, repo write yetkisi)

### Mac'te yapılacaklar (öncelikli sırayla)
1. Repo'yu clone et veya OneDrive'dan kopyala (eğer Mac OneDrive senkronize ediyorsa)
2. `git push origin main` ile pending commit'i remote'a yolla
3. SSH tunnel kur (Pi @ 95.70.252.214, port 2222) → DB için tunnel localhost:5432
4. Yeni Claude session'ı başlat, bu dosyayı oku, devam et
5. Backtest tekrar koştur (çoktan eski versiyondu, şimdi crash-safe)
   ```bash
   cd ai-engine
   export DATABASE_URL="postgresql://iddaai_user:IddaA1_S4crET!@localhost:5432/iddaai_db?schema=public"
   export PYTHONIOENCODING=utf-8
   python scripts/diagnostic_backtest.py --start 2026-05-01 --end 2026-05-14 --max-matches 1500
   # ölürse, aynı komutu tekrar koş — checkpoint'ten devam eder
   ```

### Mevcut sağlam veri
Validation kayıp ama elimizde **in-sample backtest** ve **grid search** çıktıları var:
- `reports/diagnostic_backtest_20260525_035649.{csv,json,txt}` — 1000 maç, May 11-24
- `reports/filter_optimization_patch.json` — grid search winners
- Bu data ile in-sample analiz tamamlandı, validation eksik

---

---

## 🎯 Üst-seviye hedef

Sistem **maç başı-1 saat** kullanıcı tetiklemesiyle çalışacak. Bahis uzmanı seviyesinde:
- **main_pick + value_pick** (sistemin önerdiği)
- **Tüm market olasılıkları** (MS, HT, OU05-45, BTTS, OE, DC, HTFT, HCAP, Cards, Corners)
- **Net HT + FT skoru** + **Top-5 olası skor dağılımı**
- **Evidence panel**: lineup impact, son 5 maç, h2h, hakem profili, benzer-oran-band geçmişi

Ürün modeli: hem user kendi bahisini oynar, hem sistem para kazanırsa abonelik satılır.
Hedef ROI: **≥%10**. Günde **3-5 kaliteli bahis**.

Detaylı requirements doc: bu dosyanın altında, "Requirements Spec" bölümü.

---

## 🟢 Şu an arka planda KOŞAN işler

### 1. Validation backtest (LOCAL — bu laptop)
- **Script**: `ai-engine/scripts/diagnostic_backtest.py`
- **Komut**: `python scripts/diagnostic_backtest.py --start 2026-05-01 --end 2026-05-14 --max-matches 1500`
- **Log**: `ai-engine/validation_full.log` (OneDrive senkronize)
- **Çıkış**: bittiğinde `ai-engine/reports/diagnostic_backtest_<timestamp>.{csv,json,txt}`
- **Tahmini bitiş**: 2026-05-25 ~22:00 (yaklaşık)
- **Amaç**: Yeni kodla (calibrator + ev_edge veto + envelope + coherence + BTTS mute) **out-of-sample** doğrulama
- **Risk**: Laptop uyursa ölür. Bitmesini beklemen lazım VEYA partial sonuçla devam.

```powershell
# Status check (kendin)
$log='C:\Users\fahri\OneDrive\المستندات\GitHub\iddaai\iddaai-be\ai-engine\validation_full.log'
Select-String $log 'rate=|Outputs:' | Select-Object -Last 3 | ForEach-Object {$_.Line}
```

### 2. Feeder historical scan (REMOTE — Pi server)
- **Konum**: SSH @ haruncan@95.70.252.214:2222 → docker container `iddaai-be` → pm2
- **PM2 process**: `feeder-historical` (id=1)
- **Log rotation**: pm2-logrotate kurulu (max 30MB/dosya, 3 dosya, gzip)
- **Davranış**: 2026-05-03'ten geriye 2023-06-01'e kadar mackolik'ten odds/lineup patch
- **Otomatik restart**: 502 olunca 30 sn delay sonra restart (max 1000 kez)
- **Beklenen süre**: 24-72 saat

```bash
# Status (kendin SSH'la)
sudo docker exec iddaai-be pm2 list
sudo docker exec iddaai-be pm2 logs feeder-historical --lines 30 --nostream
```

---

## 📝 Bu seansta yapılan KOD değişiklikleri

Hepsi local repo'da, OneDrive senkronize edecek, başka makinede pull etmesen de açtığında orada olacak.

### A. Settlement / data layer
| Dosya | Değişiklik |
|---|---|
| `iddaai-be/prisma.config.ts` | `.env` fallback ekledim (`.env.local` üstüne) — `prisma generate` çalışsın diye |
| `iddaai-be/src/tasks/prediction-settlement.market-resolver.ts` | DC parser ayraçsız "1X/X2/12" kabul ediyor + HT_OU05/HT_OU15/HT_OU25 resolver eklendi |
| `iddaai-be/src/tasks/feature-enrichment.task.ts` **(YENİ)** | Cron 08:15 — eksik football_ai_features row insert + odds_movement SQL backfill |
| `iddaai-be/src/tasks/python-enrichment.task.ts` **(YENİ)** | Cron 08:25 — Python `enrich_ai_features.py` subprocess |
| `iddaai-be/src/tasks/tasks.module.ts` | İki yeni task register |
| `iddaai-be/src/scripts/run-feature-enrichment.ts` **(YENİ)** | Manuel one-shot trigger |

### B. AI engine — betting brain
`iddaai-be/ai-engine/services/betting_brain.py` — büyük revizyon:
- **HARD_MIN_SAMPLES = 50** floor (calibrator bypass <50 sample)
- **`ev_edge < 0.0` HARD VETO** (`negative_ev_edge`)
- **`ev_edge >= 0.20` HARD VETO** (`ev_edge_too_high_trap`)
- **`MUTED_MARKETS = {"BTTS"}`** — backtest no profitable config bulduğu için
- **`MARKET_OPTIMAL_FILTERS`** — MS ve OU25 için grid-search'ten gelen optimal envelope
- **`_score_consistent_markets()`** — skor tahminine uymayan picks elimine
- **`judge()` score coherence filter** — main_pick coherent set'ten seçilir
- **HTFT reversal cross-check** — Man City 1/2 senaryosu

### C. AI engine — model & calibration
| Dosya | Değişiklik |
|---|---|
| `ai-engine/models/calibration.py` | HARD_MIN_SAMPLES floor + sample-weighted blend formülü değişti |
| `ai-engine/models/calibration/*.pkl` | **10 calibrator retrain** (ms_home/draw/away, ou15/25/35, btts, ht_home/draw/away) — 4989-5000 sample her biri |

### D. AI engine — orchestrator feature builder
`ai-engine/services/orchestrator/feature_builder.py`:
- Hardcoded `home_position=10, away_position=10` → real `data.home_position` kullanılıyor
- Cup detection upper'a taşındı, `is_cup_match` UpsetEngine'e geçiyor
- Total teams parametresi UpsetEngine'e geçiyor

`ai-engine/services/orchestrator/data_loader.py`:
- `_estimate_league_position` artık **sezon filtresi** (son 300 gün) kullanıyor

### E. AI engine — scripts (yeni)
| Dosya | Ne yapıyor |
|---|---|
| `ai-engine/scripts/diagnostic_backtest.py` | Per-bet diagnostic backtest (CSV+JSON+TXT output) |
| `ai-engine/scripts/analyze_backtest_csv.py` | Backtest CSV üzerinde root-cause hipotez testleri |
| `ai-engine/scripts/optimize_filters.py` | Grid search per-market optimal threshold |
| `ai-engine/scripts/compare_backtests.py` | İki CSV karşılaştırması verdict ile |
| `ai-engine/scripts/test_score_coherence.py` | Coherence filter smoke test (LAFC senaryosu) |

### F. Social poster modülü (NestJS)
| Dosya | Değişiklik |
|---|---|
| `src/modules/social-poster/social-poster.service.ts` | Cron 15→10 dk, window 10-60, MAX_POSTS_PER_RUN, getHealthStatus() |
| `src/modules/social-poster/image-renderer.service.ts` | SEO filename + metadata sidecar (.json) |
| `src/modules/social-poster/caption-generator.service.ts` | SEO hashtag stratejisi (12 küratör tag) |
| `src/modules/social-poster/social-poster.controller.ts` | `/health` public + `/preview-png/:matchId` + `/run-now` endpoints |
| `mds/SOCIAL_POSTER_SETUP.md` **(YENİ)** | Env vars + API key alma adımları + test komutları |

### G. Modern image rendering (deneme)
| Dosya | Açıklama |
|---|---|
| `src/scripts/render-social-card-v3.ts` | satori + resvg-js ile modern HTML→PNG rendering (Twemoji top + bayrak) |
| `src/modules/social-poster/assets/*.svg` | Twemoji futbol/basket/bayrak SVG'leri |

### H. Yapılan DB değişiklikleri (idempotent — tekrar koşturulursa sorun yok)
| İşlem | Etki |
|---|---|
| `football_ai_features` 4008+ satır backfill | Son 60 günün FT maçları için feature row var artık (calculator_ver=feature_enrichment_task_v1) |
| Python enrichment koştu | h2h, referee, possession, league_avg, implied_* hepsi gerçek değerlerle dolu (181,614+ satır enriched) |
| Calibrator dosyaları yazıldı | `ai-engine/models/calibration/*.pkl` overwritten |

---

## 📂 Önemli dosya konumları (OneDrive synced)

```
iddaai-be/
├── mds/
│   ├── SESSION_HANDOFF.md            ← BU DOSYA
│   └── SOCIAL_POSTER_SETUP.md        ← social poster env+keys
├── ai-engine/
│   ├── reports/                      ← BACKTEST CIKTILARI
│   │   ├── diagnostic_backtest_*.csv,json,txt
│   │   └── filter_optimization_patch.json
│   ├── validation_full.log           ← validation backtest canlı log
│   ├── diagnostic_backtest_run.log   ← önceki backtest log
│   ├── enrichment_run3.log           ← enrichment koşma log
│   └── calibration_run.log           ← calibrator retrain log
├── public/predictions/               ← render edilmiş social card PNG/JSON
└── src/scripts/                      ← tüm yeni script'ler
```

---

## 🔑 Erişim bilgileri

### Pi sunucu (feeder + prod stack)
- **SSH**: `haruncan@95.70.252.214:2222`
- **Şifre**: `M594xH%$iM&4MM`
- **Plink kullan**: `~/plink.exe -ssh -P 2222 -pw '<password>' -hostkey 'SHA256:iq0YVI/4J897sf9dkksI7QzetpLCD0l57ZMX4UissI8' haruncan@95.70.252.214`
- **Docker**: `iddaai-be`, `iddaai-ai-engine`, `iddaai-fe`, `iddaai-postgres`, `iddaai-redis`, `gitea`

### DB (uzak Postgres @ Pi)
- **SSH tunnel function**: `iddaai-db` PowerShell fonksiyonu (yerel makinedeki profile'da kayıtlı)
- **Tunnel: localhost:5432 → Pi:5432**
- **Connection string**: `postgresql://iddaai_user:IddaA1_S4crET!@localhost:5432/iddaai_db?schema=public`
- **MCP**: Claude'un postgres MCP'si bu tunnel üzerinden çalışıyor (restricted mode, read-only)

---

## 📊 BACKTEST sonuçları geçmişi

### Backtest #1 — In-sample grid search (2026-05-11 → 05-24, 1000 maç)
- **CSV**: `ai-engine/reports/diagnostic_backtest_20260525_035649.csv`
- **TXT**: `ai-engine/reports/diagnostic_backtest_20260525_035649.txt`
- **Toplam playable**: 524 bet
- **Hit rate**: %54.77
- **ROI**: **−%16.73** (baseline kötü)
- **Grid-search'ten çıkan optimal filtreler (in-sample)**:
  - MS: edge [-5%, +15%], V27 AGREE zorunlu → +%8.23 (21 bet)
  - OU25: odds ≥ 1.80, edge ≤ +15% → +%28.91 (20 bet)
  - BTTS: tüm config'lerde kayıp → MUTE
- **Aggregate optimize**: 95 bet, ROI +%2.16 (in-sample)

### Backtest #2 — Validation (2026-05-01 → 05-14, KOŞUYOR)
- **Bitince konum**: `ai-engine/reports/diagnostic_backtest_<yeni_timestamp>.{csv,json,txt}`
- **Karşılaştırma çalıştır**: `python scripts/compare_backtests.py` (otomatik en yeni 2'yi alır)
- **Beklenen sonuç**: ROI ≥ 0 → out-of-sample doğrulama BAŞARILI; in-sample overfit değil

---

## ❓ Backtest BİTTİĞİNDE yapılacak (yeni session'da bu kısımdan başla)

### 1. Sonucu oku
```powershell
cd C:\Users\fahri\OneDrive\المستندات\GitHub\iddaai\iddaai-be\ai-engine
Get-ChildItem reports\diagnostic_backtest_*.txt | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Get-Content
```

### 2. Karşılaştır
```powershell
python scripts\compare_backtests.py
```

Bu otomatik en yeni 2 backtest'i karşılaştırır, **VERDICT** verir:
- ✅ "FILTERS WORK" → ROI pozitif AND improved
- 🟡 "PARTIAL" → improved ama hâlâ negatif
- ❌ "OVERFITTING" → validation ROI collapse

### 3. Karara göre 2 yol

**Eğer ROI ≥ +%2 ve overfit yok:**
- `/sc:design` ile UI/API contract → Sprint 1
- Sprint 1: top-5 skor + evidence panel + "why" cümlesi
- Test edip prod'a aç

**Eğer ROI negatif veya overfit:**
- `analyze_backtest_csv.py` ile loss diagnostic
- Hangi market hâlâ kötü → tighten filter veya mute
- Calibrator recalibrate (özellikle BTTS dışındakiler için yeni sample)
- Tekrar backtest

---

## ⚠️ Bilinen açık problemler / sorular

1. **Coherence filter validate edilmedi production-side** — smoke test 20/20 ama gerçek production data ile karşılaştırma yok
2. **Lineup-overlap last-5 hesabı** — yazılmadı, requirements doc'ta F8 var
3. **Skor top-5 distribution** — Poisson zaten hesaplıyor, surface edilmedi (UI tarafı)
4. **"Why" cümlesi main_pick'te** — boş, doldurulması gerek
5. **Cards/Corners/RED CARD model** — yok, "henüz desteklenmiyor" placeholder ile bırak (kullanıcı onayladı: mevcut market'ler sağlamlaşsın)
6. **Orphan match_id 51 satır** — `prediction_runs` içinde, `matches`'ta yok. Sample noise, geçiştirilebilir.
7. **opening_value feeder bug** — `odds_movement_*` SQL yazıyor ama tüm değerler 0 (opening == closing). Feeder upstream sorun. Düşük öncelik.

---

## 🚦 Yeni Claude session'ında ilk komut

```
Bu projeye yeni bağlandım. Lütfen aşağıdaki dosyayı oku ve bana proje durumunu özet ver:

C:\Users\fahri\OneDrive\المستندات\GitHub\iddaai\iddaai-be\mds\SESSION_HANDOFF.md

Sonra validation backtest'in sonucuna bak:
- C:\Users\fahri\OneDrive\المستندات\GitHub\iddaai\iddaai-be\ai-engine\reports\
  içindeki en yeni diagnostic_backtest_*.txt dosyasını oku
- compare_backtests.py script'ini koş, verdict göster
- Verdict'e göre sonraki adımı öner
```

Buradan devam eder. Tüm context bu doc'ta + dosyalarda + DB'de.

---

## 🛠️ Requirements spec (sıkıştırılmış)

**Ürün**: UI-tetikli per-match analiz, bahis uzmanı seviyesi
**Trigger**: User tıklar, on-demand
**Output**: main_pick + value_pick + tüm market olasılıkları + tek HT/FT skoru + top-5 skor dağılımı + evidence panel
**Kapsam**: Mevcut market'ler sağlamlaştırılır, yeni market eklenmez (kullanıcı onayı)
**Quality bar**: Calibration sapması ±2-5pp per market, NaN yok, response <3sn
**Validation**: Out-of-sample backtest (1500 maç, May 1-14) — KOŞUYOR

---

**SON NOT**: Backtest'in TAMAMLANMASINI bekle (~22:00). Laptop'u kapatma. Bittiğinde OneDrive senkronize eder, başka makinede otomatik orada olur. Yeni session'da bu dosyayı oku, sonuçlara bak, devam et.
