@appaflytech/zeyrek-ai-mcp 0.0.41 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/knowledge/componentCatalog.js +27 -97
  2. package/dist/knowledge/componentEvents.js +1 -18
  3. package/dist/knowledge/mobileComponentCatalog.js +114 -15
  4. package/dist/knowledge/mobileComponentEvents.js +41 -0
  5. package/dist/knowledge/motionResolve.js +252 -0
  6. package/dist/knowledge/normalize.js +87 -59
  7. package/dist/knowledge/pageDiscover.js +2 -2
  8. package/dist/knowledge/platform/batchOps.js +70 -0
  9. package/dist/knowledge/platform/heroTag.js +153 -0
  10. package/dist/knowledge/platform/lint.js +128 -6
  11. package/dist/knowledge/platform/mobile.js +1 -1
  12. package/dist/knowledge/platform/mobileLayoutLint.js +8 -1
  13. package/dist/knowledge/platform/mobileRules.js +18 -0
  14. package/dist/knowledge/platform/pageTransition.js +57 -0
  15. package/dist/knowledge/platform/web.js +1 -1
  16. package/dist/knowledge/rules.js +52 -1
  17. package/dist/knowledge/styleResolveNative.js +88 -4
  18. package/dist/platform/capture/actions.js +4 -1
  19. package/dist/platform/capture/capture.js +10 -13
  20. package/dist/platform/capture/persistent-browser.js +130 -0
  21. package/dist/resources/examples/flow-list-to-form.json +8 -10
  22. package/dist/resources/examples/flow-load-table.json +1 -1
  23. package/dist/resources/examples/mobile-list-detail-form.json +4 -3
  24. package/dist/resources/examples/mobile-scan-code.json +285 -0
  25. package/dist/resources/guides/component.md +3 -3
  26. package/dist/resources/guides/expressions.md +2 -2
  27. package/dist/resources/guides/merge.md +98 -18
  28. package/dist/resources/guides/microservice.md +2 -2
  29. package/dist/resources/guides/mobile-layout.md +2 -1
  30. package/dist/resources/guides/mobile-publish.md +1 -0
  31. package/dist/resources/guides/mobile-steps.md +67 -0
  32. package/dist/resources/guides/mobile.md +27 -55
  33. package/dist/resources/guides/page.md +182 -121
  34. package/dist/resources/guides/translation.md +26 -0
  35. package/dist/resources/schema-fingerprint.json +2 -2
  36. package/dist/resources/schemas/ResolveMergeConflictsCommand.json +30 -1
  37. package/dist/tools/activities.js +3 -1
  38. package/dist/tools/applications.js +16 -2
  39. package/dist/tools/components.js +12 -6
  40. package/dist/tools/designSchemaPatch.js +18 -13
  41. package/dist/tools/layouts.js +7 -2
  42. package/dist/tools/merges.js +29 -9
  43. package/dist/tools/pages.js +129 -127
  44. package/dist/tools/platformInfo.js +3 -2
  45. package/dist/tools/profileWrite.js +2 -2
  46. package/dist/tools/schemaOps.js +132 -34
  47. package/dist/tools/screenWrite.js +1 -1
  48. package/dist/tools/screens.js +3 -3
  49. package/package.json +2 -2
@@ -189,16 +189,16 @@ Tablonun/listenin satırları şemaya "dataSource" yazarak değil, **flow ile**
189
189
  ```
190
190
 
191
191
  **Event'ler komponent tipine göre değişir; `component_get`'in `events` alanından okunur.**
192
- Sayfa açılışında veri çekmek için `mount` kullanılır ama tek seçenek o değil — örneğin `table`
193
- 8 olay yayar:
192
+ Sayfa açılışında veri çekmek için `mount` kullanılır ama tek seçenek o değil — örneğin
193
+ `datatable` 7 olay yayar:
194
194
 
195
- `mount · pagination · filter · sort · select · selectionChange · doubleClick · rowChange`
195
+ `mount · rowClick · rowDoubleClick · save · discard · rowSelectionChange · cellSelectionChange`
196
196
 
197
- Yani "satırı seçince detay getir" (`select`), "kolondan süzünce sunucudan yeniden çek"
198
- (`filter`), "sayfa değişince yeni sayfayı çek" (`pagination`), "satıra çift tıklayınca formu aç"
199
- (`doubleClick`) akışları da aynı `set_event` mekanizmasıyla kurulur. Buna karşılık `datatable`
200
- yalnız `mount` yayar (bilinçli — Kural 1e); `page-header` 2026-09-18'den beri izdeki öğe
201
- tıklamasını `clickItem` olarak yayar (`component_get` yükü verir).
197
+ Yani "satıra tıklayınca detay getir" (`rowClick`), "satıra çift tıklayınca formu aç"
198
+ (`rowDoubleClick`), "düzenlenen satırları kaydet" (`save`) akışları da aynı `set_event`
199
+ mekanizmasıyla kurulur. Süzme, sıralama ve sayfalamanın AYRI olayı yoktur: `datatable` kendi
200
+ prop'larını yazıp `mount`'u yeniden tetikler (bilinçli — Kural 1e); `page-header` 2026-09-18'den
201
+ beri izdeki öğe tıklamasını `clickItem` olarak yayar (`component_get` yükü verir).
202
202
 
203
203
  **Olay adları `on` ÖNEKİ ALMAZ** (`button` → `click`, `form` → `submit`, `texteditor` → `change`);
204
204
  katalogda istisna yok. **Komponentin desteklemediği bir olay adı verirsen bağ
@@ -239,19 +239,18 @@ aksiyonları (`platform_guide('html')`) ve **`params`'ı da gönderen komponentl
239
239
  (`eventcalendar` · `importwizard` · `kanban` · `signature` · `stepper` · `tabs` ·
240
240
  `tree-view` · `pagination`): bunların yükü `event.data.<anahtar>` ile de okunur; `kanban` ve
241
241
  `eventcalendar` yükü `self`'e HİÇ yazmaz (`component_get` çıktısındaki sözleşme notları ayrımı
242
- söyler). Sessiz hata örneği: **tablonun kendi** sayfalama akışını (`table.pagination`)
243
- `event.data.limit`'e bağlarsan sorgu `LIMIT null OFFSET null` ile koşar ve **tüm satırları**
244
- döndürür; hata yok, sayfalama yok. (Bağımsız `pagination` komponenti bu tuzağa girmez, yükünü
245
- `params` ile de gönderir.)
242
+ söyler). Sessiz hata örneği: **tablonun** yükleme akışında sayfa değerlerini `event.data.limit` /
243
+ `event.data.offset`'ten okursan sorgu `LIMIT null OFFSET null` ile koşar ve **tüm satırları**
244
+ döndürür; hata yok, sayfalama yok — `datatable` bu değerleri `self.limit` / `self.offset`'e yazar
245
+ (ölçüm 2026-08-25, kaldırılan tablonun sayfalama olayında; kural aynı). (Bağımsız `pagination`
246
+ komponenti bu tuzağa girmez, yükünü `params` ile de gönderir.)
246
247
 
247
248
  | Komponent · olay | Yük (aynı zamanda prop adları) | Akışta nereden okunur |
248
249
  |---|---|---|
249
- | `table.sort` | `{ sortField, sortType, offset }` | `self.sortField` · `self.sortType` · `self.offset` |
250
- | `table.filter` | `{ filters, offset }` | `self.filters` · `self.offset` |
251
- | `table.pagination` | `{ offset, limit }` | `self.offset` · `self.limit` |
252
- | `table.select` · `doubleClick` | — | `self.selectedRow` |
253
- | `table.selectionChange` | — | `self.selectedRows` |
254
- | `datatable.mount` | — | `self.filters` · `self.sortField` · `self.sortType` · `self.offset` |
250
+ | `datatable.mount` | — | `self.filters` · `self.sortField` · `self.sortType` · `self.offset` · `self.limit` |
251
+ | `datatable.rowClick` · `rowDoubleClick` | — | `self.selectedRow` |
252
+ | `datatable.rowSelectionChange` | — | `self.selectedRows` |
253
+ | `datatable.save` | — | `self.operation` · `self.changeset` · `self.editedRows` · `self.deletedRows` |
255
254
  | `pagination.change` | `{ offset, limit }` | `self.offset` · `self.limit` ya da `event.data.offset` · `event.data.limit` |
256
255
  | `textinput/textarea/password.change` | `{ value }` | `self.value` |
257
256
  | `dropdown.change` · `multi-select.change` | `{ value }` | `self.value` |
@@ -961,7 +960,8 @@ kapsayıcının kardeşi olarak yaşar (qm `[SY] Profil bilgilerim`: `page_conta
961
960
  > `gatewayNormalized` ile bildirir. Senin verdiğin `appearance.heightType`'a dokunmaz.
962
961
  >
963
962
  > Katalogda `isDefaultAutoHeight: false` olan (yani `fixed` damgalanan) tipler: `auth-layout`,
964
- > `html`, `image`, `layout`, `qrcode`, `table`, `text-editor`, `video`. Diğer her tip `auto`'dur.
963
+ > `html`, `image`, `layout`, `layout-region`, `layout-shell`, `qrcode`, `texteditor`, `video`
964
+ > (katalogdan ölçüldü 2026-10-13). Diğer her tip `auto`'dur.
965
965
  > Bu tiplerde `size.h` gerçek yüksekliktir — göz kararı değil, içeriğe göre hesapla
966
966
  > (bir satır ≈ 10px; Kural 1f).
967
967
 
@@ -985,107 +985,104 @@ sayfasında da reddedilir (web sayfayı her gezinmede baştan kurar, `mount` yet
985
985
  - Akış kilidi burada da geçerlidir (Kural 3): önce bütün `flow_create`'ler, sonra events bağı.
986
986
  - Mevcut bağları `page_get` gösterir (`events[].value` = flow id).
987
987
 
988
- ## Kural 1e — İKİ tablo komponenti var: `table` ve `datatable`
989
-
990
- > **`data-table` KALDIRILDI (2026-08-17).** Katalogda böyle bir slug yok; eski bir örnekte ya da
991
- > eski bir sayfada görürsen `datatable` ya da `table` ile değiştir. Katalogda tablo işi gören
992
- > başka komponent yoktur — aşağıdaki iki satır listenin tamamıdır.
993
-
994
- | slug | Olaylar | Ayırt edici prop'lar |
995
- |---|---|---|
996
- | `table` | 8: `mount · pagination · filter · sort · select · selectionChange · doubleClick · rowChange` | `rowSelection` (none/single/multi), `selectedRow`/`selectedRows`, `filterMode` (panel/hide/row), `filters`, `showSort`, `sortField`/`sortType`, `isEditable`, `showColumnMenu`, `actions`, `emptyIcon/emptyText/emptyActions`, `style` (root/thead/th/tr/td), satır bazlı `_columns`/`_actions` ezmesi (Kural 1e-2) |
997
- | `datatable` | 1: `mount` | `title`, `locale` (tr/en), `tableStyle` (zebra/plain — satır zemini varyantı), **`style`** (parça bazlı CSS: `&__toolbar`/`&__title`/`&__head`/`&__th`/`&__body`/`&__row`/`&__td`), kolonlarda `isFilterable`/`isSortable`/`colorMap` (statik)/`prefix`/`suffix`/`precision`/`thousands`/`dateFormat`/`imageShape`/**`progress`** kolon tipi, `filters`/`sortField`/`sortType` (hidden), `actions` |
998
-
999
- **`datatable`'ın tek olay yayması eksiklik değil, tasarım.** Filtre paneli, sıralama ve sayfalama
1000
- komponentin İÇİNDE: kullanıcı süzdüğünde/sıraladığında/sayfa değiştirdiğinde `datatable` önce
1001
- kendi `filters`/`sortField`/`sortType`/`offset` prop'larını node'a yazar, sonra **`mount`'u
1002
- yeniden tetikler** (`updateQuery` → `emitMount`). Yani tek bir `mount` akışı yazarsın; o akış
1003
- tabloya bağlı uca bu prop'ları parametre olarak geçirir ve dönen satırları geri yazar.
1004
-
1005
- **`table`'da her etkileşim AYRI bir olaydır** ve her birini ayrı akışa bağlarsın (`filter`,
1006
- `sort`, `pagination` olayları yükte yeni değerleri de taşır — yukarıdaki olay yükü tablosu).
1007
-
1008
- Her ikisinin de süzme/sıralaması sunucu taraflıdır: seçilen filtreler uca `filters` parametresi
1009
- olarak gider ve ancak `enableDynamicFilters: true` olan bir uçta karşılık bulur
988
+ ## Kural 1e — Tablo komponenti `datatable`'dır
989
+
990
+ > **`table` KALDIRILDI (2026-09-30)**, `data-table` ondan önce (2026-08-17). Katalogda tablo işi
991
+ > gören tek komponent `datatable`'dır. Eski bir sayfada `type: "table"` düğümü görürsen runtime
992
+ > onu `datatable` ile çizer (takma ad), ama o düğümün eski olayları (sayfalama, süzme, sıralama,
993
+ > seçim, çift tık, satır değişimi) ve eski prop'ları (satır seçim kipi, satır bazlı `_columns`
994
+ > ezmesi, `style.thead|th|tr|td`) artık karşılık bulmaz — kurulumu aşağıdaki sözleşmeye çevir.
995
+ >
996
+ > **Kayıt defterinde durmaya devam eder.** Eşitleme kaldırılan bileşeni silmez, gizler (silmek o
997
+ > tipteki kayıtlı düğümleri de silerdi): `component_list` onu yalnız `includeHidden: true` ile ve
998
+ > `retired: true` işaretiyle gösterir — henüz eşitlenmemiş bir ortamda gizlenmeden de listelenebilir —
999
+ > `component_get` eski şemayı `retired` notuyla döner ve PLATFORM o tipte düğümü kabul eder (runtime
1000
+ > `datatable` çizer, eski olaylara kurulan bağ kaydedilir ama ölü kalır). Gateway bu yüzden emekli tipte YENİ
1001
+ > düğümü **PAGE-051** ile istek gitmeden reddeder: `add_component`, `page_create` / `layout_create` /
1002
+ > `component_create` şeması ve `layout_patch`'in eklediği düğüm. O tiple kayıtlı düğüme yazan op'lar
1003
+ > (`replace_prop`, `move_component`…) ve tam şema yazan `page_update` geçer — eski sayfa düzenlenebilir
1004
+ > kalır; düğümü silip aynı tiple yeniden eklemek ise reddedilir. Kayıtlı `table` düğümüne olay
1005
+ > bağlarken `datatable`'ın olay adlarını yaz (`rowDoubleClick`): gateway adı onun listesinden denetler.
1006
+
1007
+ | Ne | Nasıl |
1008
+ |---|---|
1009
+ | Olaylar | 7: `mount · rowClick · rowDoubleClick · save · discard · rowSelectionChange · cellSelectionChange` |
1010
+ | Süzme / sıralama / sayfalama | komponentin İÇİNDE, ayrı olayı yok: `filters`/`sortField`/`sortType`/`offset` prop'larını (hidden) yazıp `mount`'u yeniden tetikler |
1011
+ | Satır | `rowClick` · `rowDoubleClick` ve satır aksiyonları (`actions`) tıklanan satırı `selectedRow`'a yazar (7b) |
1012
+ | Düzenleme | `editMode` (`none` · `row` · `cell` · `batch`); kayıt `save` olayıyla gelir (`self.operation` + `self.changeset`) |
1013
+ | Kolon biçimi | `isFilterable`/`isSortable`/`colorMap`/`prefix`/`suffix`/`precision`/`thousands`/`dateFormat`/`imageShape`, **`progress`** kolon tipi |
1014
+ | Görünüm | `title`, `locale` (tr/en), `tableStyle` (zebra/plain — satır zemini varyantı), **`style`** (parça bazlı CSS: `&__toolbar`/`&__title`/`&__head`/`&__th`/`&__body`/`&__row`/`&__td`) |
1015
+
1016
+ **Süzme/sıralama/sayfalamanın ayrı olayı olmaması eksiklik değil, tasarım.** Filtre paneli,
1017
+ sıralama ve sayfalama komponentin İÇİNDE: kullanıcı süzdüğünde/sıraladığında/sayfa değiştirdiğinde
1018
+ `datatable` önce kendi `filters`/`sortField`/`sortType`/`offset` prop'larını node'a yazar, sonra
1019
+ **`mount`'u yeniden tetikler** (`updateQuery` → `emitMount`). Yani tek bir `mount` akışı yazarsın;
1020
+ o akış tabloya bağlı uca bu prop'ları parametre olarak geçirir ve dönen satırları geri yazar
1021
+ (`ngapps://examples/flow-load-table`).
1022
+
1023
+ Süzme/sıralama sunucu taraflıdır: seçilen filtreler uca `filters` parametresi olarak gider ve
1024
+ ancak `enableDynamicFilters: true` olan bir uçta karşılık bulur
1010
1025
  (`platform_guide('microservice')`).
1011
1026
 
1012
- **Karar senin, dayatma yok.** Sorular:
1027
+ **Kurarken sorulacaklar:**
1013
1028
 
1014
- - *Kullanıcı bu listeyi ekrandan süzecek/sıralayacak mı?* Hayır ise ikisi de olur; en az kavramla
1015
- kurulanı seç ve `mount` akışı yeterlidir.
1016
- - *Süzme/sıralama var mı?* → `datatable` tek akışla kurar (daha az bağlama), `table` her olayı
1017
- ayrı akışa bağlamanı ister ama karşılığında satır seçimi (`rowSelection`), çift tık, hücre içi
1018
- düzenleme (`isEditable`) ve boş-durum aksiyonları verir.
1019
- - *Satır seçimi / çift tıkla forma geçiş / hücre düzenleme gerekiyor mu?* → **`table`**; bunlar
1020
- `datatable`'da yok.
1029
+ - *Kullanıcı bu listeyi ekrandan süzecek/sıralayacak mı?* Hayır ise kolonlarda
1030
+ `isFilterable`/`isSortable` açma; `mount` akışı yeterlidir.
1031
+ - *Satıra tıklayınca / çift tıklayınca bir şey olacak mı?* → `rowClick` / `rowDoubleClick` ya da
1032
+ satır aksiyonu (`actions`) — 7b.
1033
+ - *Hücre içi düzenleme gerekiyor mu?* → `editMode`; kaydı `save` akışı yazar, bağlı tabloda
1034
+ (Connect Data) runtime bağlantısı (`component_get('datatable')` → `knowledge`).
1021
1035
  - *Sayı/tarih/görsel biçimlendirme (para birimi öneki, ondalık, binlik ayracı, tarih formatı,
1022
- avatar şekli) gerekiyor mu?* → **`datatable`**; `prefix`/`suffix`/`precision`/`thousands`/
1023
- `dateFormat`/`imageShape` yalnız onun kolon şemasındadır, `table`'da yoktur.
1024
- - *Renk gerekiyor mu?* → **ikisi de yapar ama farklı şeyi.** `datatable`'ın `colorMap`'i
1025
- **statiktir**: hücrenin kendi değerine bakar; satır verisinde rengi taşırsan (`{ label, color }`)
1026
- dinamik de olur. `table` ise satır bazında **koşullu** renklendirir (`_columns` ezmesi,
1027
- Kural 1e-2). İkisinin de `style` prop'u vardır (datatable'ınki 2026-08-27'de eklendi), yani
1028
- renk uğruna stilden vazgeçmen gerekmiyor.
1029
- - *Hücrenin içinde ilerleme çubuğu ya da yüzde halkası mı istiyorsun?* → **`datatable`**, kolon
1030
- tipi `progress`. `progressVariant` çubuk/halka, `thresholds` yüzdeye göre renk, `captionField`
1031
- ise BAŞKA bir satır alanını çubuğun üstüne yazar — ad ve çubuk tek hücrede durur. `table`'da
1032
- böyle bir kolon tipi yok.
1033
-
1034
- **Bu, katalogdaki her komponent için geçerlidir:** hangi komponenti kullanacağını
1036
+ avatar şekli) gerekiyor mu?* → kolon şemasında `prefix`/`suffix`/`precision`/`thousands`/
1037
+ `dateFormat`/`imageShape`.
1038
+ - *Renk gerekiyor mu?* → Kural 1e-2.
1039
+ - *Hücrenin içinde ilerleme çubuğu ya da yüzde halkası mı istiyorsun?* → kolon tipi `progress`.
1040
+ `progressVariant` çubuk/halka, `thresholds` yüzdeye göre renk, `captionField` ise BAŞKA bir
1041
+ satır alanını çubuğun üstüne yazar — ad ve çubuk tek hücrede durur.
1042
+
1043
+ **Komponent seçimi sana aittir:** hangi komponenti kullanacağını
1035
1044
  `component_list`/`component_get` ile keşfedip kendin seçersin, rehberdeki örnekler tercih değil
1036
1045
  şablondur.
1037
1046
 
1038
- Kaçınılacak tek şey **yarım kurulum**: süzme arayüzünü açıp (`table` + `filterMode:'row'`, ya da
1039
- `datatable` + `isFilterable` kolonlar) arkasına statik filtreli uç bağlamak. Sayfa çalışır
1040
- görünür, kullanıcı süzer, hiçbir şey olmaz. Ya süzme arayüzünü kapat, ya ucu
1041
- `enableDynamicFilters: true` yap ve akışta `filters` parametresini geçir.
1047
+ Kaçınılacak tek şey **yarım kurulum**: süzme arayüzünü açıp (`datatable` + `isFilterable`
1048
+ kolonlar) arkasına statik filtreli uç bağlamak. Sayfa çalışır görünür, kullanıcı süzer, hiçbir şey
1049
+ olmaz. Ya süzme arayüzünü kapat, ya ucu `enableDynamicFilters: true` yap ve akışta `filters`
1050
+ parametresini geçir.
1042
1051
 
1043
1052
  > Komponenti sonradan değiştirmek pahalıdır: flow'un `setter` adımı hedefi kayıt anında
1044
1053
  > **DesignComponent id**'sine çözer (`StepIterate.component?.Id`), komponenti silip yeniden
1045
1054
  > eklersen elementId aynı olsa bile o bağ kopar ve flow'u yeniden kaydetmen gerekir. Tipi
1046
1055
  > baştan doğru seç.
1047
1056
 
1048
- ## Kural 1e-2 — Satır bazlı renk `table`'da: `_columns` ezmesi
1057
+ ## Kural 1e-2 — Satır bazlı renk: `colorMap` ve satır verisi
1049
1058
 
1050
- `table` her hücreyi çizerken **satırın kendi `_columns` sözlüğünü** kolon tanımıyla birleştirir
1051
- (`column-view.ts` `resolveColumn` → `Table.svelte:1207` `<TableCell {column}>`). Yani bir satır
1052
- kendi `appearance`/`isBold`'unu dayatabilir; renk, satırın herhangi bir alanından hesaplanır:
1059
+ `datatable`'da renk kolonun işidir ve çizim sırası **satır verisindeki `color` → `colorMap` →
1060
+ `autoColor`**'dır (`component_get('datatable')` → `knowledge.propNotes.colorMap`):
1061
+
1062
+ | istenen | yol |
1063
+ |---|---|
1064
+ | Değere göre sabit renk | `tag` kolonu + `colorMap`: `[{ value: 'Active', label: 'Aktif', color: 'success' }]` — hücrenin KENDİ değerine bakar, satırın başka alanına göre hesaplanamaz |
1065
+ | Satıra göre koşullu renk | hücre değerini `{ label, color }` nesnesi olarak yaz: renk satır verisinde taşınır |
1053
1066
 
1054
1067
  ```jsonc
1055
- // setter: rows'a yazmadan önce satırları zenginleştir
1068
+ // setter: rows'a yazmadan önce hücreyi { label, color } nesnesine çevir
1056
1069
  { "type": "change", "element": "tbl", "property": "rows", "source": "component",
1057
1070
  "mapping": { "source": "", "mappings": {} },
1058
- "value": { "type": "code", "ref": "(Steps.listele?.data || []).map(function (r) { return Object.assign({}, r, { _columns: [null, null, null, null, { appearance: r.durum === 'İptal' ? 'error' : 'success' }] }); })" } }
1071
+ "value": { "type": "code", "ref": "(Steps.listele?.data || []).map(function (r) { return Object.assign({}, r, { durum: { label: r.durum, color: r.durum === 'İptal' ? 'error' : 'success' } }); })" } }
1059
1072
  ```
1060
1073
 
1061
- **`_columns` bir DİZİDİR ve konum kolonun `columns` dizisindeki İNDEKSİDİR** — yukarıdaki dört
1062
- `null`, hedef kolon 5. sırada (indeks 4) olduğu için var; ezilmeyen kolonlar atlanır.
1063
- `buildViewColumns` `index`'i `isHidden` kolonlar elenmeden ÖNCE atar, yani **görünür sıra değil
1064
- tanım sırası**: gizli bir `id` kolonu indeksleri kaydırmaz, kullanıcının kolon menüsünden kolon
1065
- gizlemesi de kaydırmaz (`hideColumns` `buildViewColumns`'dan SONRA uygulanır).
1066
- Aynı kalıp `_actions[i]` ile satır bazlı **aksiyon** ezmesinde de çalışır (tek bir satırda "Sil"i
1067
- `{ "isHidden": true }` ile gizlemek gibi).
1074
+ Renk semantik ad (`primary · info · success · warning · error` — tema token'ına çözülür, tema
1075
+ değişince izler) ya da hex/rgb/CSS renk adıdır; temalarda `info` neredeyse beyazdır, mavi için
1076
+ `primary` yaz. `colorMap` satırının `mode: 'solid'`'i o değeri dolu zemin + beyaz yazıyla çizer.
1068
1077
 
1069
- > Sözleşme frontend'de belgeli ve testli: `column-view.ts` `resolveColumn` + `column-view.spec.ts`
1070
- > (`applies the row's own override fields on top`, `matches the override by the column definition
1071
- > order`). Ezilebilen alanlar `appearance` · `options` · `isBold`. CSV export'u da bu ezmeyi
1072
- > uygular, yani ekranda gördüğün renk dışa aktarımda da tutarlıdır.
1078
+ Satır bazlı `_columns` görünüm ezmesi `datatable`'da **yoktur** (kaldırılan tablonun özelliğiydi).
1079
+ Satıra göre değişebilen şey AKSİYONDUR: `rows[i]._actions[<aksiyon indeksi>] = { isHidden,
1080
+ isDisabled, text … }` o satırda aksiyonun üstüne biner; `actions[i].isHidden`/`isDisabled` bir kod
1081
+ ifadesi de olabilir (`{ "type": "code", "ref": "{{ !item.isCustomizable }}" }`, `item` = o satır) —
1082
+ Connect Data'ya bağlı tabloda satırlar `_actions` taşıyamadığı için tek yol budur.
1073
1083
 
1074
- İki renk yolu var:
1075
-
1076
- | istenen | yol |
1077
- |---|---|
1078
- | Hazır palet | `tag` kolonu + `appearance`: `primary · info · success · warning · error`; `_columns` ile satır satır değişir |
1079
- | Serbest hex | `tags` kolonu + satır verisinde `[{ "value": "kritik", "color": "#da1e28" }]` |
1080
-
1081
- **`style` yazarken iki ayrı kural geçerli:** `style.root` emotion'dır (camelCase çalışır, iç
1082
- seçici yazılabilir); `style.thead|th|tr|td` ise satır içi `style` attribute'una basılır
1083
- (`toStyleString` anahtarı olduğu gibi yazar) — bu dördünde **kebab-case zorunludur**, `fontSize`
1084
- sessizce düşer, `font-size` çalışır.
1085
-
1086
- > `datatable`'da `style` prop'u **yoktur** (ne şemada ne `.svelte`'de) ve `_columns` ezmesi de
1087
- > yoktur; `tableStyle` CSS değil `zebra`/`plain` varyantıdır. Tabloya CSS ya da koşullu satır
1088
- > rengi gerekiyorsa **`table`**.
1084
+ Tabloya CSS `style` prop'uyla yazılır (parça bazlı, camelCase; `designerCss` her bildirime
1085
+ `!important` ekler); `tableStyle` CSS değil `zebra`/`plain` varyantıdır.
1089
1086
 
1090
1087
  ## Kural 1f — Koordinat modeli ve layout-slot yerleşimi
1091
1088
 
@@ -1438,6 +1435,75 @@ düşer: sekme yığını kendi geçmişini tutar ve modal onu kırardı. `prese
1438
1435
 
1439
1436
  Web uygulamasında alan yok sayılır; gateway web profilinde bu konuda bulgu üretmez.
1440
1437
 
1438
+ ### `redirect.transition`
1439
+
1440
+ `redirect` adımının `args.transition` alanı hedef ekranın NASIL GİRDİĞİNİ söyler — `presentation`'ın
1441
+ yanındaki ikinci seçim, yalnız mobil. Kapalı küme:
1442
+
1443
+ - `default` — işletim sisteminin kendi geçişi
1444
+ - `none` — anında
1445
+ - `fade` — solarak
1446
+ - `slide` — yandan kayarak (iOS'ta sistemin geçişiyle aynı görünür)
1447
+ - `slideUp` — alttan kayarak
1448
+
1449
+ Öncelik: **adımın değeri → uygulamanın varsayılanı → sistem.** Alan yazılmamışsa adım uygulamanın
1450
+ varsayılanını kullanır: `application_update` `properties.mobile.transition` (aynı küme; `properties.mobile.tabs`'in
1451
+ yanındaki anahtar — `properties` yazılırken sekme ayarı da gönderilir, gövde REPLACE'tir). Adımda açıkça yazılmış
1452
+ `default` bir seçimdir ve uygulama varsayılanını ezer. Süre alanı yoktur.
1453
+
1454
+ - Küme dışı ADIM değerini backend 422 ile reddeder (iletisi kümeyi sayar); yazım gitmez. Küme dışı UYGULAMA ayarını
1455
+ backend doğrulamaz ve cihaz sessizce düşürür — onu söyleyen tek yer `application_create` / `application_update`
1456
+ yanıtındaki `platformWarnings`'tir (**MOB-029**).
1457
+ - **`modal` sunumda ve sekme hedefinde geçiş kullanılmaz:** modal sistemin kağıt animasyonuyla açılır, sekme
1458
+ hedefinde sekme değişir ve ekran itilmez. `modal` ile birlikte yazılırsa akış yazımının yanıtına MOB-029 bilgi notu
1459
+ düşer; sekme hedefi için not YOKTUR (lint sekme ayarını görmez) — hedef sayfanın sekme olup olmadığını
1460
+ `application_get` `properties.mobile.tabs.items`'tan kendiniz kontrol edin.
1461
+ - Geri dönüş (başlık çubuğunun geri düğmesi) aynı geçişin tersidir. iOS'ta kenardan geri kaydırma her geçişte
1462
+ sistemin yatay hareketidir.
1463
+ - "Hareketi azalt" açık cihazda seçilmiş geçiş oynamaz; `default` sisteme kalır.
1464
+ - `_transition` sorgu adı kabuğundur: `args.query` içinde bu adı kullanmayın — cihazda adrese yazılmaz ve sayfa onu
1465
+ `Page.queryParams`'ta görmez (web önizleme sorguyu olduğu gibi geçirir; iki yüzey bu adda ayrışır).
1466
+ - Geçiş TELEFONDA oynar. Web önizlemesi (`/dev`, `/preview`) yalnız GELEN sayfanın girişini oynatır — giden sayfa
1467
+ canlanmaz, `modal` ve sekme hedefinde giriş yoktur. `page_screenshot`'ın varsayılan karesi (`motion: 'frozen'`)
1468
+ "hareketi azalt"la alınır: giriş oynamaz, kare son hâli gösterir; `motion: 'play'` karesi girişin ortasına denk
1469
+ gelebilir.
1470
+
1471
+ Web uygulamasında alan yok sayılır; gateway web profilinde bu konuda bulgu üretmez.
1472
+
1473
+ ## Kural 1g-3 — Paylaşılan öğe: `heroTag` (liste satırındaki görselden açılan ayrıntı)
1474
+
1475
+ `heroTag` iki sayfada AYNI etiketi taşıyan iki düğümü çift yapar: kaynak sayfadaki öğeye dokunulup hedef sayfaya
1476
+ gidilince hedef sayfa o öğenin kutusundan **büyüyerek** açılır, geri dönüşte o kutuya küçülür. Sayfanın TAMAMI büyür
1477
+ (iOS'un yakınlaşma geçişi) — yalnız öğenin uçtuğu klasik Hero değildir. Alanı `image` ve `container` taşır
1478
+ (`component_get` → `propNotes.heroTag`).
1479
+
1480
+ Liste → ayrıntı, üç adım:
1481
+
1482
+ 1. **Kaynak:** satır şablonundaki `image`'a (ya da satırın kabına) `heroTag` yazın — `{ type: 'static', data: 'kapak' }`
1483
+ yeter. Satıra dokunmak (`repeater.itemPress`) satırdaki etiketli düğümden açar; dokunuşun görselin üstünde olması
1484
+ gerekmez. Liste dışında, `click`'i bağlı bir kabın içindeki etiketli düğüm de aynı kuralla kaynak olur. Satıra TEK
1485
+ etiket yazın: iç içe iki etiketli düğümde (kap ⊃ görsel) dokunuş ikisinin de dışındaysa içteki kaynak olur.
1486
+ 2. **Hedef:** ayrıntı sayfasında büyük görsele AYNI etiketi yazın. Sayfa ona hizalanarak açılır. Hedefte eş yoksa
1487
+ sayfa yine kaynaktan büyür, yalnız hizalanacak kutu olmaz.
1488
+ 3. **Gezinme:** bildiğiniz `redirect` adımı (`pageId`, `query`). Ek alan yok: etiketli öğeden çıkan itme (`push`) ve
1489
+ `modal` sunum yakınlaşır; sekme değişimi ve `replace` yakınlaşmaz.
1490
+
1491
+ - Etiketi satıra özgü yazmak GEREKMEZ (kaynak dokunulan satırdır). Hedef sayfada birden çok etiketli düğüm varsa
1492
+ doğrusunu ifade seçtirir: satırda `{{ 'urun-' + item.id }}`, hedefte `{{ 'urun-' + Page.queryParams.id }}`
1493
+ (`set_binding`). Hedef etiketini SORGU PARAMETRESİNDEN türetin: sonradan yüklenen veriye bağlı etiket ilk çizimde
1494
+ boştur, değer gelince düğüm yeniden kurulur ve `mount` akışları ikinci kez koşar.
1495
+ - **Yalnız iOS 18+ cihazda oynar.** Android'de, eski iOS'ta, `/dev` önizlemesinde, `page_screenshot`'ta ve kanvasta
1496
+ sayfa adımın geçişiyle açılır (`redirect.transition`). Yakınlaşma oynadığında adımın geçişi oynamaz. "Hareketi azalt"
1497
+ açıkken yakınlaşma yoktur. Dokunuşla başlamayan gezinme (zamanlayıcı, dokunuştan 10 sn sonra biten akış) yakınlaşmaz.
1498
+ - Hedef düğümün `motionStyle.enter`'ı oynamaz; hedef olmayan düğümlerinki oynar.
1499
+ - Aynı sayfada aynı statik etiketi iki düğüme yazmak KAYNAK sayfada olağandır (aynı etiketli kartlar). HEDEF sayfada
1500
+ hizalama kutusu tektir: ilk çizilen düğüm hizalanır — yazım bunu **MOB-030** bilgi notuyla söyler. Sayfalar arası
1501
+ eş arama yazımda yapılmaz (hedef sayfa henüz yazılmamış olabilir) ve eşi olmayan etiket için uyarı yoktur: iki
1502
+ sayfanın etiketlerini `page_runtime_get` özetindeki `heroTags`'ten (layout'unkiler dahil) karşılaştırın.
1503
+ - `_hero` sorgu adı kabuğundur (`_transition` gibi): `args.query` içinde kullanmayın.
1504
+
1505
+ Web uygulamasında alan yoktur.
1506
+
1441
1507
  ## Kural 1h — Tasarım: `style` prop'u ve tema değişkenleri
1442
1508
 
1443
1509
  Her komponentin `style` prop'u vardır ve emotion `css()` bloğudur: iç seçiciler, pseudo-class'lar
@@ -1460,12 +1526,6 @@ yapmanın yolu budur — ölçülmüş kurallar (anket-doldur, 2026-08-19):
1460
1526
  > düğümleri silip yeniden kurmaya, o da 20 setter'ın sessizce kopmasına yol açtı. Gateway artık
1461
1527
  > kebab-case anahtarı camelCase'e çevirir ve `gatewayNormalized` ile bildirir; seçici anahtarlara
1462
1528
  > (`&__body`, `:hover`, `--ng-*`) dokunmaz.
1463
- >
1464
- > **İSTİSNA — satır içi stil dalları (TB-129).** Kural `style` prop'unun emotion bloğu olan
1465
- > dalları içindir. `table.style.thead|th|tr|td` ise DOM'un `style` attribute'una string olarak
1466
- > basılır ve orada **kebab-case zorunludur**; gateway bu dört alanın altına 2026-09-20'den beri
1467
- > hiç dokunmaz (`INLINE_STYLE_FIELDS_BY_TYPE`). `table.style.root` ve öteki komponentler eskisi
1468
- > gibi çevrilir. Çeviri bu dalları da camelCase yapınca stil sessizce düşüyordu (S2-39).
1469
1529
 
1470
1530
  **1. Temayı tek yerden çevir: `page_container.style` içinde `--ng-*` değişkenlerini ez.**
1471
1531
  Runtime bütün renk/tipografi/form tokenlarını CSS değişkeni olarak basar
@@ -2175,7 +2235,7 @@ start → [setter] btn_save.isLoading = true
2175
2235
  > katalogla sınırlıdır** ama artık neredeyse her komponent tanımlıyor: **101 kaydın 99'u**
2176
2236
  > (ölçüm 2026-09-08; 2026-08-26'daki toplu ekleme öncesi 81'de 37 idi). Tanımlamayan yalnız
2177
2237
  > iki kap var: **`slot` · `widget-area`** — onların içindekini gizlemek için sarmalayıcı
2178
- > kullan. Eskiden tanımlamayan `text` · `table` · `datatable` · `dropdown` · `multi-select` ·
2238
+ > kullan. Eskiden tanımlamayan `text` · `datatable` · `dropdown` · `multi-select` ·
2179
2239
  > `tag-input` · `tabs` · `notification` · `toast` · `datepicker` ailesi gibi komponentlere
2180
2240
  > artık doğrudan `props.isHidden` yazılabilir; sırf gizlemek için `container`'a sarmak
2181
2241
  > GEREKMEZ. Tek doğru kaynak `component_get` + `page_schema_validate` kuru koşusudur.
@@ -2189,26 +2249,27 @@ start → [setter] btn_save.isLoading = true
2189
2249
 
2190
2250
  ### 7b — Liste → form geçişi
2191
2251
 
2192
- **Önce hangi tabloyu kullandığını bil — ikisi FARKLI kurulur:**
2252
+ Tablo `datatable`'dır (Kural 1e). Kaydı açmanın iki yolu var; ikisinde de tıklanan satır, akış
2253
+ koşmadan ÖNCE komponentin `selectedRow` prop'una **komponent tarafından** yazılır
2254
+ (`Table.svelte` → `setNode` + `onEmit`):
2193
2255
 
2194
- | | `table` | `datatable` |
2256
+ | Yol | Kurulum | Satır akışta |
2195
2257
  |---|---|---|
2196
- | Yaydığı olaylar | `mount` · `select` · `doubleClick` · `filter` · `sort` · `pagination` … | **yalnız `mount`** |
2197
- | Süzme/sıralama/sayfalama | her biri AYRI akışa bağlanır | komponent kendi prop'larını (`filters`/`sortField`/`sortType`/`offset`) yazıp `mount`'u yeniden tetikler → **tek akış yeter** |
2198
- | Satır seçimi / çift tık | var (`self.selectedRow`) | **YOK** — `doubleClick` bağlamak 200 döner ama bağ ölüdür (gateway PAGE-008 keser) |
2199
- | Kayıt açma | `doubleClick` akışı | satır **aksiyonu**: `actions: [{ text, kind, icon, flow: { type: 'flow', ref: <flowId> } }]` |
2200
-
2201
- `datatable` satır aksiyonunda tıklanan satır komponentin `selectedRow` prop'una **komponent
2202
- tarafından** yazılır, sonra akış çalışır (`Table.svelte:72` → `setNode` + `onEmit`): akışta
2203
- `<elementId>.selectedRow.<alan>` ile okunur. `actions[].kind` sözlüğü **butonunkinden farklıdır**
2258
+ | Satır olayı | `set_event` → `rowDoubleClick` (tek tık için `rowClick`) | `self.selectedRow.<alan>` |
2259
+ | Satır aksiyonu | `actions: [{ text, kind, icon, flow: { type: 'flow', ref: <flowId> } }]` | `<elementId>.selectedRow.<alan>` |
2260
+
2261
+ `rowClick` veri hücresine tıklamada yayılır; onay kutusu, ✏/🗑 ve aksiyon düğmeleri tetiklemez.
2262
+ `editMode` `none` DIŞINDAYKEN çift tık satırı ayrıca düzenlemeye açar — geçiş için `editMode: none`
2263
+ bırak ya da aksiyon kullan. `actions[].kind` sözlüğü **butonunkinden farklıdır**
2204
2264
  (`error · information · solid · transparent · dark · danger · warning`; butonda
2205
2265
  `success · error · info · primary · warning`) — yanlış sözlükten değer `invalid-enum-value` verir.
2266
+ Kaldırılan tablonun çift tık ve seçim olay adları `datatable`'da yoktur: bağlamak 200 dönüp ölü
2267
+ bağ bırakmaz, gateway PAGE-008 ile istek gitmeden reddeder.
2206
2268
 
2207
- Aşağıdaki `doubleClick` tarifi **`table`** içindir. Geçişi `redirect` yapar ve
2208
- **`query` bir İFADEDİR**:
2269
+ Geçişi `redirect` yapar ve **`query` bir İFADEDİR** (`ngapps://examples/flow-list-to-form`):
2209
2270
 
2210
2271
  ```jsonc
2211
- // satıra çift tıkla → edit ; self = tetikleyen komponent
2272
+ // satıra çift tıkla (rowDoubleClick) → edit ; self = tetikleyen komponent
2212
2273
  { "stepId": "go_edit", "type": "redirect", "kind": "normal",
2213
2274
  "args": { "pageId": "<form sayfası id>", "path": "departman",
2214
2275
  "query": "`id=${self.selectedRow.id}`" },
@@ -2216,7 +2277,7 @@ Aşağıdaki `doubleClick` tarifi **`table`** içindir. Geçişi `redirect` yapa
2216
2277
 
2217
2278
  // "Yeni" butonu → create (bağlamı taşıyarak; komponente ADIYLA erişim)
2218
2279
  { "args": { "pageId": "<form sayfası id>", "path": "departman",
2219
- "query": "table?.selectedRow?.id ? `parent=${table.selectedRow.id}` : ''" } }
2280
+ "query": "records_table?.selectedRow?.id ? `parent=${records_table.selectedRow.id}` : ''" } }
2220
2281
  ```
2221
2282
 
2222
2283
  Sayfalar arası veri geçmenin yolu budur: gönderen `query`'ye yazar, alan `Page.queryParams.<ad>`
@@ -2280,7 +2341,7 @@ bağlanır, filtre `source:'expression'` + `value:'user.id'` olur.
2280
2341
  | Tarih / saat / aralık | `datepicker` · `datetimepicker` · `daterangepicker` · `datetimerangepicker` · `timepicker` (yalnız HH:mm) |
2281
2342
  | Kimlik alanları | `textinput` (e-posta için `inputMask` Email hazır maskesi ya da `regex` kuralı — `email` diye bir bileşen YOK, `add_component` `unknown-type` ile reddedilir) · `password` |
2282
2343
  | Dosya | `fileUpload` (dropzone) · `fileInput` · `filebutton` · `file-viewer` |
2283
- | Liste | `table` · `datatable` (Kural 1e) · `repeater` (kart listesi VE dinamik form — Kural 1g) · `tree-view` (hiyerarşi; `isSearchable` ile istemci içi arama) · `timeline` (tarihli olay akışı) |
2344
+ | Liste | `datatable` (Kural 1e) · `repeater` (kart listesi VE dinamik form — Kural 1g) · `tree-view` (hiyerarşi; `isSearchable` ile istemci içi arama) · `timeline` (tarihli olay akışı) |
2284
2345
  | Pano / takvim | `kanban` (durum kolonlarında sürüklenebilir kartlar; taşıma `cardMove` ile `event.data`'dan okunur, kalıcılık AKIŞIN işidir) · `eventcalendar` (ay/hafta/gün/ajanda; veri `rows`'a akışla yazılır, `monthChange`/`viewChange` görünen `start`/`end` aralığıyla tazeleme kancasıdır) |
2285
2346
  | Kayıt detayı | `detailview` — tek kaydı etiket/değer ızgarası basar (alan başına format, iç içe alan yolu); OLAY YAYMAZ, tıklanabilirlik gerekiyorsa kapsayıcıya sar |
2286
2347
  | Adımlı akış | `stepper` — tabs gibi her adım kendi droppable görünümünü taşır; ileri gidiş `canProceed` kapısıyla (`{{ form1.isValid === true }}` biçimi), adım `currentStep` setter'ıyla sürülür |
@@ -2540,7 +2601,7 @@ micro-op hattına dönün.
2540
2601
  > 2026-09-20 öncesinde koruma her op'a tek başına baktığı için düğüm taşıyan her yama ikiye
2541
2602
  > bölünmek zorundaydı (S2-35). Akışı gerçekten referanssız bırakan yama hâlâ durur.
2542
2603
  >
2543
- > **Satır aksiyonları statik şemada görünmeyebilir (TB-126).** `table`/`datatable`'ın
2604
+ > **Satır aksiyonları statik şemada görünmeyebilir (TB-126).** `datatable`'ın
2544
2605
  > `actions[].flow` bağı `{ type: 'flow', ref }` olarak sayılır — ama bu prop'u çoğu zaman YÜKLEME
2545
2606
  > AKIŞI çalışma zamanında yazar (aksiyon role göre eklenip çıkarılıyorsa başka yolu da yok) ve o
2546
2607
  > hâlde şemada `actions` BOŞ durur. `flow_list` böyle bir barındırıcıda `unboundFlowIds` yanına
@@ -127,6 +127,32 @@ Son kullanıcı dili `language-selector` komponentiyle değiştirir (`platform_g
127
127
  prop'lar sayfa yenilenmeden yeniden çözülür — ayrı bir akış kurmana gerek yok, komponenti sayfaya
128
128
  eklemen yeterli. Projede dil tanımlı değilse (`languages` boşsa) liste boş çizilir.
129
129
 
130
+ **Akıştan dil (2026-10-14 frontend; uzak kurulumda dağıtımdan sonra):** kod adımında ve `{{ }}` bağında
131
+ `Page.language` etkin dil kodunu verir, `Page.setLanguage('en')` dili seçicinin yaptığı gibi değiştirir
132
+ (saklanır, bütün bağlar yeni dilde çözülür; projede olmayan kod yok sayılır). "Girişten sonra
133
+ kullanıcının kayıtlı diline geç" böyle kurulur — sayfayı yenilemek gerekmez. Seçicinin `self.value`'su
134
+ `mount`'ta boştur; dili okumak için `Page.language` kullan.
135
+
136
+ ## İfade başka komponentin çeviri bağlı prop'unu okuyunca
137
+
138
+ 2026-10-14 frontend'inden (uzak kurulumda dağıtımdan) sonra ifade, kod adımı, `self`, `Widget.x`, setter'ın
139
+ eleman kopyası ve uç argümanının Property kaynağı çeviriye bağlı prop'u **ekranda görünen metinle**
140
+ okur — iç içe dizilerdekiler dahil (`{{ menu.navigations }}` başlıklarla gelir, `drawer.actions.map(a =>
141
+ a.text)` düğme metinlerini verir). Akış okuduğu diziyi geri yazınca, yazılan metin o anki çeviriyle
142
+ aynıysa çeviri bağı korunur ve dil sonradan değişince o metin de değişir; farklı metin yazılırsa bağın
143
+ yerini o metin alır. Bu sürümden önceki kurulumda aynı okuma `null` verir (menü boş, geri yazılan düğme
144
+ yazısı kaybolur) — orada geri okunan diziyi çeviriye bağlama.
145
+
146
+ ## html şablonunda çeviri: `{{#t}}anahtar{{/t}}`
147
+
148
+ html bileşeninin `content`'inde `{{#t}}page.x.baslik{{/t}}` sözlükteki metni etkin dilde basar (zincir
149
+ ekrandakiyle aynı), HTML kaçışlıdır ve dil değişince yeniden çizilir. Bölümün içi önce çizildiği için
150
+ anahtar `context`'ten kurulabilir: `{{#t}}common.status.{{durum}}{{/t}}`. `context`'i akışlar baştan
151
+ yazsa da şablondaki metin etkilenmez — birden çok akışın doldurduğu html'deki sabit metni çevirmenin yolu
152
+ budur. Lambda yalnız `{{#t}}` geçen şablona eklenir; `context` kendi `t` alanını taşıyorsa o kazanır; markup taşıyan cümle yine `context` + `{{{…}}}` ile
153
+ basılır; datatable'ın `html` hücresi bu sözdizimini tanımaz. 2026-10-14 frontend'i (frontend ADR 0021),
154
+ uzak kurulumda dağıtımdan sonra.
155
+
130
156
  ## Kareyi ikinci dilde almak: `page_screenshot(language:)`
131
157
 
132
158
  Dil değiştirici **kanıt için gerekli değildir.** Runtime boot dilini şu sırayla seçer:
@@ -1,6 +1,6 @@
1
1
  {
2
- "hash": "1766032527c4215282c73fb003cbe3526babafabc8588b80289dc28fd4e8b393",
3
- "generatedAt": "2026-10-12T12:46:03.355Z",
2
+ "hash": "ba18a5111614d9b1e63e0d50f1a06a4dce1081b3d482c88e7620ca4bda9a466b",
3
+ "generatedAt": "2026-10-14T08:45:02.944Z",
4
4
  "types": 337,
5
5
  "files": 167,
6
6
  "note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
@@ -41,6 +41,9 @@
41
41
  },
42
42
  "choice": {
43
43
  "$ref": "#/components/schemas/NgApps.Domain.Contexts.Organization.Merges.MergeChoice"
44
+ },
45
+ "value": {
46
+ "$ref": "#/components/schemas/System.Text.Json.Nodes.JsonNode"
44
47
  }
45
48
  },
46
49
  "additionalProperties": false
@@ -48,10 +51,36 @@
48
51
  "NgApps.Domain.Contexts.Organization.Merges.MergeChoice": {
49
52
  "enum": [
50
53
  "source",
51
- "target"
54
+ "target",
55
+ "both",
56
+ "custom"
52
57
  ],
53
58
  "type": "string",
54
59
  "format": ""
60
+ },
61
+ "System.Text.Json.Nodes.JsonNode": {
62
+ "type": "object",
63
+ "properties": {
64
+ "options": {
65
+ "$ref": "#/components/schemas/System.Text.Json.Nodes.JsonNodeOptions"
66
+ },
67
+ "parent": {
68
+ "$ref": "#/components/schemas/System.Text.Json.Nodes.JsonNode"
69
+ },
70
+ "root": {
71
+ "$ref": "#/components/schemas/System.Text.Json.Nodes.JsonNode"
72
+ }
73
+ },
74
+ "additionalProperties": false
75
+ },
76
+ "System.Text.Json.Nodes.JsonNodeOptions": {
77
+ "type": "object",
78
+ "properties": {
79
+ "propertyNameCaseInsensitive": {
80
+ "type": "boolean"
81
+ }
82
+ },
83
+ "additionalProperties": false
55
84
  }
56
85
  }
57
86
  }
@@ -13,6 +13,8 @@ const activityKind = z.enum([
13
13
  'merge.applied_with_drift',
14
14
  'merge.discarded',
15
15
  'merge.failed',
16
+ 'merge.replanned',
17
+ 'merge.resolutions_carried',
16
18
  'deployment.started',
17
19
  'deployment.completed',
18
20
  'deployment.failed',
@@ -25,7 +27,7 @@ export function registerActivityTools(server, platform) {
25
27
  const config = platform.config;
26
28
  server.registerTool('activity_list', {
27
29
  title: 'Proje etkinlik günlüğü',
28
- description: "Projenin dal, merge ve dağıtım geçmişini en yeniden eskiye listeler: kim, ne zaman, ne yaptı. Her satırda kind, actor, actorSource (human|ai|system), occurredAt ve türe göre değişen bir summary vardır — merge.applied'da message ve counters, environment.created'da branchName, deployment.*'da süre ya da hata. subjectId merge satırlarında plan id'sidir; ayrıntı için merge_get ile okuyun. actorSource='ai' satırları bu gateway üzerinden yapılan işlerdir.",
30
+ description: "Projenin dal, merge ve dağıtım geçmişini en yeniden eskiye listeler: kim, ne zaman, ne yaptı. Her satırda kind, actor, actorSource (human|ai|system), occurredAt ve türe göre değişen bir summary vardır — merge.applied'da message ve counters, merge.resolutions_carried'da carried/dropped (tazelemede korunan ve yeniden sorulan karar sayısı), environment.created'da branchName, deployment.*'da süre ya da hata. subjectId merge satırlarında plan id'sidir; ayrıntı için merge_get ile okuyun. actorSource='ai' satırları bu gateway üzerinden yapılan işlerdir.",
29
31
  inputSchema: {
30
32
  projectId: guid,
31
33
  kind: activityKind,
@@ -2,6 +2,7 @@ import { guid, pagingParams, readOnly, writes, updates, destructive } from './co
2
2
  import { handle } from '../platform/responses.js';
3
3
  import { forgetApplication, readApplicationPlatform, resolveApplication } from '../knowledge/platform/resolve.js';
4
4
  import { mobileTabsProblems, readMobileTabs } from '../knowledge/platform/mobileTabs.js';
5
+ import { mobileTransitionProblems } from '../knowledge/platform/pageTransition.js';
5
6
  import { findingLine } from '../knowledge/platform/profile.js';
6
7
  import { listComponents } from './components.js';
7
8
  import { z } from 'zod';
@@ -37,6 +38,19 @@ export async function mobileTabsWarnings(platform, applicationId, projectSlug, h
37
38
  guide: "platform_guide('mobile') §Gezinme"
38
39
  }));
39
40
  }
41
+ /**
42
+ * MOB-029 (varsayılan sayfa geçişi) — `properties.mobile.transition` yazan mobil uygulama çağrısının denetimi.
43
+ * Yazım platforma YİNE gider (backend `properties`'i doğrulamaz); cihaz sözlük dışı değeri sessizce düşürdüğü için
44
+ * bulgunun söylendiği tek yer `platformWarnings`'tir.
45
+ */
46
+ export function mobileTransitionWarnings(properties) {
47
+ return mobileTransitionProblems(properties).map(message => findingLine({
48
+ code: 'MOB-029',
49
+ severity: 'warn',
50
+ message,
51
+ guide: "platform_guide('page') §Kural 1g-2"
52
+ }));
53
+ }
40
54
  function withPlatformWarnings(response, warnings) {
41
55
  if (warnings.length === 0 || !response || typeof response !== 'object' || Array.isArray(response))
42
56
  return response;
@@ -77,7 +91,7 @@ export function registerApplicationTools(server, platform) {
77
91
  annotations: writes
78
92
  }, handle(config, async ({ projectId, ...body }) => {
79
93
  const warnings = readApplicationPlatform(body.type) === 'mobile'
80
- ? await mobileTabsWarnings(platform, undefined, undefined, undefined, body.properties)
94
+ ? [...await mobileTabsWarnings(platform, undefined, undefined, undefined, body.properties), ...mobileTransitionWarnings(body.properties)]
81
95
  : [];
82
96
  const response = await platform.org('POST', `/applications/${projectId}`, { body });
83
97
  forgetApplication(platform);
@@ -100,7 +114,7 @@ export function registerApplicationTools(server, platform) {
100
114
  }, handle(config, async ({ id, ...body }) => {
101
115
  const current = await resolveApplication(platform, id);
102
116
  const warnings = current?.platform === 'mobile'
103
- ? await mobileTabsWarnings(platform, id, current.projectSlug, body.homepageId, body.properties)
117
+ ? [...await mobileTabsWarnings(platform, id, current.projectSlug, body.homepageId, body.properties), ...mobileTransitionWarnings(body.properties)]
104
118
  : [];
105
119
  const response = await platform.org('PUT', `/applications/${id}`, { body });
106
120
  forgetApplication(platform, id);