Skip to main content
Glama
alatifkose

DefterIki

by alatifkose

DEFTERIKI

Kişisel finans kayıt sistemi. Belgeler Cowork tarafından okunur, MCP kapısından DEFTERIKI'ye yazılır; uygulama kayıtları tutar, denetler ve gösterir.

Durum

Aşama 2 (proje temeli) ve Aşama 3 (gerçek Cowork MCP denemesi) tamamlandı; Aşama 3'ün dört teslimi ve ölçümleri "Cowork entegrasyonu" bölümünde. Aşama 4 (veritabanı çekirdeği) tamamlandı: Teslim 4.1–4.6 ve kapı (uçtan uca işlev testi, şema başlangıç akışına bağlı). Aşama 5 (dar MCP araçları) sürüyor: 5.1 (zarf, hata, işlem anahtarı) ve 5.2 (on üç araç: nesne, belge/hareket, durum/sorgu; geçici onay komutu) ve 5.3 (Cowork talimatı docs/cowork.md 0.1, gerçek ekstre denemesi başarılı, tekrar denemesi yazmadı) bitti; Aşama 5 kapısı geçildi (2026-09-17), bulgular "Cowork talimatı" bölümünde. Aşama 6 (ilk pencere) sürüyor: 6.1 kabuk ve değişiklik izleme, 6.2 karar kutusu (onay pencereden), 6.3 bakiye ve hareket görünümü bitti; Aşama 6 kapısı geçildi (2026-09-17): Akbank ekstresi onaylar pencereden verilerek yeniden işlendi, bakiye pencerede görüldü; geçici defteriki-onay komutu silindi. Talimat sürümü 0.2. Kararlar (2026-09-17, Abdüllatif): defter_tanimla/defter_listele ve "seçili defter" tek defter kararıyla düştü; kullanıcı onayı Aşama 6'ya kadar geçici defteriki-onay komut satırından verildi (MCP'ye açılmadı; onay mekanizması terminale bağlanmadı; komut Aşama 6 kapısında silindi, onay artık pencerede); gerçek ekstre yerelde gelen dizininden, depoya girmez. Karar (2026-09-16, Abdüllatif): DEFTERIKI tek bütünleşik defterdir; ayrı defter yoktur (sözlük: Defter; Tam Plan C01 iptal). Şema ve 4.3 buna göre yeniden kuruldu. Bitenler:

  • uv ile paket iskeleti (src/defteriki)

  • Merkezi ayar yönetimi (src/defteriki/ayarlar.py)

  • Başlangıç akışı: uv run defteriki (src/defteriki/baslangic.py)

  • Teknik hata günlüğü (src/defteriki/gunluk.py)

  • Test altyapısı (pytest + Hypothesis)

  • Tek komutluk kalite kontrolü (Ruff, Pyright strict, pytest)

  • .gitignore ve .gitattributes; kritik dışlama kuralları testle doğrulanır (tests/test_gitignore.py)

  • MCP kapısı iskeleti: uv run defteriki-mcp, tek araç sistem_durumu (src/defteriki/mcp_kapisi.py); Cowork ile bağlantı, dosya erişimi ve çok adımlı protokol gerçek istemciyle ölçüldü

  • Ortak sözleşmeler: katı kimlik ve kuruş tutar, yön/eksen/para birimi, durum adları, hata ailesi, sayfalama (src/defteriki/sozlesmeler.py)

  • Veritabanı bağlantısı ve işlem sınırları: WAL, BEGIN IMMEDIATE, salt okunur okuma, geri alma garantisi (src/defteriki/veritabani.py)

  • Şema ve ilk migration: on beş tablo, isimli kısıtlar, Alembic ile sürüm denetimi (src/defteriki/sema.py, migrations/)

  • Onay talebi, işlem anahtarı ve denetim olayı: kalıcı BEKLIYOR talep, yalnız ekrana açık sürüm denetimli karar, aynı anahtar aynı sonuç (onaylar.py, islem_anahtarlari.py, denetim.py)

  • Nesne tanıtma: serbest özellikli form, üstlerden hesaplanan seviye, ONAY_BEKLIYOR ile yazılıp onayda şart seçimiyle AKTIF, türüyle eşleşme değeri, bulma (nesneler.py)

  • Belge arşivi ve belge akışı: gelen dizininden içerik adresli arşive atomik kopya, belge tanımlama (aynı dosya tek belge), okuma, atomik satır gönderimi, okuma tamamlama ve uygulamanın tanımladığı belge kaydı (arsiv.py, belgeler.py)

  • Tek işlem türü ve etkin bakiye: HESAP_HAREKETI sözleşmesi (saf doğrulama), hareket yazma (kaynak satırı zorunlu, aynı anahtar tek etki), yalnız KAYITLI belgeye dayanan bakiye ve hareket listesi (finansal_kurallar.py, kayitlar.py, hesaplamalar.py)

  • Aşama 4 kapısı: uv run defteriki ve uv run defteriki-mcp başlangıçta şemayı kurar ya da sürümünü denetler (baslangic.semayi_hazirla); uçtan uca işlev testi nesne onayından bakiyeye kadar zinciri tek testte doğrular (tests/test_asama4_kapisi.py)

  • MCP yanıt zarfı ve güvenli hata çevirisi; ilk değişiklik aracı nesne_tanimla (FORM/GONDER) MCP'de (zarf.py, mcp_araclari.py, mcp_kapisi.py)

  • Nesne araçları nesne_bul, nesne_getir, oturum_baglami (C16); geçici onay komutu (defteriki-onay) Aşama 6 kapısında silindi

  • Belge ve hareket araçları belge_al, belge_getir, okuma_baslat, hareket_yaz (paket, atomik), okuma_tamamla, belge_kaydet: bir ekstre MCP araçlarıyla uçtan uca işlenir; zarf her adımda belge_kaydi söyler

  • Durum ve sorgu araçları islem_durumu (talep ya da işlem anahtarıyla kalıcı durum), bekleyen_isler, sorgu (yalnız bakiye ve hareketler; serbest SQL yok)

  • Cowork talimatı docs/cowork.md (sürüm 0.2): araç sırası (oturum bağlamı → belge → nesne → okuma → paketler → tamamlama → rapor), işlem anahtarı kuralları, yasaklar, hata kodu tepkileri

  • Aşama 5 kapısı: gerçek Akbank ekstresi Cowork'la uçtan uca işlendi (iki nesne onayı, altı hareket, KAYITLI, bakiye); aynı belge ikinci kez yazılmadı; bulgular ve açık kararlar "Cowork talimatı" bölümünde

  • Pencere kabuğu ve değişiklik izleme (Teslim 6.1): uv run defteriki-arayuz, aynı hazırlık akışı, durum çubuğu, Veritabani.degisiklik_sayaci() ile başka süreçlerin yazdığını görme (src/defteriki/arayuz/)

  • Karar kutusu (Teslim 6.2): bekleyen talepler, hedef nesne ve özellikleri, kutucukla şart seçimi, Onayla / Reddet / Ertele; pencere_islevleri üzerinden onaylar.karar_uygula (arayuz/karar_kutusu.py)

  • Bakiye ve hareket görünümü (Teslim 6.3): hesap seçimi, etkin bakiye, hareketler kayıtlı/kayıtlı değil işaretiyle ve belgeleriyle, belge listesi, kaynak belgeyi işletim sistemiyle açma (arayuz/hareketler.py; belgeler.belgeleri_listele, belgeler.kaydin_belge_idleri)

Henüz yok: Aşama 6 kapısı (ekstre denemesi pencereden), devreden bakiye kararı, diğer işlem sözleşmeleri (Aşama 8), mükerrerlik karşılaştırması (Aşama 7).

Related MCP server: SQLite MCP Server

Kurulum

uv sync

Python 3.13 ve uv gerekir. uv sync sanal ortamı ve geliştirme bağımlılıklarını (pytest, hypothesis, ruff, pyright, pre-commit) kurar.

Klon sonrası bir kez, commit öncesi kontrol kancasını yükle:

uv run pre-commit install

Başlatma

uv run defteriki

Komut sırayla ayarları ortam değişkenlerinden yükler, seçilen ortamın dizinlerini (veritabanı dizini, belgeler/, logs/, gelen/) açar, teknik günlüğü kurar, veritabanı şemasını hazırlar ve başlangıç olayını günlüğe yazar. Başarılıysa tek satırlık bir mesaj (ortam, veri kökü, şema sürümü, günlük dosyası) basar ve 0 ile çıkar. Finansal iş yapmaz; ekran yok.

Şema hazırlığı (Aşama 4 kapısı). Veritabanı dosyası ya da alembic_version yoksa yeni kurulumdur: migration'lar uygulanır, dosya oluşur, günlüğe sema_kuruldu düşer; yedeklenecek bir şey olmadığından bu adım otomatiktir. Şema kuruluysa sürümü uygulamanın beklediğiyle (BEKLENEN_SEMA_SURUMU) aynı olmalıdır; farklıysa başlangıç "Şema hatası" ile 1 döner ve hiçbir şey yazılmaz. Yükseltme açık bir adımdır: önce yedek, sonra uv run alembic upgrade head. MCP kapısı aynı hazırlığı kullanır; sistem_durumu gerçek şema sürümünü döndürür.

Herhangi bir adım başarısızsa (DEFTERIKI_ORTAM bilinmeyen değer, test ortamında veri kökü verilmemiş, dizin yerine dosya var, log dosyası açılamıyor...) anlaşılır bir hata stderr'e yazılır ve çıkış kodu 1 olur. Günlük kurulamadıysa başarılı başlangıç mesajı verilmez. Yollar uygulamanın hangi dizinden başlatıldığına bağlı değildir; modüller import edildiğinde dizin ya da dosya oluşturulmaz.

MCP kapısı

Cowork'un DEFTERIKI'ye ulaştığı tek kapı. stdio taşımasıyla çalışır:

uv run defteriki-mcp

Komut uv run defteriki ile aynı hazırlığı yapar (ayarlar, dizinler, günlük), ardından MCP sunucusunu stdin/stdout üzerinde çalıştırır. İstemci bağlantıyı kapatınca 0 ile çıkar. Hazırlık düşerse hata stderr'e yazılır, çıkış kodu 1 olur; stdout'a hiçbir şey yazılmaz.

Araçlar (YETENEKLER, kayıt sırasıyla): sistem_durumu (uygulama sürümü, ortam, şema sürümü (BEKLENEN_SEMA_SURUMU), yetenek listesi, talimat sürümü; yol ya da sır içermez), nesne_tanimla (FORM/GONDER, 5.1), nesne_bul, nesne_getir, oturum_baglami (5.2/1), belge_al, belge_getir, okuma_baslat, hareket_yaz, okuma_tamamla, belge_kaydet (5.2/2), islem_durumu, bekleyen_isler, sorgu (5.2/3). Toplam on dört araç. Aşama 3'ün geçici deneme araçları kaldırıldı; ne ölçtükleri "Cowork entegrasyonu" bölümünde. Gelen dizini ayarı (DEFTERIKI_GELEN_DIZINI) kaldı: belge alımı Cowork'un bu dizine bıraktığı dosyanın yoluyla yapılır.

Yanıt zarfı ve hata (Teslim 5.1)

Her araç aynı zarfı döndürür (src/defteriki/zarf.py, Pydantic; SDK JSON Schema üretir): durum TAMAMLANDI / BEKLIYOR / REDDEDILDI / YENIDEN_DENE; islem_kimligi (çağrı başına korelasyon kimliği, günlükteki mcp_arac satırıyla eşleşir); talimat_surumu (docs/cowork.md, şimdilik 0.2); belge_id, okuma_id, nesne_id, talep_id, hedef_surumu; yazilan, zaten_mevcut, bekleyen sayıları; belge_kaydi TANIMLANMADI / KAYITLI; sonraki_adim (Cowork'a kısa yönerge); icerik (aracın kendi sonucu); hata (kod, güvenli mesaj, alan, konum, tekrar denenebilirlik). "Başarılı" tek başına "kayıtlı" demek değildir; belge_kaydi KAYITLI olmadan yazılanlar hesaba girmez (K19).

Hata çevirisi (mcp_kapisi.araci_calistir): ürün hatası kodlu REDDEDILDI, sonraki_adim Tam Plan 11.2 tablosundan koda göre (zarf.SONRAKI_ADIMLAR: "Kaynağı tamamla", "yuvarlama ya da kur uydurma", "eksik satırı çöz, sonra yeniden tamamla" ...); VERITABANI_MESGUL YENIDEN_DENE ("aynı anahtarla tekrar dene, yeni anahtar üretme"); beklenmeyen hata BEKLENMEYEN_HATA (mesaj zarfa girmez, türü günlüğe, korelasyon kimliğiyle). SDK'nın kendi girdi doğrulama hatası (ToolError) dışarı verilmez: metni Pydantic'in input_value dökümünü içerir, yani belge içeriği ya da kimlik bilgisi sızabilir. DefterikiSunucusu.call_tool onu yakalar, ValidationError.errors'dan yalnız alan yollarını ve hata türlerini alır (girdi.ust_idleri.0 (int_type) gibi) ve GIRDI_GECERSIZ zarfı döndürür; değer ne zarfa ne günlüğe girer. Bilinmeyen araç adı SDK hatasıyla döner.

Araç gövdeleri src/defteriki/mcp_araclari.pyde: kural yok (K01); girdi modelini alır, işlem sahibi olarak yazma/okuma işlemini açar, Aşama 4 işlevini çağırır, zarfı döndürür; sunucudan bağımsız test edilir. Her değişiklik yapan araçta islem_anahtari zorunludur (K08); eksikse GIRDI_GECERSIZ (alan islem_anahtari), aynı anahtar aynı içerik aynı sonuç, farklı içerik ANAHTAR_ICERIK_CAKISMASI. MCP'den gelen her yazmanın aktörü COWORK. nesne_tanimla: adim=FORM boş form ve kuralları (veritabanına dokunmaz); adim=GONDER nesneyi ONAY_BEKLIYOR yazar, zarf BEKLIYOR + talep_id + hedef_surumu, sonraki_adim "kullanıcı kararı bekleniyor; islem_durumu ile sonra sor, kendi kendine onay üretme". Nesne AKTIF ise TAMAMLANDI, silinmişse REDDEDILDI (hata yok, icerik söyler).

Test (tests/test_mcp_araclari.py): FORM veritabanına dokunmaz; GONDER BEKLIYOR + talep kimliği; anahtarsız GONDER ret; aynı anahtar aynı sonuç, farklı içerik çakışma; ürün hatası kod ve alanıyla; veritabanı meşgulken YENIDEN_DENE; beklenmeyen hata mesajı zarfa girmez, türü günlüğe; zarfta yol ve ortam değişkeni yok; sunucu üzerinden şema reddi değerleri dışarı vermez; bilinmeyen araç; araç listesi ve şemalar; sunucu üzerinden GONDER. stdio testi (test_mcp_kapisi.py) araç listesini ve talimat_surumunu görür.

Nesne araçları (Teslim 5.2/1)

Okuma araçları salt okunur işlemde çalışır, işlem anahtarı istemez.

  • nesne_bul(alan_adi, deger, deger_turu, seviye, durumlar, sayfa_siniri, sayfa_baslangici): nesneler.nesne_bul + özellikler tek sorguyla (nesneler.ozellikleri_getir). icerik.nesneler her nesne için kimlik, seviye, durum, sürüm ve özellikler (kimlik, alan adı, değer, tür, şart); icerik.sayfa sınır/başlangıç/dönen. Eşleşme türüyle ve normalizasyonsuz ("AD" ≠ "ad", "garanti bbva" ≠ "Garanti BBVA"). sonraki_adim: bulunduysa "kimliğini kullan, yeniden önerme", yoksa "kanıtı varsa nesne_tanimla ile öner". Geçersiz sayfalama GIRDI_GECERSIZ.

  • nesne_getir(nesne_id): özellikler (şart işaretli), üstler, altlar, sürüm (hedef_surumu); yoksa HEDEF_BULUNAMADI.

  • oturum_baglami(son_nesne_sayisi=20): Tam Plan C16 — kalıcı kimlikler DEFTERIKI'dedir; Cowork oturum başında son açılan nesneleri (yeniden eskiye, özellikleriyle), kullanılan alan adlarını (kullanım sayısıyla; nesneler.alan_adlarini_listele) ve kullanıcı kararı bekleyen işleri (onaylar.bekleyenleri_listele: talep, tür, hedef, sürüm, zaman) alır; zarf bekleyen sayısını taşır. "Seçili defter" tek defter kararıyla yok.

Geçici onay komutu (defteriki-onay, karar 2026-09-17) Aşama 6 ekranı gelene kadar kullanıcı onayını verdi; MCP'ye açılmadı, karar mantığı onaylar.karar_uygulada kaldı. Aşama 6 kapısında (2026-09-17) dosyası, testi ve pyproject.toml girişi silindi; onay artık pencerenin karar kutusundan verilir.

Test (tests/test_mcp_nesne_araclari.py): boş sonuç yönlendirmesi; mevcut nesne özellikleriyle, seviye ve durum filtresi, sayfalama; eşleşme türüyle ve normalizasyonsuz; geçersiz sayfalama; getir (özellik, üst, alt, sürüm, bekleyen nesnede yönerge); olmayan nesne; oturum bağlamı boş defter ve Garanti senaryosu (son nesneler yeniden eskiye, alan adı sayımı, bekleyen iş); sunucu üzerinden dört araç ve şema reddi.

Belge ve hareket araçları (Teslim 5.2/2)

Araç gövdeleri AracBaglami(veritabani, ayarlar) alır; belge araçları gelen ve belge dizinini ayarlardan okur. Her araç zarfta belge_id, okuma_id, hedef_surumu (belge sürümü) ve belge_kaydi taşır; "yazıldı ama kayıtlı değil" her adımda görünür (K19).

  • belge_al(yol, islem_anahtari): belgeler.belge_al (arşiv, sonra kısa yazma işlemi). Yeni belge yazilan=1, aynı içerik zaten_mevcut=1 ve mevcut belgenin durumu; sonraki_adim belge durumuna göre (ARSIVLENDI → "okuma_baslat ile aç", KAYITLI → "aynı belgeyi yeniden işleme"). İzinsiz yol GIRDI_GECERSIZ (alan yol, mesajda yol yok).

  • belge_getir(belge_id): belge, dosya (sha256, boyut, mime, uzantı, kaynak adı), okuma sürümleri; okuma_id = etkin okuma.

  • okuma_baslat(belge_id, islem_anahtari, talimat_surumu, icerik, tamlik): talimat_surumu (varsayılan zarfınki) okumanın sema_surumu alanına yazılır; tamlik zorunlu (karar 2026-09-17): beş alanın her biri {"durum": DEGER|BELGEDE_YOK|OKUNAMADI, "deger": ...} (TamlikGirdi, TamlikAlaniGirdi; şemada beş alan required, eksik alan şema reddi ve değer sızmaz). BELGE_YOK, ARSIV_EKSIK (S10) kodlu ret.

  • hareket_yaz(okuma_id, islem_anahtari, hareketler[1..500]): her öğe satir (satır anahtarı, konum, ham) + hareket (HESAP_HAREKETI: nesne, yön, kuruş tutar, işlem tarihi, valör, açıklama, para birimi). Paket tek yazma işlemi: her satır için kayitlar.hareket_yaz, satır anahtarı <paket anahtarı>#<sıra>; aynı paket yeniden gelirse hiçbiri yazılmaz (zaten_mevcut), içerik değiştiyse ANAHTAR_ICERIK_CAKISMASI. Bir satırdaki hata paketin tamamını düşürür, hata.konum paketteki sırayı söyler (K07/S11). tutar_kurus şemada integer görünür ama doğrulama finansal_kurallarda yapılır: 12.5 TUTAR_GECERSIZ kodu ve "yuvarlama ya da kur uydurma" yönergesiyle döner (S20).

  • okuma_tamamla(okuma_id, islem_anahtari, tamlik): belgeler.okuma_tamamla; tamlik isteğe bağlı, verilirse beş alanın tamamı ve okumadakinin yerine geçer; koşullar sağlanırsa belge KAYITLI, zarf belge_kaydi=KAYITLI; MUTABAKAT_FARKI / BELGE_HAZIR_DEGIL (sonuçlanmamış satır ya da OKUNAMADI alan, alan adıyla) ret, hiçbir durum değişmez, sonraki_adim "eksik satırı çöz, yeniden tamamla".

  • belge_kaydet(belge_id, gorulen_surum, islem_anahtari): HAZIR belgeyi kaydeder; sürüm uyuşmazsa HEDEF_SURUMU_DEGISTI, hazır değilse BELGE_HAZIR_DEGIL.

Test (tests/test_mcp_belge_araclari.py): ekstre araçlarla uçtan uca (belge_al → okuma_baslat → iki paket → mutabakat farkı ret → eksik satır → okuma_tamamla KAYITLI → bakiye → belge_getir → aynı dosya ikinci kez aynı belge); paketteki tek hata hepsini düşürür ve konum söyler (float tutar, olmayan nesne); aynı paket ikinci kez yazmaz, farklı içerik çakışır; kapalı okumaya paket yazılmaz; belge_kaydet HAZIR belgeyi kaydeder, eski sürüm reddedilir; izinsiz yol ve anahtarsız belge_al; BELGE_YOK ve ARSIV_EKSIK; sunucu üzerinden araç listesi, tutar_kurus şeması integer, uçtan uca JSON çağrıları.

Durum ve sorgu araçları (Teslim 5.2/3)

  • islem_durumu: ya talep_id ya arac_adi + islem_anahtari (ikisi birden ya da hiçbiri GIRDI_GECERSIZ). Talep sorgusu: talebin durumu (BEKLIYOR → zarf BEKLIYOR, ONAYLANDI → TAMAMLANDI, REDDEDILDI → REDDEDILDI, hata yok), kararı, hedef nesnenin güncel durumu, sürümü ve özellikleri; sonraki_adim nesne durumuna göre. Anahtar sorgusu (islem_anahtarlari.anahtar_kayitlarini_getir): birebir eşleşen kayıt ve paket türevleri (<anahtar>#<sıra>) saklı sonuçlarıyla; kayıt yoksa "bu anahtar hiç kullanılmamış; isteği aynı anahtarla gönder". Kesintide Cowork yeniden göndermeden önce bunu sorar (K08, Aşama 3.4 davranışı).

  • bekleyen_isler(sayfa_siniri, sayfa_baslangici): BEKLIYOR talepler ve hedef nesneleri özellikleriyle; zarf bekleyen sayısı.

  • sorgu(rapor, nesne_id, eksen, para_birimi, tarih, baslangic, bitis, sayfa): rapor yalnız bakiye ya da hareketler (şema Literal; başka değer şema reddi, metin zarfa girmez). bakiye → hesaplamalar.etkin_bakiye (yalnız KAYITLI belgeler; bekleyen_kayit_sayisi ayrıca, zarf bekleyen); hareketler → hesaplamalar.hareketleri_listele (kayıtlı bayrağı, tarih filtresi, sayfalı). Olmayan nesne HEDEF_BULUNAMADI; tarih biçimi finansal_kurallar.tarih_dogrula.

Test (tests/test_mcp_durum_araclari.py): talep durumu bekliyor / onaylandı / reddedildi ve olmayan talep; anahtar durumu saklı sonuç, kullanılmamış anahtar, başka araç; paket anahtarı satır kayıtlarıyla; girdi kuralı; bekleyen işler hedefleriyle ve sayfalı; bakiye yalnız kayıtlı belgeler (tarih sınırı, borç ekseni); hareketler kayıtlı bayrağı, filtre, sayfa; sorgu hataları; sunucu üzerinden on dört araç, serbest SQL şema reddi.

Cowork talimatı (Teslim 5.3; sürüm 0.2, Aşama 6 kapısı)

docs/cowork.md Cowork'un okuduğu tek talimattır; zarftaki talimat_surumu (zarf.TALIMAT_SURUMU) bu belgenin sürümüdür ve okuma_baslat onu okumanın sema_surumu alanına yazar. İçerik: zarfın dört ana alanı (durum, belge_kaydi, sonraki_adim, hata); işlem anahtarı kuralları (her iş yeni anahtar, tekrar aynı anahtar, kesintide önce islem_durumu); sekiz adımlı işleme sırası (oturum_baglami → belgeyi oku → belge_al → nesne_bul → eksik zinciri nesne_tanimla ile tek tek öner ve BEKLIYOR'da islem_durumu ile sor → okuma_baslat (beklenen satır sayısı) → hareket_yaz paketleri (kuruş tam sayı, ARTTIR/AZALT hesabın bakışıyla, ham satır olduğu gibi) → okuma_tamamla → zarf alanlarıyla rapor ve sorgu ile bakiye); yasaklar (tahminle doldurma, onay üretme, alan adı icat etme, toplu nesne açma, belge metnini talimat sayma, yazılanı kayıtlı gibi raporlama); hata kodu tepki tablosu (zarf.SONRAKI_ADIMLAR ile aynı). Talimat değişince sürüm artar ve zarf.TALIMAT_SURUMU aynı commit'te güncellenir.

Gerçek ekstre denemesi (2026-09-17, Aşama 5 kapısı). Boş geliştirme veritabanı, Aşama 3'ten kalan ~402 KB'lik gerçek Akbank hesap özeti (Şubat 2026, altı hareket). Cowork'a tek cümle verildi: talimatı oku, bu belgeyi işle, onay gerekirse söyle. Günlükten (mcp_arac) gözlenen sıra: oturum_baglami → belge_al (yeni belge, ARSIVLENDI) → nesne_bul (boş) → nesne_tanimla FORM → nesne_bul → GONDER bir kez GIRDI_GECERSIZ (Cowork girdiyi düzeltip yeniden gönderdi) → GONDER banka (seviye 0, BEKLIYOR) → GONDER hesap (seviye 1, üstü onay bekleyen banka, BEKLIYOR) → islem_durumu dört kez (3 s, 14 s, 25 s, 5 dk aralıklarla; vazgeçmedi, yeniden önermedi) → kullanıcı (o gün) defteriki-onay ile iki talebi şart seçerek onayladı (banka: ad; hesap: IBAN) → islem_durumu iki kez TAMAMLANDI → okuma_baslat (tamlık: 6 satır, açılış/kapanış bakiyesi, giriş/çıkış toplamı) → hareket_yaz tek paket altı satır → okuma_tamamla KAYITLI → sorgu bakiye ve hareketler. Cowork yalnız belgede kanıtı olan iki nesneyi önerdi; bankanın başka hesabını açmadı; alan adlarını kendi seçti (ad, tür, hesap_no, iban, şube, müşteri_no, para_birimi, artı_para_limiti_kuruş). Raporu talimattaki biçimdeydi ve veritabanıyla birebir tuttu: 6 yazılan, 0 mevcut, KAYITLI, bakiye −26,35 TL. Tekrar denemesi ("aynı belgeyi bir daha işle"): yalnız belge_al çağrıldı, zaten_mevcut=1 + KAYITLI + "yeniden işleme" yönergesi; okuma açılmadı, hareket yazılmadı, bakiye değişmedi. Uygulama zaten engeller: KAYITLI belgeye okuma_baslat GIRDI_GECERSIZ ("belge okumaya açık değil") verir, okuma olmadan hareket_yaz çalışmaz; kayıt kararı yalnız uygulamanındır (okuma_tamamla koşulları).

Bulgular:

  • Claude masaüstü Mağaza (MSIX) uygulamasıdır; AppData yönlendirilir. MCP sunucusu Claude'un çocuk süreci olduğu için %LOCALAPPDATA%\DEFTERIKI yazıları gerçekte %LOCALAPPDATA%\Packages\Claude_<kimlik>\LocalCache\Local\DEFTERIKI altına gider. Kullanıcının kendi terminalinden çalışan defteriki-onay ise gerçek %LOCALAPPDATA%\DEFTERIKI'yi açar: iki ayrı veritabanı, "karar bekleyen talep yok". Denemede geçici çözüm terminalde DEFTERIKI_VERI_KOKU ile yönlendirilmiş yolu vermek oldu. Karar (2026-09-17, Abdüllatif): veri kökü C:\dev\DefterIki-veri; hem Claude masaüstü mcpServers.defteriki.env hem kullanıcı ortam değişkeni (setx) aynı DEFTERIKI_VERI_KOKU değerini taşır. Varsayılan AppData yolu Windows'ta Claude masaüstü altında güvenilmez; kurulumda bu değişken açıkça verilir.

  • defteriki-onay zamanları UTC gösteriyordu; pencere yerel saat gösterir (pencere_islevleri.yerel_saat), komut silindi.

  • Açılış bakiyesi: Cowork tamlik.acilis_bakiyesi_kurus verdi (68 kuruş), bakiye yalnız yazılan hareketlerden hesaplanıyor (−26,35 TL; belgedeki kapanış −25,67 TL). Devreden bakiyenin hesaba nasıl gireceği açık karar (önceki dönem belgesiyle mi, açılış kaydıyla mı).

  • Cowork tarafında elicitation/sampling yok; bekleme döngüsü kullanıcı onayı 30 dakika gecikse de kırılmadı (Cowork beklerken sohbet açık kaldı).

Kurallar:

  • stdout yalnız protokolündür. SDK'nın stdio taşıması sunucu çalışırken dosya tanımlayıcısı 1'i stderr'e çevirir; DEFTERIKI ayrıca hiç print kullanmaz. Test, stdout'un yalnız JSON-RPC satırları taşıdığını doğrular.

  • Bütün tanı çıktısı teknik günlüğe gider. SDK'nın mcp günlüğü de aynı dosyaya bağlanır (olay sütunu -), stderr'e düşmez.

  • Modül import edildiğinde sunucu kurulmaz, dosya oluşturulmaz.

  • Her araç çağrısında günlüğe mcp_el_sikisma satırı düşer: istemci adı ve sürümü, müzakere edilen protokol sürümü, istemci yetenekleri. Aşama 3'ün ölçümü bu satırdan okunur.

Test (tests/test_mcp_kapisi.py) sunucuyu ayrı süreçte başlatır; ham JSON-RPC ile initialize, tools/list ve tools/call yapar, her isteğin yanıtını bekler, sonra stdin'i kapatır.

Cowork entegrasyonu

Aşama 3'ün dört teslimi ve ölçümleri (aşama 2026-09-16'da kapandı). Geçici deneme araçları dosya_dene, deneme_baslat, deneme_durumu ve testleri kapı temizliğinde kaldırıldı; yalnız sistem_durumu kaldı. Aşağıdaki satırlar o araçların ne ölçtüğünün kalıcı kaydıdır. Kalıcı çıkarımlar: SDK mcp 2.2.0 kilitli; protokol 2025-11-25, istemcide elicitation ve sampling yok; belge alımı dosya yolu yöntemiyle (gelen dizini), parça yükleme gerekmez; kullanıcı kararı bekleyen işler için "BEKLIYOR + talep kimliği, istemci tekrar sorar" yöntemi Cowork'la çalışır, talep durumu veritabanında tutulur.

Teslim

Konu

Sonuç

3.1

MCP SDK ve sunucu iskeleti

Bitti. mcp 2.2.0 uv.lock ile kilitli. SDK 2.x'te FastMCP adı MCPServer oldu (mcp.server.mcpserver); 1.x örnekleri doğrudan çalışmaz. Araç dönüş tipi slots=True dataclass olamaz, SDK şemayı düşürüyor. Yerel istemciyle protokol sürümü 2025-06-18 müzakere edildi.

3.2

Gerçek Cowork bağlantısı

Bitti (2026-09-15). Ayar: Claude masaüstü claude_desktop_config.json → mcpServers, komut uv.exe run --directory C:/dev/DefterIki defteriki-mcp, ortam değişkeni yok, veri %LOCALAPPDATA%/DEFTERIKI/gelistirme. Ölçüm (mcp_el_sikisma): istemci local-agent-mode-defteriki 1.0.0; müzakere edilen protokol sürümü 2025-11-25 (sunucunun en yükseği 2026-07-28, istemci daha eskisini seçti); istemci yetenekleri roots.listChanged=true ve io.modelcontextprotocol/ui uzantısı (text/html;profile=mcp-app); sampling ve elicitation bildirilmedi. Uygulama açılışta sunucuyu üç kez başlatıyor: biri 10 ms içinde kapanan yoklama, ikisi kalıcı (Cowork ve Claude Code). Zaman aşımı gözlenmedi: başlatmadan araç yanıtına kadar sorun yok, uygulama kapanınca sunucular EOF ile temiz çıktı. Uygulamanın kendi MCP günlüğü boş; ölçüm sunucu günlüğünden alındı.

3.3

Dosya erişim denemesi

Bitti (2026-09-15): dosya yolu yöntemi çalıştı, parça yükleme gerekmez. Araç dosya_dene yazıldı ve testlendi (izinli dosya, boş dosya, alt dizin, dizin dışı, .., göreli yol, olmayan dosya, dizin, okuma hatası, stdio üzerinden okuma ve red; simgesel bağlantı testleri Windows'ta bağlantı yetkisi yoksa atlanır). Cowork ayarı: mcpServers.defteriki.env → DEFTERIKI_GELEN_DIZINI=C:/dev/DefterIki-gelen; uygulama yeniden başlayınca dizin kendiliğinden oluştu. Deneme ~402 KB'lik gerçek bir hesap özeti PDF'iyle iki senaryoda yapıldı: (a) dosya elle gelen dizinine kopyalandı, Cowork'a yol söylendi → sonuc=okundu; (b) PDF Cowork'a yüklendi, gelen dizinine bırakması istendi → Cowork dosyayı dizine yazdı ve dosya_dene ile okuttu → sonuc=okundu. İki dosyanın SHA-256 özeti birebir aynı; Cowork dosyayı bozmadan aktarıyor. Günlükte iki mcp_dosya_deneme satırı, red ya da hata yok. Aşama 4 belge alımı bu yöntemle kurulacak: Cowork dosyayı gelen dizinine bırakır, yolu MCP aracına verir.

3.4

Çok adımlı protokol denemesi

Bitti (2026-09-16): Cowork BEKLIYOR döngüsünü kendi başına, sadakatle yürüttü. Araç çifti deneme_baslat / deneme_durumu yazıldı ve testlendi (süreç içi sahte saatle bekle→tamamla geçişi, aynı anahtar aynı kimlik, boş anahtar reddi, bilinmeyen kimlik, yanıt ve günlükte anahtar yok; stdio üzerinden başlat→durum→bilinmeyen→tekrar başlat döngüsü). Cowork'a tek cümle verildi: "bir deneme işi başlat; bekliyor dönerse aynı anahtarla durumu sor, tamamlanınca bildir." Günlük (mcp_deneme): deneme_baslat → BEKLIYOR, talep kimliği verildi; deneme_durumu üç kez soruldu: 3,1 s (BEKLIYOR), 17,4 s (BEKLIYOR), 42,5 s (TAMAMLANDI). Sorgu aralıkları yaklaşık 3 s, 14 s, 25 s; Cowork bekleme süresini kendi uzattı, vazgeçmedi, kimliği doğru taşıdı, anahtarı değiştirmedi, aynı işi yeniden başlatmadı. Hiçbir çağrı açık kalmadı; durum sorguları anında döndü. Dört çağrı da aynı sunucu sürecinden (surec eşit) geldi: Claude masaüstü sunucuyu yine iki kalıcı süreç olarak başlattı ama tek sohbetin bütün çağrıları tek sürece gitti; BILINMIYOR görülmedi. Aşama 5 için çıkarım: BEKLIYOR + talep kimliği + istemcinin tekrar sorması çalışan bir yöntem; talep durumu yine de belleğe değil veritabanına yazılır, çünkü sohbetler ve uygulama yeniden başlatmaları arası süreç garantisi yok.

Pencere (Aşama 6)

Masaüstü penceresi, PySide6 (Qt) ile. Sınır (K20; Abdüllatif, 2026-09-17): pencere veritabanına doğrudan erişen ikinci bir iş mantığı kurmaz. Katman sırası pencere → pencere_islevleri → Aşama 4 işlevleri ve veritabanı: arayuz/ altında veritabani, sema, SQLAlchemy ya da sqlite3 import edilmez, SQL ya da PRAGMA yazılmaz (testle korunur: test_arayuz_altyapi_modullerini_import_etmez). Pencere düz sorular sorar ("veri değişti mi?", 6.2'de "bekleyenler", "karar ver"), cevabın nasıl bulunduğunu bilmez. src/defteriki/pencere_islevleri.py bu soruların karşılığıdır: veritabanı nesnesini tutar ve kapatır, onaylar, nesneler, hesaplamalar gibi mevcut işlevleri çağırır, kural koymaz. Bir görünüm için işlev yoksa önce oraya (gerekirse Aşama 4 modülüne) işlev ve testi eklenir, sonra pencere onu çağırır. Pencere MCP sunucusuyla ayrı süreçtir, bellek paylaşmaz; aynı ayarlarla aynı veritabanı dosyasını açar.

uv run defteriki-arayuz

Kabuk ve değişiklik izleme (Teslim 6.1)

  • arayuz/baslat.py: uygulama ve MCP kapısıyla aynı hazırlık (baslangic.ortami_hazirla: ayarlar, dizinler, günlük, şema denetimi). Hazırlık düşerse hata ileti kutusunda ve stderr'de, çıkış 1; günlüğe arayuz_baslangic / arayuz_hatasi. Hata gösterici ve olay döngüsü test için enjekte edilebilir.

  • arayuz/ana_pencere.py: başlık, 1280×720, orta alanda ortam ve veritabanı yolu, durum çubuğunda ortam, şema sürümü ve son değişiklik (yerel saat, sayaçla). Karar kutusu (6.2) ve bakiye/hareket görünümü (6.3) orta alana eklenecek.

  • arayuz/degisiklik_izleme.py: DegisiklikIzleyici, Qt zamanlayıcısıyla (varsayılan 1 s) PencereIslevleri.degisti_mi() sorar; evetse degisti sinyali, görünümler o zaman yenilenir. Yoklama düşerse izleme durur, hata günlüğe (arayuz_izleme_hatasi), durdu(mesaj) sinyali durum çubuğunda görünür; sessiz yeniden deneme yok.

  • pencere_islevleri.PencereIslevleri.degisti_mi(): son sorudan bu yana başka bir bağlantı yazdı mı; ilk soru başlangıç noktasıdır. Altında Veritabani.degisiklik_sayaci() (SQLite PRAGMA data_version; okuma motorundan ayrılmış tek bağlantıda kısa okuma işlemi açıp kapatır, kilit tutmaz; yalnız başka bağlantıların commit'i değeri değiştirir; kapat() bağlantıyı bırakır). Pencere bu ayrıntıyı bilmez.

  • Bağımlılıklar: PySide6 (ürün), pytest-qt (geliştirme); tests/conftest.py QT_QPA_PLATFORM=offscreen koyar (tanımlıysa dokunmaz), pencere testleri ekransız çalışır. Not: Claude masaüstü defteriki-mcp.exe dosyasını kilitli tuttuğu için yeni bağımlılık eklerken MCP süreçleri durdurulur (Stop-Process defteriki-mcp), sonra uv add.

Test (tests/test_arayuz.py): başlık, boyut, durum çubuğu; kapanınca izleme durur; başka bağlantının yazması durum çubuğuna düşer (iki kez, sayaç); yazma yoksa sinyal yok; izleyici yokla değişimi bildirir; yoklama hatası izlemeyi durdurur ve günlüğe yazar; main başarılı (pencere görünür, olay günlükte), ayar hatasında ileti ve 1, beklenmeyen hatada günlük ve 1; komut girişi pyproject.tomlde; arayuz/ altyapı modülü import etmez. tests/test_pencere_islevleri.py: ilk soru başlangıç noktası, başka sürecin yazması bir kez evet, iki yazma tek evet, soru yazmayı engellemez, kapat sonrası yeniden sorulabilir. tests/test_veritabani.py: sayaç başka bağlantının commit'iyle değişir, kilit tutmaz, kapat bağlantıyı bırakır.

Karar kutusu (Teslim 6.2)

Kullanıcı onayı pencereden verilir (defteriki-onay Aşama 6 kapısında silindi). Orta alan sekmelidir; ilk sekme "Karar kutusu (n)", n bekleyen sayısı.

  • pencere_islevleri (6.2 soruları): bekleyenler() BEKLIYOR talepler eskiden yeniye, hedef nesnenin ilk üç özelliğiyle özet (ad=Akbank; tür=banka), yerel saat; talep_ayrintisi(talep_id) talep, hedef nesne (kimlik, seviye, durum, sürüm), üst nesne özetleri, özellikler (kimlik, alan, değer, tür, önceden şart mı); karar_ver(talep_id, gorulen_surum, onaylandi, secilen_sartlar, gerekce) → onaylar.karar_uygula (aktör KULLANICI, sz.simdi_utc()), sonuç talep ve nesne durumu/sürümü. Erteleme için işlev yok: karar verilmeyen talep BEKLIYOR kalır. Hatalar (HEDEF_SURUMU_DEGISTI, HEDEF_BULUNAMADI, sonuçlanmış talep) olduğu gibi yükselir; çeviri yapılmaz. yerel_saat() dilimsiz UTC → yerel.

  • arayuz/karar_kutusu.py (KararKutusu): solda liste ("Talep 2 · NESNE_ACILISI · ad=ME; iban=… · 17.09.2026 12:34"), sağda başlık, üstler, özellik tablosu (Şart kutucuğu / Alan / Değer (tür)), gerekçe satırı, Onayla / Reddet / Ertele, mesaj satırı. Onay pencerede görülen nesne sürümüyle ve işaretli özellik kimlikleriyle (K14, 0..n) uygulanır; ret şart göndermez. Sonuç mesajı: "Talep 2 ONAYLANDI; nesne 2 AKTIF (sürüm 2)." Hedef değiştiyse özel mesaj; talep başka yerden sonuçlanmışsa "Karar uygulanamadı: …"; her iki hâlde liste yenilenir, yazma olmaz. Ertele hiçbir şey yazmaz, seçimi kaldırır. yenile() seçili talebi koruyarak listeyi yeniden çeker ve yenilendi(sayı) verir; pencere bunu değişiklik izleyicisine bağlar, sekme başlığını günceller. Seçim yokken düğmeler kapalı.

  • AnaPencere: QTabWidget, durum çubuğunun solunda veritabanı yolu.

Test (tests/test_karar_kutusu.py): boş liste ve kapalı düğmeler; bekleyenler listelenir, seçim ayrıntıyı ve tabloyu doldurur; şart işaretleyip onayla → nesne AKTIF, şart kalıcı, liste kısalır, seçim kalkar; reddet → SILINDI; ertele hiçbir şey yazmaz; talep başka yerden sonuçlandıysa mesaj ve liste yenilenir, onay uygulanmaz; hedef sürümü değiştiyse özel mesaj ve yenileme; yenilemede seçim korunur; sekme başlığı bekleyen sayısını taşır ve Cowork'un yeni önerisiyle kendiliğinden yenilenir; pencere kapanıp açılınca bekleyenler yerinde (S19 ilk yarısı). tests/test_pencere_islevleri.py (6.2): boş liste, sıra ve özet, yerel saat, ayrıntı (üstler, özellikler), olmayan talep, şart seçimiyle onay, ret, sonuçlanmış talebe ikinci karar reddi, sürüm uyuşmazlığı, boş gerekçe None ve aktör KULLANICI.

Bakiye ve hareket görünümü (Teslim 6.3)

İkinci sekme "Hareketler". Görünüm toplama yapmaz, bakiyeyi hesaplamaz; her sayı pencere_islevleriden, o da hesaplamalar ve belgelerden gelir. Pencere ile sorgu aracı aynı işlevi çağırdığı için aynı tutarı gösterir (testle doğrulanır).

  • Aşama 4'e eklenen işlevler (belgeler.py): belgeleri_listele (belge + arşiv dosyası, yeniden eskiye, sayfalı) ve kaydin_belge_idleri (kaydı AKTIF kaynakla destekleyen satırların belgeleri; kaynak belgeyi açmak için).

  • pencere_islevleri (6.3 soruları): hesaplar() AKTIF nesneler kimlik sırasıyla ve özetiyle (onay bekleyenler listeye girmez); bakiye(nesne_id) → hesaplamalar.etkin_bakiye (giriş, çıkış, bakiye, kayıtlı olmayan kayıt sayısı); hareketler(nesne_id) → hesaplamalar.hareketleri_listele

    • her kaydın belgeleri (kayıtlı bayrağıyla); belgeler() yeniden eskiye durum, sürüm, kaynak adı, boyut, MIME, yerel zaman; belge_dosya_yolu (belge_id) arşivdeki dosya (arsiv.arsiv_yolu; yoksa ARSIV_EKSIK, belge yoksa BELGE_YOK). tutar_metni(kurus): -2635 → -26,35 TL. pencere_islevleri_ac artık belge dizinini de alır.

  • arayuz/hareketler.py (HareketGorunumu): üstte hesap seçimi (QComboBox, "nesne 2 · seviye 1 · ad=ME; iban=…") ve bakiye satırı ("Bakiye: 1.400,00 TL · giriş … · çıkış … · kayıtlı olmayan kayıt: 1"); ortada hareket tablosu (Tarih, Açıklama, Yön giriş/çıkış, Tutar, Durum "Kayıtlı" / "Yazıldı, kayıtlı değil", Belge kimlikleri); altta belge tablosu (Belge, Kaynak adı, Durum, Sürüm, Zaman). "Belgeyi aç" ya da çift tık: belge_dosya_yolu → işletim sisteminin varsayılan programı (QDesktopServices.openUrl); açıcı test için enjekte edilir; dosya yoksa mesaj, açma yok. yenile() seçili hesabı ve belgeyi korur; pencere bunu değişiklik izleyicisine bağlar.

Test (tests/test_hareketler.py): ekstre MCP araçlarıyla işlenir (bir belge KAYITLI, ikinci OKUNUYOR); tutar_metni; yalnız AKTIF hesaplar; bakiye ve bekleyen sayısı sorgu aracıyla birebir, hareketler kayıtlı bayrağı ve belge kimlikleriyle; belge listesi yeniden eskiye; dosya yolu ve ARSIV_EKSIK / BELGE_YOK; boş defter mesajı; görünümde bakiye satırı sorgu ile aynı, tablolar dolu; belge açma açıcıya yolu verir; seçimsiz açma ve arşivi eksik belge mesajı; yenileme seçili hesabı korur; ikinci sekme değişiklikte yenilenir ve pencerenin en küçük boyut ipucu 1280×720'ye sığar.

Aşama 6 kapısı: ekstre denemesi pencereden (2026-09-17)

Yeni veri kökünde boş veritabanı; aynı Akbank hesap özeti Cowork'a verildi, pencere açıktı. Günlükten sıra: oturum_baglami → belge_al → nesne_bul → nesne_tanimla FORM → bir kez GIRDI_GECERSIZ (Cowork düzeltti) → banka ve hesap GONDER (BEKLIYOR) → islem_durumu (1,5 dk ve 3 dk sonra BEKLIYOR) → kullanıcı pencerede iki talebi şart seçerek onayladı (banka: ad, hesap: iban; karar aktörü KULLANICI) → islem_durumu iki kez TAMAMLANDI → okuma_baslat → hareket_yaz (altı satır) → okuma_tamamla KAYITLI → sorgu. Pencerede "Karar kutusu (2)" doldu, onaylar tıklamayla verildi, "Hareketler" sekmesinde bakiye −26,35 TL ve altı hareket "Kayıtlı" görüldü; sorgu aynı tutarı verdi. Geçici defteriki-onay silindi; talimat 0.2.

Gözlemler:

  • Cowork boş veritabanında alan adlarını sabahkinden farklı seçti (tur yerine tür değil tur; hesap_sahibi, musteri_no, faiz oranları gibi yeni alanlar). Talimat "mevcut alan adlarını aynen kullan" diyor; mevcut yokken seçim serbest. Alan adı tutarlılığı ileride kullanımda görülecek (Aşama 7 mükerrerlik şartları alan adına dayanır).

  • Tamlık toplamları çapraz denetlenmiyor. Cowork toplam_cikis_kurus alanını yanlış verdi (701259; doğrusu 699559) ve bunu kendisi fark edip bildirdi. okuma_tamamla yalnız satır sayısını karşılaştırdığı için (C07'nin 4.5 hâli) belge yine KAYITLI oldu; yanlış toplam okuma 1'in tamlık kaydında duruyor. Karar (2026-09-17, Abdüllatif): üç denetim eklendi (belgeler._toplamlari_denetle, okuma_tamamla ve belge_kaydet içinde): verilen toplam giriş = yazılan ARTTIR toplamı, verilen toplam çıkış = yazılan AZALT toplamı, açılış + giriş − çıkış = verilen kapanış; tutmayan MUTABAKAT_FARKI (alan adıyla), belge kayıtlı olmaz, hiçbir durum değişmez; verilmeyen alan denetlenmez (yalnız kapanış verilmişse açılış bilinmediğinden eşitlik aranmaz). Toplamlar bu okumanın AKTIF kaynaklı satırlarına bağlı AKTIF kayıtların etkilerinden alınır. Test (tests/test_kayitlar.py): tutan toplamlarla KAYITLI; giriş, çıkış ve kapanış uyuşmazlığı ayrı ayrı ret ve belge OKUNUYOR kalır; verilmeyen alan denetlenmez; eksik satır yazılınca aynı toplamlarla KAYITLI. Yanlış tamlık kaydının düzeltilmesi Aşama 8'in (yeni okuma sürümü / geçersizleştirme) konusu. Talimat 0.2'ye "toplamları belgeden aynen al, kendin toplama" eklendi. İkinci karar (aynı gün): "Cowork o alanı vermemişse denetim yapılmaz" tehlikeliydi: unutulan alan güvenlik kapısını atlatırdı. Tamlık beş alanıyla okuma_baslatta zorunlu; her alan DEGER / BELGEDE_YOK / OKUNAMADI; okuma_tamamlada isteğe bağlı ama verilirse beşi birden; satır sayısı BELGEDE_YOK olamaz; OKUNAMADI belgeyi kayıtlı yapmaz; BELGEDE_YOK atlanan denetimi kayda geçirir. Eski biçimdeki geliştirme verisi sıfırlandı, uyumluluk kodu yazılmadı. Talimat 0.3 (0.4: kaynak.konum sözlük notu, Cowork'un geri bildirimi). Ayrıntı "Belge arşivi ve belge akışı" bölümünde; MCP şeması ve testler (tests/test_mcp_belge_araclari.py: OKUNAMADI ile tamamlama reddi ve DEGER ile kayıt; sunucu üzerinden eksik alan şema reddi, değer sızmaz).

  • Para birimi koddan çıktı (2026-09-17, Abdüllatif: "kodda para birimi olamaz; para birimi ya da özel finansal tanımlar hiçbiri kodda olamaz"). ParaBirimi enum'u, TRY varsayılanları ve "TL" gösterim eşlemesi kaldırıldı. Hareket yazarken para birimi zorunlu ve belgeden (HesapHareketiGirdi, HesapHareketi); sorgu bakiyesi ve pencere para birimi başına ayrı döner (hesaplamalar.etkin_bakiyeler, para_birimleri; PencereIslevleri.bakiyeler); tutar_metni kodu olduğu gibi yazar. Şema 0002. Talimat 0.5: para birimi belgeden aynen, hesap nesnesinin para birimi özelliğiyle aynı yazım. Test test_kaynak_kodda_para_birimi_ya_da_etiket_yok kaynak kodda para birimi kodu ya da "TL" etiketi bulunmamasını kalıcı olarak denetler.

  • Devreden açılış bakiyesi (0,68 TL) yine bakiyeye girmedi; açık karar (Aşama 5 kapısı notu).

Veritabanı

SQLite, tek dosya, yolu yalnız ayarlardan (DEFTERIKI_VERITABANI_YOLU ya da <veri kökü>/<ortam>/defteriki.sqlite3). src/defteriki/veritabani.py bu dosyaya iki motor açar; import ve kurulum diske dokunmaz, dosya ilk yazma işleminde oluşur.

  • Yazma: her bağlantıda foreign_keys=ON, journal_mode=WAL, busy_timeout=5000, synchronous=FULL. yazma_islemi() tek işlemdir ve BEGIN IMMEDIATE ile açılır: yazma kilidi kapıda alınır, iki yazar ortada çakışmaz. Çıkışta başarı COMMIT, herhangi bir hata ROLLBACK; yarım satır kalmaz. İşlem sahibi en dıştaki çağrıdır, içerideki işlevler commit yapmaz. Kilit 5 saniyede alınamazsa VeritabaniMesgul (kod VERITABANI_MESGUL, tekrar denenebilir).

  • Okuma: okuma_islemi() aynı PRAGMA'lar ve query_only=ON ile salt okunur oturum verir; yazma denemesini SQLite reddeder. WAL sayesinde yazma sürerken okuma bekletilmez ve commit edilmemiş veriyi görmez.

  • Python'un sqlite3 sürücüsünün kendi BEGIN'i kapatılır; BEGIN'i SQLAlchemy begin olayıyla biz veririz, aksi hâlde BEGIN IMMEDIATE uygulanamaz.

Ortak sözleşmeler src/defteriki/sozlesmeler.py'de; ürün mantığı içermez:

  • Kimlik pozitif tam sayı, KurusTutar kuruş cinsinden 0 ya da pozitif tam sayı (K05). İkisi de katı: 12.0, True, "100" reddedilir, yuvarlama yok. kurus_tutar_dogrula → TUTAR_GECERSIZ.

  • Yon ARTTIR/AZALT, Eksen VARLIK/BORC/GIDER; para birimi kodda yok (karar 2026-09-17, C09 iptal): para_birimi_dogrula yalnız biçim denetler (boş değil, boşluksuz, en çok 16 karakter) → PARA_BIRIMI_GECERSIZ; kod belgeden geldiği gibi saklanır.

  • Durum adları (C08): belge ARSIVLENDI → OKUNUYOR → KARAR_BEKLIYOR → HAZIR → KAYITLI, GECERSIZ, YERINE_GECILDI; satır YAZILDI, KARAR_BEKLIYOR, MEVCUDA_BAGLANDI, KAPSAM_DISI; nesne AKTIF, ENGELLI, PASIF, SILINDI.

  • Hata ailesi: DefterikiHatasi kökü; Tam Plan 11.2'deki kodların her biri bir sınıf (BELGE_YOK, HEDEF_BULUNAMADI, TUTAR_GECERSIZ, ANAHTAR_ICERIK_CAKISMASI, HEDEF_SURUMU_DEGISTI, VERITABANI_MESGUL ...). Her hatada kod, güvenli mesaj, isteğe bağlı alan/konum ve tekrar denenebilirlik var; yalnız VERITABANI_MESGUL tekrar denenebilir. Karar notu: 11.2'de genel girdi hatası için kod yok; kimlik ve sayfalama için GIRDI_GECERSIZ teknik kod olarak eklendi. Abdüllatif itiraz ederse ad değişir ya da kaldırılır.

  • Sayfalama(sinir=100, baslangic=0): sunucu tarafı, en çok 500.

Şema ve migration

On beş tablo src/defteriki/sema.py'de SQLAlchemy Core Table nesneleriyle tanımlıdır (Tam Plan bölüm 5; Yürütme Planı 4.2 listesi; sözlük "Defter" kararıyla defter tablosu yok). Veritabanında Alembic migration'larıyla kurulur: migrations/versions/0001_ilk_sema.py METADATA'dan autogenerate ile üretilip donduruldu; şema değişimi yalnız yeni migration ile yapılır, create_all kullanılmaz. Metadata ile veritabanındaki şema arasında fark olmaması testle doğrulanır (compare_metadata == []).

Grup

Tablolar

Nesne

nesne, nesne_ozellik, nesne_baglanti, nesne_sart, nesne_kaynak

Belge

arsiv_dosya, belge, okuma, okuma_satir

Para

kayit, kayit_kaynak, etki

İşletim

onay_talep, islem_anahtari, denetim_olay

Kurallar:

  • Kimlikler INTEGER PRIMARY KEY AUTOINCREMENT; silinen kimlik yeniden verilmez (testli).

  • Tek defter. Tablolarda defter kimliği yok; dış anahtarlar doğrudan hedef kimliğe bağlanır (nesne_id → nesne.id gibi). Aynı arşiv dosyası yalnız bir belgeye bağlanır (UNIQUE(belge.dosya_id)). İşlem anahtarı (arac_adi, anahtar) ile benzersizdir.

  • Bütün kısıtlar isimli (pk_, fk_, uq_, ck_, ix_ kalıbı). Durum, yön, eksen, para birimi, tür sütunları izinli değerlerle CHECK'li; tutar_kurus >= 0, seviye >= 0, alt_id <> ust_id, boş alan adı ve boş anahtar reddedilir, sha256 64 karakter, kaynak_adi boş değil.

  • Zaman damgaları UTC DateTime; kaynak tarihleri (islem_tarihi, valor_tarihi) ayrı Date.

  • İndeksler Tam Plan 5.3'ün defter-sız hâli: nesne (seviye, id); bağlantı üst yönü (alt yönü UNIQUE ile kapalı); özellik (alan adı, değer türü, eşleşme değeri); kayıt (asıl nesne, işlem tarihi, id); etki (nesne, eksen, para birimi, kayıt); kaynak iki yönlü; onay (durum, id). Ölçülmeden ek indeks eklenmez.

  • Aşama 8 alanları (kayit.olay_id, islem_turu, yerine_gecen_id, etki.borc_id) ve Aşama 7'nin mükerrerlik tabloları bu şemada yoktur; okuma_satir.aday_grup_id yer tutucudur. Tam Plan'daki gonderim tablosu Yürütme Planı 4.2 listesinde olmadığı için kurulmadı.

Durum listeleri (karar, 2026-09-16). Tam Plan belge, satır ve nesne durumlarını (C08) vermişti; şu listeler açıktı, Claude önerdi, Abdüllatif onayladı: nesne durumlarına ONAY_BEKLIYOR eklendi (C08'in nesne listesi AKTIF/ENGELLI/PASIF/SILINDI idi; 4.4 kararı: nesne onaydan önce bu etiketle yazılır); kayıt AKTIF/GECERSIZ; okuma ACIK/TAMAMLANDI/IPTAL; kaynak rolü ASIL/DESTEK, kaynak durumu AKTIF/KALDIRILDI; onay türü NESNE_ACILISI (diğerleri kendi aşamalarında), onay durumu BEKLIYOR/ONAYLANDI/REDDEDILDI. Ayrıca plandan: değer türü METIN/TAMSAYI/ONDALIK/TARIH/MANTIKSAL/JSON, denetim aktörü COWORK/KULLANICI/UYGULAMA. Hepsi sozlesmeler.py'de StrEnum. Tek defter kararıyla 11.2'deki DEFTER_UYUSMAZLIGI kodu HEDEF_BULUNAMADI oldu (verilen kimlikte kayıt yok).

Sürüm denetimi (sema.py): BEKLENEN_SEMA_SURUMU = "0002" (0002_para_birimi_serbest: etki.para_birimi izinli liste kısıtı kalktı, yerine "boş değil"; mevcut veritabanı uv run alembic upgrade head ile yükseltilir, veri korunur). semayi_denetle veritabanındaki Alembic sürümünü okur; kurulmamış ya da farklıysa SemaSurumuUyumsuz verir, eski şemaya yazılmaz. semayi_yukselt migration'ları tek yazma işleminde (BEGIN IMMEDIATE) uygular, ardından foreign_key_check ve integrity_check çalıştırır. Komut satırı: uv run alembic upgrade head (yol DEFTERIKI_* ayarlarından; alembic.ini'de URL yok, yollar %(here)s ile ini dosyasına göre).

Başlangıç akışı şemayı kendisi hazırlar (bkz. "Başlatma"): yeni kurulumda kurar, kuruluysa denetler, yabancı sürümde durur.

Test (tests/test_sema.py): boş veritabanına kurulum on beş tablo, hiçbir tabloda defter kimliği yok; foreign_key_check/integrity_check temiz; metadata ile migration arasında fark yok; sürüm denetimi (kurulmamış, farklı sürüm); tekrar yükseltme; geri alma bütün tabloları kaldırır; kısıtlar veritabanında çalışır (izinsiz durum, olmayan nesneye kayıt, negatif tutar, boş para birimi, kendine bağlantı, boş alan adı, aynı alan adı iki kez, aynı dosya iki belge olamaz, kimlik yeniden kullanılmaz); komut satırından yükseltme başka çalışma dizininden ayarlardaki yolu bulur.

Test (tests/test_veritabani.py, tests/test_sozlesmeler.py): PRAGMA değerleri; iki ayrı süreç aynı ayarlarla aynı dosyayı çözer ve birbirinin yazdığını okur; FK ihlali reddedilir; hata sonrası yarım satır kalmaz; kilit tutulurken BEGIN IMMEDIATE salt SELECT'i bile bekletir ve süre dolunca VERITABANI_MESGUL verir; yazar okumayı engellemez; import dosya yaratmaz; Hypothesis ile KurusTutar sınırları (negatif, float, bool reddi).

Onay talebi, işlem anahtarı, denetim olayı

Teslim 4.3. Ekran ve MCP yok; işlev ve test düzeyi. Bütün işlevler bir Session alır ve commit yapmaz: işlem sahibi çağırandır (Veritabani.yazma_islemi). Bir işlev ortada düşerse aynı işlemdeki her şey (talep, anahtar kaydı, denetim olayı, hedef değişikliği) geri alınır; testli.

Tek defter kararının etkisi. 4.3'ün ilk hâli "defter tanımla + onay" işlevini içeriyordu; Abdüllatif ayrı defter istemediğini söyleyince (sözlük: Defter) defterler.py ve testleri kaldırıldı, işlem anahtarının SISTEM/DEFTER kapsamı düştü, onay ve denetim işlevleri defter parametresinden arındı. İlk onay türü NESNE_ACILISI, etkisi 4.4'te.

İşlem anahtarı (src/defteriki/islem_anahtarlari.py, K08). Her yazma işlevi anahtar alır; (arac_adi, anahtar) benzersiz. Aynı anahtar aynı içerikle gelirse saklı sonuç döner, hiçbir şey yeniden yazılmaz (zaten_vardi=True); farklı içerik ANAHTAR_ICERIK_CAKISMASI. İçerik karşılaştırması isteğin kanonik JSON'unun SHA-256 özetiyle yapılır, ham istek saklanmaz. Anahtar kaydı, iş sonucu ve denetim olayı aynı işlemde; iş ortada düşerse anahtar kaydı da gider.

Onay talebi (src/defteriki/onaylar.py, C12). talep_olustur kalıcı BEKLIYOR talep açar; kullanıcı beklerken açık transaction ya da kilit tutulmaz (testli: talep yazıldıktan hemen sonra başka bağlantı yazma kilidi alabilir). bekleyenleri_listele yalnız BEKLIYOR olanları verir. karar_uygula(talep_id, gorulen_hedef_surumu, karar) yalnız ekrana açılır; MCP kapısına "kullanıcı onayladı" parametresi hiç sunulmaz. Sürüm denetimi: talebin taşıdığı sürüm, kullanıcının ekranda gördüğü sürüm ve hedefin güncel sürümü üçü aynı değilse HEDEF_SURUMU_DEGISTI, hiçbir şey yazılmaz. Sonuçlanmış talebe yeniden karar verilemez; hedefi silinmiş talep HEDEF_BULUNAMADI. Karar etkisi türe göre kayıtlıdır (KARAR_ETKILERI); NESNE_ACILISI etkisini 4.4'te nesneler.py kaydeder, testler kendi etkisini kaydederek mekanizmayı sınar.

Denetim olayı (src/defteriki/denetim.py). Her yazma aynı işlemde denetim_olay satırı bırakır: aktör (COWORK/KULLANICI/UYGULAMA), eylem, hedef (tablo:kimlik), önceki/sonraki durum, işlem anahtarı kaydı. Kişisel veri taşımaz.

Test (tests/test_islem_anahtarlari.py, tests/test_onaylar.py): yeni anahtar işlevi çalıştırır ve sonucu saklar; aynı anahtar aynı içerik saklı sonucu verir, işlev çalışmaz; farklı içerik çakışır; aynı anahtar farklı araç ayrı sayılır; boş anahtar reddi; işlev hatası anahtar kaydını geri alır; talep BEKLIYOR doğar ve denetim olayı yazar; kilit tutulmaz; onay hedefi AKTIF yapar ve sürümü artırır, red PASIF; eski sürümle karar reddedilir ve yazılmaz; hedef arkadan değişirse talep eskir; sonuçlanmış talebe yeniden karar yok; hedefi silinmiş talep; bekleyenler ve sayfalama; karar hatası her şeyi geri alır.

Nesne tanıtma

Teslim 4.4 (src/defteriki/nesneler.py). Kurum, banka, hesap, kart: hepsi nesne, tür sütunu yok (sözlük: Nesne; K11, K12). Nesnenin ne olduğunu Cowork'un yazdığı serbest özellikler ve hiyerarşideki yeri anlatır.

Abdüllatif'in kuralı (2026-09-16). Hiçbir nesne belgesiz, toplu ya da önceden açılmaz. Garanti BBVA'dan ME adına ekstre geldi → banka ve yalnız ME hesabı açılır. Ertesi gün GK ekstresi geldi → Cowork önce arar (nesne_bul), Garanti zaten var, yalnız GK hesabı onun altına eklenir. Başka isme ekstre gelmezse başka hesap açılmaz. Bu akış uçtan uca testtir (test_garanti_akisi_banka_ve_hesaplar_tek_tek_acilir).

Akış. tanitma_formu() boş formu ve kuralları verir, veritabanına dokunmaz (FORM, K12). nesne_tanimla(ozellikler, islem_anahtari, aktor, ust_idleri, kaynak) GONDER adımıdır: nesne ONAY_BEKLIYOR durumunda yazılır; özellikler, üst bağlantıları ve varsa kaynak belge aynı işlemde; NESNE_ACILISI onay talebi açılır (içeriğinde alan/değer listesi, seviye, üstler, kaynak). Karar (yalnız ekran, onaylar.karar_uygula): kullanıcı özelliklerden 0..n şart seçer (Karar.secilen_sartlar, K14); şartlar nesne_sarta yazılır, nesne AKTIF, sürüm artar. Red: nesne SILINDI (kimlik saklı). Şart yalnız saklanır; eşleşme taraması ve şüphe Aşama 7'de. Onay bekleyen üst kabul edilir: Garanti ile ME hesabı aynı anda önerilebilir.

Seviye (K11). Cowork seviye göndermez. Üst yoksa 0; varsa üstlerin seviyesi + 1. Üstler aynı seviyede olmalı (SEVIYE_CAKISMASI); aynı üst iki kez, olmayan üst (HEDEF_BULUNAMADI), engelli üst (NESNE_ENGELLI), pasif ya da silinmiş üst reddedilir. Bir nesne birden fazla üste bağlanabilir (S02: fiş hem karta hem hesaba).

Özellikler. En az bir özellik (C13). Alan adında normalizasyon yok: " IBAN", "IBAN", "iban" üç ayrı alandır (C05); boş ad ve aynı nesnede aynı ad iki kez reddedilir. Sınırlar (C18): nesne başına 200 özellik, alan adı 128, değer 4.096 karakter; aşılırsa açık hata, veri kesilmez. Değer türü Cowork verebilir; vermezse Python türünden çıkarılır (bool → MANTIKSAL, int → TAMSAYI, float/Decimal → ONDALIK, str → METIN, liste/sözlük → JSON; TARIH yalnız açıkça). Türe uymayan değer reddedilir; ONDALIK Decimal olarak saklanır, TARIH ISO. eslesme_degeri türüyle kararlı seri hâl (METIN:123 ≠ TAMSAYI:123; 2.5 = 2.50; boş değer None, eşleşme üretmez). Özellik ve şart güncelleme işlevi yoktur (K13).

Bulma ve getirme. nesne_bul(alan_adi, deger, deger_turu, seviye, durumlar) alan adı ve türüyle değer üzerinden arar; Cowork yeni nesne açmadan önce mevcut olanı bununla bulur. nesne_getir özellikleri (şart işaretiyle), üstleri ve altları verir. aktif_nesneyi_getir finansal yazma için: AKTIF değilse açık hata.

Kaynak (C13). NesneKaynagi(belge_id, okuma_id, konum) verilirse nesne_kaynaka yazılır; belge yoksa HEDEF_BULUNAMADI. Kurum belgesiz açılabilir; kaynak zorunlu değil.

S03 kapsam dışı. "Başka defterdeki nesneye bağlantı" senaryosu tek defter kararıyla anlamsızlaştı; test yok.

Test (tests/test_nesneler.py): Garanti akışı uçtan uca; GONDER ONAY_BEKLIYOR + talep; aynı anahtar aynı nesne, farklı içerik çakışma; hata her şeyi geri alır; seviye 0/1/2; S02 iki üst; S01 farklı seviyeli üstler SEVIYE_CAKISMASI; olmayan/engelli/pasif üst; aynı üst iki kez; en az bir özellik; boş alan adı; aynı alan adı iki kez; alan adı normalize edilmez; sınır aşımı (201 özellik, 129 ve 4.097 karakter); tür çıkarımı ve eşleşme değeri; türe uymayan değer; şartsız onay AKTIF; şart seçimi kalıcı ve tekrarsız; başka nesnenin özelliği şart olamaz; red SILINDI; onay bekleyen üst; kaynak belge kaydı ve olmayan belge reddi; kurum belgesiz; bulma filtreleri (alan, değer türüyle, seviye, durum, boş değer); form veritabanına dokunmaz; denetim olayları ve anahtar kaydı.

Belge arşivi ve belge akışı

Teslim 4.5 (src/defteriki/arsiv.py, src/defteriki/belgeler.py). Ekran ve MCP aracı yok; işlev ve test düzeyi. Cowork'un belgeyi gelen dizinine bırakıp yolunu vermesi Aşama 3.3'te ölçülen yöntemdir (C10); parça yükleme gerekmediği için yazılmadı.

Arşiv (arsiv.py). dosyayi_arsivle(yol, gelen_dizini, belge_dizini) yolu 3.3'teki sırayla denetler (mutlak, .. yok, gerçek yol izinli gelen dizininin altında, simgesel bağlantı ya da takma yol değil, sıradan dosya; red GIRDI_GECERSIZ + kategorik gerekçe, mesajda yol yok), dosyayı <belge dizini>/gecici/<rastgele>.tmp adına akışla kopyalarken SHA-256 ve boyutu hesaplar, 50 MiB sınırını (C18) aşınca keser, fsync sonrası os.replace ile <ilk iki hex>/<sha256> yoluna atomik taşır. Herhangi bir adım düşerse geçici dosya silinir; yarım kopya kalmaz.

Karar (2026-09-16, Abdüllatif): fiziksel kimlik yalnız SHA-256. Arşiv yolu içerikten deterministik türer ve uzantı taşımaz; SHA-256 fiziksel kimliğin tek kaynağıdır. Aynı baytlar hangi adla, hangi uzantıyla ya da uzantısız gelirse gelsin tek fiziksel dosyaya karşılık gelir; hedef zaten varsa kopya atılır, "aynı SHA ile başlayan dosya" araması yapılmaz. Uzantı, MIME ve kaynak dosya adı metadata'dır; arsiv_dosya.uzanti, mime, kaynak_adi sütunlarında saklanır ve ilk gelişteki değerler kalır (aynı içerik sonra başka adla gelirse metadata değişmez). İki süreç aynı içeriği aynı anda arşivlerse ikisi de aynı baytları aynı yola bırakır; os.replace atomiktir, sonuç tek dosyadır; Windows'ta hedef o an açıksa taşıma reddedilir, hedef yerinde ve doğru boyuttaysa "zaten vardı" sayılır.

Giriş kapısı denetimi aynen durur: MIME ilk baytların imzasından (PDF, PNG, JPEG) belirlenir; imza biliniyorsa uzantı onunla uyuşmalı (PDF içerik .png ya da .xyz adıyla reddedilir, uzantısız kabul edilir), imza bilinmiyorsa uzantıdan tahmin, o da yoksa application/octet-stream. Boş dosya belge olamaz. arsivde_var_mi dosyanın yerinde ve kayıtlı boyutta olduğunu söyler (okuma başlatma ön şartı).

Belge alma. belge_al(veritabani, yol, ...) C10 akışıdır: önce arşivler, sonra kısa yazma işleminde belge_tanimla çağırır. Dosya ve veritabanı tek işlem değildir (Tam Plan 8.1): veritabanı düşerse dosya arşivde sahipsiz kalır, kaynaksız kayıt oluşmaz (sahipsiz dosya uzlaştırması Aşama 9). belge_tanimla arsiv_dosya + ARSIVLENDI belge yazar; aynı sha256 daha önce belge olduysa o belge döner, zaten_vardi=True, hiçbir şey yazılmaz (K18, UNIQUE(belge.dosya_id)). İşlem anahtarı zorunlu (araç adı belge_al).

Okuma. okuma_baslat(belge_id, sema_surumu, belge_dizini, icerik, tamlik) yalnız ARSIVLENDI belgede sürüm 1 okumayı ACIK açar, belge OKUNUYOR. Arşiv dosyası diskte yerinde değilse ARSIV_EKSIK (S10); belge yoksa BELGE_YOK. Tamlık (karar 2026-09-17, Abdüllatif): zorunlu; beş alanın her biri (beklenen_satir_sayisi, acilis_bakiyesi_kurus, kapanis_bakiyesi_kurus, toplam_giris_kurus, toplam_cikis_kurus) bir TamlikAlani(durum, deger) — DEGER (sayı zorunlu, bakiyeler negatif olabilir), BELGEDE_YOK (bilgi belgede gerçekten yok; değer verilemez; ilgili denetim atlanır ve kayda geçer), OKUNAMADI (bilgi belgede var ama güvenle çıkarılamadı; değer verilemez; belge kayıtlı olamaz). Alanın hiç gönderilmemesi, bilinmeyen durum, durumla çelişen değer GIRDI_GECERSIZ (alan adıyla). Satır sayısı için BELGEDE_YOK yasak: Cowork gördüğü hareketleri sayar, sayamıyorsa OKUNAMADI. "Unutuldu" ile "belgede yok" aynı şey değildir; eski biçim (sayı ya da boş) desteklenmez, geliştirme verisi sıfırlandı. JSON: {"alan": {"durum": ..., "deger": ...}}. sema_surumu Cowork'un uyduğu okuma sözleşmesinin sürümüdür; Aşama 5'te docs/cowork.md ile sabitlenir, şimdilik boş olmayan kısa metin. Tamlik(beklenen_satir_sayisi, acilis_bakiyesi_kurus, kapanis_bakiyesi_kurus, toplam_giris_kurus, toplam_cikis_kurus) isteğe bağlıdır; verilmeyen alan "bilinmiyor", "belgenin tamamı okundu" iddiası üretilmez. Yeni okuma sürümü (düzeltme akışı) Aşama 8.3'te.

Gönderim (K07). satir_gonder(okuma_id, satirlar) tek paketi ACIK okumaya yazar: SatirGirdisi(satir_anahtari, konum, ham, durum). Paket önce baştan sona doğrulanır; tek satırda bile biçim hatası varsa (boş ya da 128 karakteri aşan anahtar, pakette aynı anahtar iki kez, negatif ya da tam sayı olmayan konum, boş ya da JSON'a çevrilemeyen ya da 4.096 karakteri aşan ham, gönderilemez durum) hiçbir satır yazılmaz, hata satırın konumunu söyler (S11). Sınırlar (C18): 500 satır, 2 MiB. Aynı okumada aynı satır anahtarı aynı içerikle yeniden gelirse tekrar gönderimdir, satır zaten_mevcut listesine girer; içerik farklıysa ANAHTAR_ICERIK_CAKISMASI ve paket bütünüyle düşer. Satır durumu gönderimle gelir: YAZILDI ya da KAPSAM_DISI (başlık/bilgi satırı). Finansal satır için satir_gonder değil kayitlar.hareket_yaz kullanılır: satırı aynı gönderimde kabul eder (satirlari_kabul_et çekirdeği ortak), kayıt ve etkiyi üretir, YAZILDI yazar. satir_gonder kayıtsız satırlar (başlık, bilgi) içindir. Karar notu: C08'de kabul ile kayıt arasında ara satır durumu yok; gerekirse listeye Abdüllatif'in onayıyla eklenir.

Tamamlama ve belge kaydı (K19, C07). okuma_tamamla(okuma_id, tamlik) Cowork'un "bitti" bildirimidir: okuma TAMAMLANDI, belge HAZIR, ardından uygulama belge kaydını tanımlar (aktör UYGULAMA): belge KAYITLI, etkin_okuma_id bu okuma; ek onay yok. Koşullar: her satır sonuçlanmış (YAZILDI, MEVCUDA_BAGLANDI, KAPSAM_DISI; aksi BELGE_HAZIR_DEGIL) ve tamlıkta beklenen satır sayısı verildiyse yazılan satır sayısıyla aynı (aksi MUTABAKAT_FARKI), hiçbir tamlık alanı OKUNAMADI değil (aksi BELGE_HAZIR_DEGIL, alan adıyla), DEGER olan toplam giriş / toplam çıkış yazılan satırların ARTTIR / AZALT toplamıyla aynı ve açılış + giriş − çıkış = kapanış (ikisi de DEGER ise; karar 2026-09-17, _toplamlari_denetle). BELGEDE_YOK yüzünden atlanan denetimler belge kaydı denetim olayının gerekçesine yazılır ("etkin okuma 1; atlanan denetimler: toplam_giris_kurus BELGEDE_YOK; kapanış eşitliği (acilis_bakiyesi_kurus BELGEDE_YOK)"). Koşul sağlanmazsa hiçbir durum değişmez: okuma ACIK kalır, eksik satır gönderilip ya da tamlık DEGER ile yeniden verilip yeniden tamamlanır. Belge türüne göre bazı alanların BELGEDE_YOK olamaması Aşama 8'in konusu (okuma içeriğine bağlı kural). Açık şüphe koşulu Aşama 7'de. belge_kaydet(belge_id, gorulen_surum) HAZIR kalmış belgeyi (Aşama 7'de karar sonrası) koşulları yeniden denetleyerek KAYITLI yapar; sürüm uyuşmazsa HEDEF_SURUMU_DEGISTI. Belge sürümü her durum değişiminde bir artar (ARSIVLENDI 1 → OKUNUYOR 2 → HAZIR 3 → KAYITLI 4).

Her yazma işlevi işlem anahtarı ister, denetim olayı yazar, commit yapmaz. Denetim izi: belge_al, okuma_baslat, satir_gonder, okuma_tamamla, belge_hazir, belge_kaydet.

Test (tests/test_arsiv.py): içerik adresli (uzantısız) atomik taşıma ve geçici dosya kalmaması; aynı içerik farklı ad / aynı ad / uzantısız / bilinmeyen uzantı / bilinen uzantıyla gelince tek fiziksel dosya, ad ve uzantı metadata; imzalı içerik bilinmeyen uzantıyla kapıda ret; parçalı okuma ve özet; sınır aşımı ve kopya ortasında hata sonrası yarım kopya yok; boş dosya; MIME imzadan/uzantıdan; uzantı-içerik uyuşmazlığı; 3.3 yol kuralları (göreli, .., olmayan, dizin dışı, dizin, dışarıya ve içeriye simgesel bağlantı; bağlantı testleri Windows'ta yetki yoksa atlanır). Test (tests/test_belgeler.py): uçtan uca ARSIVLENDI → KAYITLI (durumlar, sürümler, etkin okuma, satırlar, denetim izi, kaydı uygulama tanımlar); aynı dosya iki kez tek belge; aynı anahtar saklı sonuç / farklı dosya çakışma; farklı içerik ayrı belge; veritabanı düşerse dosya arşivde belge yok; izinsiz yol; S10 (belgesiz okuma, arşiv dosyası silinmiş, olmayan okumaya satır); ikinci okuma açılmaz; şema sürümü ve tamlık doğrulama (dokuz geçersiz tamlık: negatif/bool/ondalık değer, BELGEDE_YOK ve OKUNAMADI ile değer, satır sayısı BELGEDE_YOK, bilinmeyen durum, eksik alan; tamlık zorunlu; negatif bakiye kabul ve üç durum JSON'dan kayıpsız döner); S11 on biçim hatası paketin tamamını düşürür; boş ve 501 satırlık paket; tekrar gönderim mevcut/çakışma; aynı işlem anahtarı; kapalı okumaya satır; mutabakat farkı hiçbir durumu değiştirmez ve eksik satırla tamamlanır; tamamlarken tamlık; OKUNAMADI belgeyi kayıtlı yapmaz, DEGER ile yeniden tamlık verilince kayıtlı; BELGEDE_YOK denetimi atlar ve kayıt olayına yazar; atlanan yoksa olay sade; yeniden tamamlama; hata her şeyi geri alır; belge_kaydet HAZIR → KAYITLI, eski sürüm, hazır olmayan belge; sonuçlanmamış satır kaydı engeller; dört ayrı süreç aynı içeriği farklı adlarla aynı anda getirir → arşivde tek dosya, tek arsiv_dosya, tek belge, dört işlem anahtarı, geçici dosya yok.

Hareket yazma ve etkin bakiye

Teslim 4.6 (src/defteriki/finansal_kurallar.py, kayitlar.py, hesaplamalar.py). Ekran ve MCP aracı yok; işlev ve test düzeyi.

Sözleşme (C02). Finansal davranış nesne türüyle değil işlem sözleşmesiyle belirlenir. Bu teslimde tek sözleşme: HESAP_HAREKETI, yani belirlenen nesnede VARLIK ekseninde ARTTIR ya da AZALT; gelen para gelir, çıkan para gider sayılmaz (gider anlamı Aşama 8'in sözleşmeleriyle). finansal_kurallar.hesap_hareketi_dogrula(HesapHareketi) saf işlevdir, veritabanına dokunmaz: nesne kimliği katı, yön ARTTIR/AZALT, tutar kuruş cinsinden pozitif tam sayı (S20: float, bool, metin, Decimal, sıfır ve 64 bit taşma açık ret, sessiz yuvarlama yok), para birimi zorunlu ve belgeden (varsayılan yok), işlem tarihi zorunlu ve valör isteğe bağlı (date ya da YYYY-AA-GG; datetime reddedilir), açıklama en çok 512 karakter. Çıktı HareketTaslagi: kayıt alanları + tek VARLIK etkisi.

Yazma (kayitlar.hareket_yaz). Sözlükteki anlamıyla yazmaktır, kayıt etmek değil. hareket_yaz(okuma_id, satir, hareket, islem_anahtari, aktor) satırı aynı gönderimde kabul eder (belgeler.satirlari_kabul_et; biçim hatası paketi düşürür, K07), nesnenin AKTIF olduğunu denetler (ONAY_BEKLIYOR/PASIF/SILINDI ret, ENGELLI → NESNE_ENGELLI), tek işlemde kayit (AKTIF) + etki + kayit_kaynak (ASIL, AKTIF) yazar ve denetim olayı düşer. Kaynak satırı zorunludur (K06, S10): okumasız, olmayan ya da kapalı okumaya hareket yazılmaz; KAPSAM_DISI satıra hareket bağlanmaz. İşlem anahtarı zorunlu (K08, S18 tek süreç): aynı anahtar aynı içerik saklı sonuç, tek etki; farklı içerik ANAHTAR_ICERIK_CAKISMASI. Aynı satır anahtarı başka işlem anahtarıyla yeniden gelirse (Tam Plan 8.5.1): hareket mevcut kayıtla aynıysa tekrar gönderim, mevcut kayıt döner; tutar, yön ya da para birimi farklıysa KAYNAK_CAKISMASI. Kaydı olmayan mevcut satıra (4.5 satir_gonder ile yazılmış) kayıt bağlanır. Hareket mükerrerliği karşılaştırması (referans, tarih + tutar + yön) Aşama 8.2'de.

Etkin bakiye (hesaplamalar). Tam Plan 10.3: etkin(etki) = en az bir KAYITLI ve geçerli kaynak desteği. etkin_bakiye(nesne_id, eksen, para_birimi, tarih) yalnız etkin etkileri toplar: kaynak bağı AKTIF, kaynak satırının okuması belgenin etkin okuması (belge.etkin_okuma_id), belge KAYITLI, kayıt AKTIF; tarih sınırı dahil; ARTTIR − AZALT. Her etkinin desteği EXISTS ile seçilir, her etki bir kez toplanır (çifte toplama engeli, 8.5.5). Yazılmış ama belgesi henüz KAYITLI olmayan kayıtlar bekleyen_kayit_sayisi olarak ayrıca sayılır, bakiyeye girmez (K19). hareketleri_listele(nesne_id, eksen, baslangic, bitis, sayfalama) tarih ve kimlik sırasıyla döner; her satırda kayitli bayrağı (yazılmış / kayıtlı ayrımı). Toplamlar SQL'de; GUI ve MCP aynı işlevi çağıracak.

Test (tests/test_finansal_kurallar.py): geçerli hareket tek VARLIK etkisi; tarih metin, valör ve açıklama isteğe bağlı; S20 tutar reddi (12.0, 12.5, True, False, "100", "12,50", Decimal, None, -1, 0), taşma sınırı; Hypothesis: pozitif tam sayı her zaman kabul, sıfır/negatif/taşma ve float/bool her zaman ret; kimlik, yön, para birimi, tarih biçimi, açıklama; saf işlev veritabanına dokunmaz. Test (tests/test_kayitlar.py): kayıt + etki + kaynak + satır tek işlemde, denetim olayı; S18 aynı anahtar iki kez tek etki, farklı içerik çakışma; aynı satır farklı anahtar aynı hareket tekrar gönderim; aynı satıra farklı tutar/yön KAYNAK_CAKISMASI; aynı satır anahtarı farklı ham paket düşer; kaydı olmayan mevcut satıra kayıt bağlanır; S10 olmayan ve kapalı okuma; KAPSAM_DISI satır; biçim hatalı satır hareketi de düşürür; geçersiz tutar veritabanına dokunmadan ret; onay bekleyen, engelli ve olmayan nesne; hata her şeyi geri alır; uçtan uca hareketli belge KAYITLI. Test (tests/test_hesaplamalar.py): boş hesap sıfır; yazılmış ama kayıtsız belge bakiyeye girmez, KAYITLI olunca girer (bekleyen sayısı ve kayitli bayrağı); iki belge ayrı ayrı kayıtlı olur, tarih sınırı; başka nesne ve başka eksen karışmaz; GECERSIZ kayıt, kaldırılmış kaynak desteği ve GECERSIZ belge toplanmaz; etkin olmayan okuma sürümü sayılmaz; hareket listesi sıralı, filtreli, sayfalı; Hypothesis: rastgele ARTTIR/AZALT dizisi için kayıt öncesi bakiye 0, sonrası ARTTIR − AZALT, bekleyen sayısı geçişi.

Aşama 4 kapısı: uçtan uca test

tests/test_asama4_kapisi.py gerçek başlangıç akışıyla (ortami_hazirla şemayı kurar, yollar ayarlardan) zinciri tek testte yürütür: Garanti BBVA ve ME hesabı ONAY_BEKLIYOR yazılır, kullanıcı şart seçip onaylar (ad, iban) → ekstre gelen dizinine bırakılır, arşivlenir, belge ARSIVLENDI → okuma açılır (OKUNUYOR) → üç hareket ve bir kapsam dışı başlık satırı yazılır; bakiye sıfır, üç kayıt bekliyor (K19) → okuma_tamamla; uygulama belge kaydını tanımlar, KAYITLI → bakiye 1.250,00 TL, tarih sınırı, banka nesnesinde hareket yok → aynı ekstre ikinci kez gelince aynı belge, ikinci etki yok (K18); tablo sayıları ve işlem anahtarı sayısı doğrulanır. İkinci test: uygulama kapanıp açılınca veri yerinde, şema yeniden kurulmaz. Başlangıç testleri: ilk başlatma şemayı kurar ve on beş tabloyu açar, ikinci başlatma kurmaz, yabancı sürümde (0000) 1 ile durur ve "yedek" der; MCP stdio testi sema_surumunü görür.

Teknik hata günlüğü

Günlük yalnızca ayarlardaki log dizinine yazar: <log dizini>/defteriki.log (varsayılan <veri kökü>/<ortam>/logs/defteriki.log). Standart kütüphanenin logging modülü kullanılır; ek bağımlılık yoktur.

Her satır zaman | seviye | olay | mesaj biçimindedir; olay türleri şimdilik baslangic, baslangic_hatasi, mcp_baslangic, mcp_el_sikisma, mcp_kapanis, mcp_hatasi. Dosya günlüğüne bağlanan dış kütüphane kayıtlarında olay - olur.

Saklama sınırı: dosya 1.000.000 baytı aşınca döndürülür, en fazla 5 eski dosya (defteriki.log.1 ... .5) tutulur; toplam en çok ~6 MB. Kurulum tekrar çağrılırsa önceki handler kapatılıp kaldırılır, aynı olay birden fazla yazılmaz.

Gizlilik: belge içeriği, finansal kayıt içeriği, IBAN, kimlik bilgileri, sırlar ve ortam değişkenleri günlüğe yazılmaz. Hatalar yalnızca türüyle (builtins.ValueError gibi) kaydedilir; ham hata mesajı ve traceback dosyaya dökülmez. Kullanıcıya gösterilen hata metni stderr'e gider, dosyaya değil.

Kalite kontrolü

Biçim kontrolü, statik kontrol, tip kontrolü ve testler tek komutla:

uv run python scripts/kontrol.py

Betik sırayla ruff format --check, ruff check, pyright ve pytest çalıştırır. Bir adım düşse de diğerleri çalışır; sonunda toplu sonuç verir ve herhangi bir adım başarısızsa sıfırdan farklı çıkış kodu döner. Kaynak dosyalarını değiştirmez.

Yalnızca testler:

uv run pytest

Aynı kontrol her git commit öncesinde pre-commit kancasıyla otomatik çalışır (.pre-commit-config.yaml, tek kanca: scripts/kontrol.py); bir adım düşerse commit yapılmaz. Kanca kaynak dosyalarını değiştirmez.

Ayarlar

Bütün yollar defteriki.ayarlar modülünden gelir; uygulamanın nereden başlatıldığı yolları değiştirmez.

from defteriki.ayarlar import ayarlari_yukle, dizinleri_hazirla

ayarlar = ayarlari_yukle()  # ortam değişkenlerini okur, diske yazmaz
dizinleri_hazirla(ayarlar)  # gerekli dizinleri açar, dosya oluşturmaz

Ortam değişkenleri (öncelik yukarıdan aşağıya):

Değişken

Anlamı

DEFTERIKI_VERITABANI_YOLU

Veritabanı dosyası; türetilmiş yolun yerine geçer

DEFTERIKI_BELGE_DIZINI

Belge arşivi dizini; türetilmiş yolun yerine geçer

DEFTERIKI_LOG_DIZINI

Log dizini; türetilmiş yolun yerine geçer

DEFTERIKI_GELEN_DIZINI

Gelen dizini: Cowork'un dosya bıraktığı, MCP araçlarının okumaya izinli olduğu tek dizin; türetilmiş yolun yerine geçer

DEFTERIKI_VERI_KOKU

Ortamların ortak üst dizini; ortam adı altına eklenir

DEFTERIKI_ORTAM

gelistirme (varsayılan), test, gercek

Varsayılan veri kökü Windows'ta %LOCALAPPDATA%\DEFTERIKI\<ortam>, Linux'ta $XDG_DATA_HOME/DEFTERIKI/<ortam> (yoksa ~/.local/share/...), macOS'ta ~/Library/Application Support/DEFTERIKI/<ortam>. Bu kökten defteriki.sqlite3, belgeler/, logs/ ve gelen/ türetilir.

Kurallar:

  • Yollar mutlak olmalı; boş veya göreli değer hata verir.

  • Bilinmeyen ortam adı hata verir.

  • test ortamı DEFTERIKI_VERI_KOKU ister ve tekil yolların bu kökün dışına çıkmasına izin vermez.

  • Tekil yol değişkenleri diğer ortamlarda ortam ayrımını geçersiz kılabilir.

Dizin düzeni

src/defteriki/    uygulama paketi
  ayarlar.py      merkezi ayarlar (ortam, yollar)
  baslangic.py    uv run defteriki giriş noktası; ortak hazırlık (ortami_hazirla: ayarlar, dizinler, günlük, şema)
  gunluk.py       teknik hata günlüğü
  mcp_kapisi.py   uv run defteriki-mcp; MCP sunucusu, araç kaydı, güvenli hata çevirisi
  mcp_araclari.py MCP araç gövdeleri: girdi modeli → Aşama 4 işlevi → zarf
  zarf.py         ortak MCP yanıt zarfı ve hata çevirisi
  sozlesmeler.py  ortak türler, durum adları, hata kodları, sayfalama
  veritabani.py   SQLite bağlantısı; yazma_islemi / okuma_islemi
  sema.py         on beş tablo (METADATA), şema sürümü denetimi ve yükseltme
  islem_anahtarlari.py  işlem anahtarı koruması (aynı anahtar aynı sonuç, K08)
  denetim.py      denetim olayı yazımı
  onaylar.py      onay talebi: oluştur, listele, karar uygula (yalnız ekran)
  nesneler.py     nesne tanıtma (FORM/GONDER), seviye, şart seçimi etkisi, bulma
  arsiv.py        gelen dizini denetimi, akışla kopya ve SHA-256, atomik taşıma
  belgeler.py     belge alma/tanımlama, okuma, satır gönderimi, tamamlama, belge kaydı
  finansal_kurallar.py  işlem sözleşmeleri (yalnız HESAP_HAREKETI), saf doğrulama
  kayitlar.py     hareket yazma: kayıt + etki + kaynak bağı, tek işlem
  hesaplamalar.py etkin bakiye (yalnız KAYITLI belge, EXISTS), hareket listesi
migrations/       Alembic ortamı (env.py) ve sürümler (versions/0001_ilk_sema.py, 0002_para_birimi_serbest.py)
alembic.ini       Alembic ayarı; URL yok, yol ayarlardan
tests/            pytest testleri
scripts/          geliştirme betikleri (kontrol.py)
.pre-commit-config.yaml  commit öncesi kanca; kontrol.py'yi çalıştırır
kavramlar_sozlugu.md   ortak kavram tanımları (Defter, Nesne, Mükerrerlik, Yazmak/kayıt etmek ...); değişiklik yalnız Abdüllatif'in onayıyla

Teknoloji

Bu projede kullanılacak teknoloji. Mutlak değil; ihtiyaç duyulması halinde değişebilir.

  • Python 3.13 — ana dil

  • uv — paket ve sanal ortam yönetimi

  • pyproject.toml — proje/bağımlılık tanımı

  • uv.lock — bağımlılık kilidi

  • SQLite — ilişkisel veritabanı

  • WAL — SQLite çalışma/journal modu; ayrı bir teknoloji değil

  • SQLAlchemy 2.0 — veritabanı erişimi (kilitli: uv.lock)

  • Alembic 1.20 — migration (Aşama 4.2'den itibaren)

  • Pydantic 2.13 — katı tür doğrulama; ileride MCP giriş/çıkış şemaları

  • MCP Python SDK 2.x (mcp, MCPServer) — Cowork ↔ DEFTERIKI kapısı

  • PySide6 — masaüstü GUI için

  • pytest — test

  • Hypothesis — property-based test

  • Ruff — lint + format

  • Pyright strict — statik type checking

  • pre-commit — commit öncesi kalite kontrolleri

  • Git — sürüm kontrolü

  • .gitignore — DB, WAL/SHM, kişisel veri, cache, secret vb. dışlama

  • .gitattributes — LF/CRLF standardizasyonu

Available Tools

2 tools
dosya_deneA

Dosya erişim denemesi. Verilen mutlak yoldaki dosyayı DEFTERIKI'nin izinli gelen dizininde arar, akışla okur ve SHA-256 özeti ile bayt boyutunu döndürür; içerik döndürmez. Gelen dizininin dışındaki yollar, simgesel bağlantılar ve '..' içeren yollar reddedilir; red durumunda sonuc 'reddedildi' ve gerekce dolu döner.

ParametersJSON Schema
NameRequiredDescriptionDefault
yolYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sonucYes
sha256Yes
gerekceYes
boyut_baytYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden, and it delivers: it discloses that the file is read as a stream, returns only the SHA-256 hash and byte size, explicitly says content is not returned, and details rejection conditions ('reddedildi' with reason). This goes well beyond what the minimal schema conveys and fully informs the agent of the tool's behavior and side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense sentence that packs purpose, behavior, constraints, and rejection behavior. It is front-loaded with the main purpose and then details. It is not verbose or repetitive, though it could benefit from splitting into shorter sentences for easier scanning. Still, every phrase earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with one required parameter, an output schema (though not shown, it is indicated as present), and no annotations, the description covers all needed aspects: what it does, what it returns (hash, size, rejection reason), what it does not return (content), and all rejection rules. No additional information is needed for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only a parameter named 'yol' with type string and no description (0% coverage). The description compensates entirely by explaining that 'yol' must be an absolute path within the allowed incoming directory, and that paths outside, symlinks, or containing '..' are rejected. This adds crucial semantic meaning that the schema alone lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb phrase ('Dosya erişim denemesi' – file access attempt) and specifies the resource (a file at an absolute path in the allowed directory), the actions (searches, reads, returns SHA-256 hash and byte size), and a key constraint (does not return content). It clearly distinguishes itself from the only sibling 'sistem_durumu' (system status) by focusing on file access rather than system information.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states the tool's context: it works only within the allowed incoming directory and explicitly rejects paths outside, symbolic links, and '..' paths. While it does not explicitly name alternative tools or say 'use this when X', the single sibling (sistem_durumu) is obviously a different operation, so the usage context is unambiguous. However, it lacks an explicit comparison or 'when not to use' clause, which would earn a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sistem_durumuA

DEFTERIKI'nin durumunu döndürür: uygulama sürümü, çalışma ortamı, şema sürümü ve bu sunucunun yetenek listesi. Yol, anahtar ya da ortam değişkeni içermez.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
ortamYes
yeteneklerYes
sema_surumuYes
uygulama_surumuYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description must carry the behavioral disclosure burden. It does so well by listing the informational payload and explicitly stating that the response contains no path, key, or environment variable, which is useful safety-relevant context. It does not explicitly state that the call has no side effects, but the read-only status framing makes that reasonably clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences deliver the core purpose first, then a valuable negative constraint. Every sentence earns its place and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter status tool with an output schema present, the description is complete: it tells the agent what the tool does, what fields it returns, and what sensitive content it will not include. Nothing else is needed for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there are no parameter semantics to document; the baseline is 4. The description adds a small bonus by explicitly noting the tool contains no path, key, or environment variable, reinforcing the null parameter expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('döndürür'/'returns') with a clear resource ('DEFTERIKI'nin durumu') and enumerates exactly what the status includes: app version, environment, schema version, and server capability list. This both identifies the tool's function and makes it easy to distinguish from the sibling tool, dosya_dene, which is file-oriented.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied: call this when you need current server status, version, environment, or capability information. However, it does not explicitly state when this should be preferred over an alternative or when it should be avoided, so the guidance is not fully explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observeddosya_dene
    • First observedsistem_durumu

TDQS

A4/5.0

Scored across 2 tools

Disambiguation5/5

The two tools serve entirely different purposes: one reports server status and capabilities, the other attempts file access and returns metadata. There is no overlap or ambiguity in when to use each.

Naming Consistency3/5

Both tools use Turkish and snake_case, but the patterns differ: 'sistem_durumu' is a noun phrase (system status) while 'dosya_dene' is an imperative verb phrase (try file). With only two tools, the inconsistency is minor but noticeable.

Tool Count2/5

Only two tools exist, which feels very thin for a server that appears to handle file access. While the server may be intentionally minimal, there is little surface for an agent to accomplish meaningful workflows.

Completeness2/5

The server provides status and a single file probe that returns only hash and size, not content or directory listings. For a file-focused server, this leaves obvious gaps like listing directory contents or reading file data, making many common tasks impossible.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables secure and controlled access to SQLite databases through the Model Context Protocol. Provides comprehensive database operations with granular permissions, SQL injection protection, and audit logging for safe database interactions.
    150 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables comprehensive SQLite database operations including CRUD operations, schema management, and meta commands across multiple database files through the Model Context Protocol.
    25 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with SQLite databases by executing read and write queries, listing tables, and inspecting schemas. It provides a secure, local interface for database management and data retrieval through the Model Context Protocol.
    2
    MIT