@appaflytech/zeyrek-ai-mcp 0.0.32 → 0.0.33

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 (167) hide show
  1. package/.env.example +15 -0
  2. package/dist/config.js +11 -0
  3. package/dist/index.js +2 -0
  4. package/dist/knowledge/access.js +802 -0
  5. package/dist/knowledge/case.js +41 -0
  6. package/dist/knowledge/componentCatalog.js +82 -213
  7. package/dist/knowledge/componentEvents.js +21 -19
  8. package/dist/knowledge/connectDataBind.js +819 -0
  9. package/dist/knowledge/connectDataDefinition.js +341 -0
  10. package/dist/knowledge/connectDataExecute.js +93 -0
  11. package/dist/knowledge/connectDataRules.js +128 -0
  12. package/dist/knowledge/decision.js +121 -0
  13. package/dist/knowledge/expressionPrelude.js +59 -0
  14. package/dist/knowledge/layoutSummary.js +140 -2
  15. package/dist/knowledge/microserviceParameters.js +58 -0
  16. package/dist/knowledge/mining.js +94 -0
  17. package/dist/knowledge/mobileComponentCatalog.js +864 -0
  18. package/dist/knowledge/mobileComponentEvents.js +239 -0
  19. package/dist/knowledge/mobileStore.js +227 -0
  20. package/dist/knowledge/normalize.js +121 -35
  21. package/dist/knowledge/platform/lint.js +385 -0
  22. package/dist/knowledge/platform/mobile.js +142 -0
  23. package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
  24. package/dist/knowledge/platform/mobileRules.js +231 -0
  25. package/dist/knowledge/platform/mobileSpacing.js +82 -0
  26. package/dist/knowledge/platform/mobileTabs.js +108 -0
  27. package/dist/knowledge/platform/nativeBoxModel.js +44 -0
  28. package/dist/knowledge/platform/profile.js +25 -0
  29. package/dist/knowledge/platform/resolve.js +122 -0
  30. package/dist/knowledge/platform/web.js +39 -0
  31. package/dist/knowledge/process.js +510 -0
  32. package/dist/knowledge/rowFilter.js +43 -0
  33. package/dist/knowledge/rules.js +291 -19
  34. package/dist/knowledge/styleResolve.js +55 -38
  35. package/dist/knowledge/styleResolveNative.js +527 -0
  36. package/dist/knowledge/themeResolve.js +3 -3
  37. package/dist/observability/trace.js +1 -1
  38. package/dist/platform/argumentAliases.js +128 -0
  39. package/dist/platform/bodyFile.js +103 -0
  40. package/dist/platform/capture/actions.js +333 -0
  41. package/dist/platform/capture/browser.js +1 -0
  42. package/dist/platform/{screenshot.js → capture/capture.js} +81 -519
  43. package/dist/platform/capture/console-log.js +122 -0
  44. package/dist/platform/capture/index.js +11 -0
  45. package/dist/platform/capture/readiness.js +103 -0
  46. package/dist/platform/capture/summary.js +77 -0
  47. package/dist/platform/capture/target.js +5 -0
  48. package/dist/platform/capture/targets/studio-mobile.js +15 -0
  49. package/dist/platform/capture/targets/studio-web.js +5 -0
  50. package/dist/platform/diagnostics.js +10 -4
  51. package/dist/platform/domSummary.js +1 -1
  52. package/dist/platform/http.js +23 -7
  53. package/dist/platform/impersonation.js +45 -0
  54. package/dist/platform/jsonArray.js +24 -0
  55. package/dist/platform/responses.js +6 -2
  56. package/dist/platform/schemaReadMemory.js +60 -0
  57. package/dist/platform/secrets.js +9 -0
  58. package/dist/platform/strictArguments.js +68 -12
  59. package/dist/platform/tokenVault.js +187 -4
  60. package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
  61. package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
  62. package/dist/resources/examples/bpm-satinalma.json +376 -0
  63. package/dist/resources/examples/connect-data-convert-verify.json +107 -0
  64. package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
  65. package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
  66. package/dist/resources/examples/connect-data-query-params.json +50 -0
  67. package/dist/resources/examples/connect-data-table-entity.json +147 -0
  68. package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
  69. package/dist/resources/examples/layout-app-shell.json +229 -707
  70. package/dist/resources/examples/mobile-app-shell-drawer.json +244 -0
  71. package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
  72. package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
  73. package/dist/resources/examples/mobile-form-screen.json +365 -0
  74. package/dist/resources/examples/mobile-list-detail-form.json +703 -0
  75. package/dist/resources/examples/page-flex-sections.json +1 -1
  76. package/dist/resources/guides/access.md +796 -0
  77. package/dist/resources/guides/bpm.md +686 -0
  78. package/dist/resources/guides/case.md +153 -0
  79. package/dist/resources/guides/component.md +10 -2
  80. package/dist/resources/guides/decision.md +185 -0
  81. package/dist/resources/guides/expressions.md +14 -5
  82. package/dist/resources/guides/functions.md +1 -1
  83. package/dist/resources/guides/layout.md +55 -58
  84. package/dist/resources/guides/microservice.md +9 -2
  85. package/dist/resources/guides/middleware.md +34 -2
  86. package/dist/resources/guides/mobile-layout.md +193 -0
  87. package/dist/resources/guides/mobile.md +578 -0
  88. package/dist/resources/guides/page.md +221 -92
  89. package/dist/resources/guides/theme.md +8 -2
  90. package/dist/resources/guides/translation.md +1 -1
  91. package/dist/resources/guides/workflow.md +7 -1
  92. package/dist/resources/read.js +41 -0
  93. package/dist/resources/schema-fingerprint.json +4 -4
  94. package/dist/resources/schemas/AccessExplanationDto.json +144 -0
  95. package/dist/resources/schemas/AccessMatrixDto.json +170 -0
  96. package/dist/resources/schemas/AccessPermissionDto.json +57 -0
  97. package/dist/resources/schemas/AccessPolicyDto.json +223 -0
  98. package/dist/resources/schemas/AccessResourceDto.json +86 -0
  99. package/dist/resources/schemas/AppSessionDto.json +53 -0
  100. package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
  101. package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
  102. package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
  103. package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
  104. package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
  105. package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
  106. package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
  107. package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
  108. package/dist/resources/schemas/DecisionDto.json +302 -0
  109. package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
  110. package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
  111. package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
  112. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +3 -1
  113. package/dist/resources/schemas/MicroserviceDto.json +2 -2
  114. package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
  115. package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
  116. package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
  117. package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
  118. package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
  119. package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
  120. package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
  121. package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
  122. package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
  123. package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
  124. package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
  125. package/dist/resources/schemas/StartMobileBuildCommand.json +54 -0
  126. package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
  127. package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
  128. package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
  129. package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +259 -0
  130. package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
  131. package/dist/server.js +7 -1
  132. package/dist/tools/accessOperations.js +135 -0
  133. package/dist/tools/accessPolicies.js +170 -0
  134. package/dist/tools/accessRuntime.js +203 -0
  135. package/dist/tools/applications.js +60 -3
  136. package/dist/tools/bpm.js +343 -0
  137. package/dist/tools/bpmGovernance.js +266 -0
  138. package/dist/tools/bpmOperations.js +230 -0
  139. package/dist/tools/bpmReporting.js +154 -0
  140. package/dist/tools/bpmRouting.js +150 -0
  141. package/dist/tools/bpmRuntime.js +396 -0
  142. package/dist/tools/case.js +178 -0
  143. package/dist/tools/caseRuntime.js +89 -0
  144. package/dist/tools/components.js +103 -12
  145. package/dist/tools/connectData.js +449 -0
  146. package/dist/tools/connectors.js +193 -0
  147. package/dist/tools/datasources.js +1 -1
  148. package/dist/tools/decisions.js +206 -0
  149. package/dist/tools/designSchemaPatch.js +22 -16
  150. package/dist/tools/externalComponents.js +25 -4
  151. package/dist/tools/flows.js +79 -6
  152. package/dist/tools/layouts.js +44 -12
  153. package/dist/tools/microservices.js +32 -10
  154. package/dist/tools/mobile.js +221 -0
  155. package/dist/tools/mobileStore.js +268 -0
  156. package/dist/tools/modules.js +48 -0
  157. package/dist/tools/organizationStructure.js +137 -0
  158. package/dist/tools/pages.js +391 -92
  159. package/dist/tools/platformInfo.js +7 -2
  160. package/dist/tools/profileWrite.js +92 -0
  161. package/dist/tools/rows.js +7 -1
  162. package/dist/tools/schemaOps.js +33 -1
  163. package/dist/tools/screenWrite.js +15 -7
  164. package/dist/tools/screens.js +90 -3
  165. package/dist/tools/variables.js +11 -5
  166. package/package.json +2 -2
  167. package/dist/knowledge/boxSections.js +0 -184
@@ -0,0 +1,153 @@
1
+ # Vaka Rehberi — CMMN 1.1 vaka yönetimi
2
+
3
+ Adımları önceden bilinmeyen işler içindir: müşteri şikâyeti, soruşturma, hasar dosyası, uygunsuzluk incelemesi. Süreç tanımı
4
+ (`process_definition_*`) sırayı çizer; **vaka** ise aşamaları, isteğe bağlı görevleri ve "şu olunca şu açılır" koşullarını
5
+ (sentry) tanımlar, sırayı olaylar ve kişiler belirler. İnsan görevleri süreç görevleriyle **aynı kutuya** düşer
6
+ (`kind: case-task`) ve `process_task_update` ile tamamlanır. Süreçten vaka `case` düğümüyle başlatılır (§Süreçten vaka).
7
+
8
+ Modüller: `case` (tanım: `case_definition_*`, `case_cmmn_*`) ve `caseRuntime` (`case_execute`, `case_instance_*`).
9
+
10
+ ## Başlangıç
11
+
12
+ 1. **Modeli yazın** — `case_definition_create { case }`. Taslak sürüm oluşur. Gateway yazmadan önce CASE-001'i denetler
13
+ (§Lint); `case_definition_preview { case }` aynı denetimi istek göndermeden yapar.
14
+ 2. **Yayınlayın** — `case_definition_publish { id }`. Çalışan vakalar başladıkları sürümde kalır; production'a yayın yok (BPM-001).
15
+ 3. **Başlatın** — `case_execute { slug, subjectRowId, caseFile, asUser }`. Yanıt `planItems[]` ve `availableActions[]` taşır.
16
+ 4. **Yürütün** — `case_instance_get` → `availableActions` → `case_instance_update { operation, planItemId }`; insan görevleri
17
+ `process_task_list` / `process_task_update`.
18
+
19
+ Düzeltmede tam modeli yeniden göndermeyin: `case_definition_get` → `case_definition_patch` (`/planItems[id=<öğe>]/…`).
20
+ Başka modelleyiciden gelen CMMN için `case_cmmn_update { filePath }`; dışa aktarma `case_cmmn_get { outPath }`.
21
+
22
+ ## Model
23
+
24
+ ```jsonc
25
+ {
26
+ "slug": "musteri-sikayeti", "name": { "tr": "Müşteri şikâyeti" }, "description": { "tr": "Şikâyeti inceler ve kapatır." },
27
+ "caseFile": [{ "id": "musteriCevabi" }, { "id": "oncelik", "default": "normal" }],
28
+ "planItems": [
29
+ { "id": "inceleme", "type": "stage", "required": true, "autoComplete": true },
30
+ { "id": "sikayeti-incele", "type": "human-task", "parent": "inceleme", "required": true, "assignee": { "rule": "user", "arg": "<kullanıcı id>" } },
31
+ { "id": "hukuk-gorusu", "type": "human-task", "parent": "inceleme", "discretionary": true, "assignee": { "rule": "role", "arg": "hukuk" } },
32
+ { "id": "yanit-alindi", "type": "milestone", "entry": ["musteri-cevapladi"] },
33
+ { "id": "kapanis", "type": "stage", "required": true, "manualActivation": true, "autoComplete": true, "entry": ["musteri-cevapladi"] }
34
+ ],
35
+ "sentries": [
36
+ { "id": "musteri-cevapladi",
37
+ "onParts": [{ "source": "inceleme", "event": "complete" }, { "source": "musteriCevabi", "event": "update" }],
38
+ "ifPart": "caseFile.musteriCevabi != 'yok'" }
39
+ ]
40
+ }
41
+ ```
42
+
43
+ | Alan | Kural (backend `CaseValidator`, hata 422 `CaseInvalid` + bulgu yolu `/planItems[id=x]/alan`) |
44
+ |---|---|
45
+ | `slug`, plan öğesi ve sentry `id` | kebab-case, benzersiz; ilk yayından sonra slug değişmez (400) |
46
+ | `caseFile[].id` | harf, rakam, alt çizgi; `default` herhangi bir JSON |
47
+ | `planItems[].type` | `stage` · `human-task` · `milestone` |
48
+ | `parent` | yalnız bir `stage`; döngü yasak. `parent` yoksa öğe vaka planının köküdür |
49
+ | `required` | aşama tamamlanmadan önce bitmesi gereken öğe; `disable` edilemez |
50
+ | `repeatable` | tamamlanınca yeni `occurrence` açılır; giriş sentry'si ister, kilometre taşında olmaz |
51
+ | `manualActivation` | koşul sağlanınca `enabled` olur, biri `start` edene kadar bekler |
52
+ | `discretionary` | tanımda durur, kişi `add-discretionary` ile ekleyene kadar oluşmaz |
53
+ | `autoComplete` | yalnız `stage`: etkin çocuk kalmayınca ve zorunlular bitince kendiliğinden kapanır |
54
+ | `assignee` | `human-task` için zorunlu: `user` (`arg` kullanıcı id), `role` (`arg` rol slug'ı, aday kaydı), `initiator` |
55
+ | `entry` / `exit` | sentry kimlikleri; girişlerden biri yeter, çıkış öğeyi ve alt ağacını `terminated` yapar |
56
+ | `onParts[].event` | kaynak kilometre taşıysa yalnız `occur`; başka plan öğesiyse `complete` · `start` · `terminate`; vaka dosyası öğesiyse `update` |
57
+ | `ifPart` | Jint; `caseFile.x` (ya da `vars.x`) vaka dosyasını, `initiator` başlatanı okur |
58
+
59
+ Süreç tanımındaki `assignee` sözlüğü (`unit-manager of …`, `position:`) vakada **yoktur**; yalnız üç kural.
60
+
61
+ ## Yaşam döngüsü
62
+
63
+ Plan öğesi: `available → enabled → active → completed | terminated | disabled`. Vaka: `active → completed | terminated`.
64
+
65
+ Her değişiklikten sonra platform yerleşimi sabitlenene kadar yeniden çalıştırır: çıkış sentry'si sağlanan öğe `terminated`;
66
+ ebeveyni etkin ve giriş koşulu sağlanan öğe `manualActivation` ise `enabled`, değilse etkin olur (insan görevi görev açar,
67
+ kilometre taşı doğrudan `completed`); kökteki her şey bitince vaka `completed`.
68
+
69
+ Aşama kapanışı **turun sonunda ve yalnız o turda başka hiçbir öğe hareket etmediyse** denenir — bir çocuk daha açılabiliyorken
70
+ aşama kapatılmaz. `autoComplete` aşama etkin çocuğu yokken ve zorunlu çocukları bitmişken kapanır, bekleyen çocuklarını
71
+ `terminated` eder. `autoComplete` **olmayan** aşama da kendiliğinden kapanır ama **bütün** çocukları terminal olmalıdır;
72
+ bekleyen çocuğu varken bekler ve onları terminale çekmez. Çocuğu olmayan aşama yalnız `autoComplete` ise kendiliğinden kapanır,
73
+ değilse elle `complete` bekler (elle `complete` her zaman gevşek koşulu kullanır: etkin çocuk yok + zorunlular bitmiş).
74
+
75
+ Sentry **durum tabanlıdır**: `onPart` kaynağın şu anki durumuna bakar (`complete`/`occur` → tamamlanmış, `start` → etkin ya da
76
+ tamamlanmış, `update` → vaka dosyası öğesi dolu) ve `ifPart` her turda yeniden çalışır. Bu yüzden vaka dosyasını değiştirmek
77
+ (`update-case-file`) bekleyen öğeyi açabilir.
78
+
79
+ ## Eylemler
80
+
81
+ `case_instance_get` yanıtındaki `availableActions[] { action, itemId, planItemId }` o an yapılabilecekleri listeler:
82
+
83
+ | `case_instance_update { operation }` | Ne yapar | Hata |
84
+ |---|---|---|
85
+ | `start` (`planItemId`) | `enabled` öğeyi başlatır | yanlış durum 409 `InstanceStateTransitionNotAllowed` |
86
+ | `complete` (`planItemId`) | etkin aşamayı kapatır (etkin çocuk yok, zorunlular bitmiş); insan görevi görev ucundan kapanır | 409 |
87
+ | `disable` (`planItemId`) | zorunlu olmayan `enabled` öğeyi devre dışı bırakır | 409 |
88
+ | `enable` (`planItemId`) | `available` öğeyi elle açar; giriş sentry'si **varsa** biri sağlanmalı (sentry'si olmayan öğe koşulsuz açılır) | sentry sağlanmıyorsa **422 `CaseSentryNotSatisfied`**, `available` değilse 409 |
89
+ | `add-discretionary` (`itemDefinitionId`) | isteğe bağlı öğeyi ebeveyn aşaması etkinken ekler | aynı öğenin bitmemiş örneği varsa 409 |
90
+ | `update-case-file` (`itemId`, `value`) | vaka dosyasına yazar, yerleşimi yeniden çalıştırır | tanımsız öğe 400 |
91
+
92
+ `enable` `availableActions`'ta **listelenmez**: yerleşim, giriş sentry'si sağlanan ya da hiç sentry'si olmayan öğeyi zaten açar,
93
+ dolayısıyla listede kalan `available` öğe sentry'sini bekliyordur ve ona `enable` 422 döner. Bu bir lint değil çalışma zamanı
94
+ kuralıdır — koşulu sağlamak için vaka dosyasını güncelleyin ya da kaynak öğeyi bitirin. Kapanmış vakada her değişiklik 409.
95
+
96
+ ## Görevler
97
+
98
+ `human-task` etkinleşince `ProcessTask` açılır: `kind: case-task`, `instanceId` = vaka kimliği, `nodeId` = plan öğesi `id`,
99
+ `definitionSlug` = vaka slug'ı. `user` ve `initiator` doğrudan atanır; `role` aday kaydı açar ve görev `claim` ister. Tamamlama
100
+ `process_task_update { action: complete, payload, asUser }` — plan öğesi `completed` olur, yük vaka defterine yazılır. Vaka
101
+ görevi süreç defterine yazmaz; görev yardımcısı (`process_task_get { view: 'assistant' }`) çalışır ama `ai-suggestion` satırı
102
+ yalnız öneri tablosuna düşer.
103
+
104
+ Görünürlük: vakayı başlatan, görevi atanan ya da tamamlayan kişi `case_instance_get` ile okur; liste (`case_instance_list`)
105
+ ve başkalarının vakaları `process.view-all` ister. Başlatma `process.start`, tanım yazımı `process.manage` ister.
106
+
107
+ ## Süreçten vaka
108
+
109
+ Süreç tanımında `case` düğümü yayındaki vakayı başlatır ve **beklemez** (akış devam eder):
110
+
111
+ ```jsonc
112
+ { "id": "sikayet-ac", "type": "case", "description": "Şikâyet vakasını açar.", "caseSlug": "musteri-sikayeti",
113
+ "input": { "musteriCevabi": "'yok'" }, "output": "vars.sikayetVakasi" }
114
+ ```
115
+
116
+ Başlatan süreç örneğinin başlatanı, iş satırı süreç konusudur; `output` yoluna vaka kimliği yazılır, süreç defterine
117
+ `case-started`. Bilinmeyen ya da yayınlanmamış slug tanım doğrulamasında `CaseUnknown`, çalışma anında düğüm hatası.
118
+
119
+ ## CMMN XML
120
+
121
+ `case_cmmn_get` CMMN 1.1 XML üretir (`zeyrek:` uzantısı atamayı, çok dilli ad/açıklamayı, varsayılanı ve sırayı taşır);
122
+ `case_cmmn_update { xml | filePath }` içe aktarır: aynı slug varsa taslağına yazar, yoksa yeni tanım açar. `stage`, `humanTask`,
123
+ `milestone` dışındaki öğeler (`processTask`, `caseTask`, olay dinleyicileri) ve DTD içeren XML 400'dür. Başka araçta
124
+ çizilmiş vakanın atamaları uzantı taşımıyorsa içe aktarma sonrası `case_definition_patch` ile ekleyin.
125
+
126
+ ## Lint
127
+
128
+ | Kural | Ne zaman | Önem |
129
+ |---|---|---|
130
+ | CASE-001 | `onParts[].source` bir plan öğesi ya da vaka dosyası öğesi değil; `entry`/`exit` tanımsız sentry'ye bakıyor | block |
131
+
132
+ Denetim `case_definition_create`, `case_definition_update`, `case_definition_patch`, `case_definition_publish` öncesinde ve
133
+ `case_definition_preview`'da çalışır. Diğer model kuralları backend'dedir (422 `CaseInvalid` bulgu listesi).
134
+
135
+ ## Hata sözlüğü
136
+
137
+ | Kod | Anlamı | Ne yapılır |
138
+ |---|---|---|
139
+ | `CaseInvalid` (422) | Model kuralı ihlali; `errors[]` yol ve mesaj taşır | yolu `case_definition_patch` ile düzeltin |
140
+ | `CaseSentryNotSatisfied` (422) | `enable` edilen öğenin giriş koşulu sağlanmıyor | kaynak öğeyi bitirin ya da `update-case-file` |
141
+ | `InstanceStateTransitionNotAllowed` (409) | öğe ya da vaka bu eyleme uygun durumda değil | `case_instance_get` ile `availableActions`'a bakın |
142
+ | `CaseUnknown` (422) | süreçteki `case` düğümü yayında olmayan vakaya bakıyor | vakayı yayınlayın |
143
+ | `ReferencedByProcess` (422) | silinen vaka tanımına bir süreç `case` düğümüyle başvuruyor | önce süreci güncelleyin |
144
+ | `InvalidOperation` (400) | vakası olan tanım silinemez | tanımı yerinde bırakın |
145
+
146
+ ## Sık tuzaklar
147
+
148
+ - **Sırayı vaka ile çizmek.** Adımlar belliyse süreç tanımı kullanın; vaka bekleme ve dallanmayı sentry'ye çevirir, okunması zorlaşır.
149
+ - **`enable`'ı düzeltme sanmak.** 422 aldıysanız koşul sağlanmamıştır; tekrar denemek değil koşulu sağlamak gerekir.
150
+ - **`repeatable` öğeyi giriş sentry'siz yazmak.** Model reddedilir; tekrar tetikleyicisiz sonsuz döngü olurdu.
151
+ - **Vaka görevini `case_instance_update { complete }` ile kapatmaya çalışmak.** `complete` yalnız aşama içindir; görev
152
+ `process_task_update` ile kapanır.
153
+ - **`caseFile` öğesini tanımlamadan `ifPart`'ta kullanmak.** Tanımsız değer `undefined` okunur; öğeyi `caseFile[]`'a ekleyin.
@@ -3,6 +3,11 @@
3
3
  Sayfaya konan her şeyin ortak kuralları. Kuruluş sırası ve şema gövdesi için
4
4
  `platform_guide('page')`; HTML kaçış kapısının derin sözleşmesi için `platform_guide('html')`.
5
5
 
6
+ > **Mobil uygulamada** katalog ayrıdır: `component_list`/`component_get` mobil satırları okur,
7
+ > `component_get` `mobileKnowledge` (bileşenin mobil farkları) ve `mobileNotes` ekler; katalogda
8
+ > olmayan tip `MOB-003` alır. Stil CSS değil React Native'dir — `page_runtime_get(resolveStyles)`
9
+ > `nativeStyle` döner (`platform_guide('mobile')`).
10
+
6
11
  ## Keşif: iki tool, üç bilgi katmanı
7
12
 
8
13
  ```
@@ -88,7 +93,10 @@ Widget, kendi komponent ağacını taşıyan yeniden kullanılabilir pakettir (`
88
93
 
89
94
  1. **Kayıt:** `component_create` — `kind:'widget'`, `widgetType`, `schema` (widget'ın kendi
90
95
  ağacı; `name = elementId` kuralı burada da geçerli — layout gibi widget adları da kullanan
91
- sayfaya sızar).
96
+ sayfaya sızar). Ağacın KÖKÜ tiplidir: `container` → `widget-area`, `modal`/`drawer` → kendi
97
+ tipi (+ düğümde `widgetType`). Runtime widget'ı yalnız bu kökten çizer; düz `container` kökle
98
+ kayıt 200 döner ama boş çizilir. Kök vermezsen gateway düğümlerini Studio'nun kurduğu köke
99
+ sarar ve `gatewayNormalized`'da CMP-002 ile bildirir (`component_update` şemada da aynı).
92
100
  2. **Sayfaya koyma:** `add_component` düğümünde `kind:'widget'` ve **`type` = widget KAYDININ
93
101
  ID'si** — slug DEĞİL (runtime widget'ı `widget.id === node.type` ile çözer; slug yazarsan
94
102
  kayıt 200 döner, render sessizce boş kalır — gateway **PAGE-012/LAY-005** ile reddeder).
@@ -108,7 +116,7 @@ Her şema düğümünde iki sözlük vardır; ikisi de ortak render katmanında
108
116
 
109
117
  | `states` | Anlamı |
110
118
  |---|---|
111
- | `isDroppable` | İçine komponent alır (container/form/repeater true) |
119
+ | `isDroppable` | İçine komponent alır (container/form/repeater true). **Değer kataloğun kararıdır** (`component_list` `droppable` sütunu): Studio kanvası bırakma hedefini bu alandan çözer, bu yüzden gateway yazdığı düğümlerde alanı katalogdan doldurur ve `gatewayNormalized` ile bildirir (PAGE-036). `false` yazılmış bir kabın içine kanvasta bırakma yapılamaz — bilerek kapatmak için `resize_component`/`set_states` |
112
120
  | `isScrollable` | İçeriği kendi alanında kaydırır (sabit yükseklikte `overflow-y: auto`) |
113
121
  | `isWrapper` | Sayfanın/layout'un/widget'ın ANA kabı — salt düzen elemanı: `height:100%` + **`min-height:80vh`**, kap başlığı ÇİZİLMEZ. **Yalnız sayfa boyu kaplaması gereken tek kap için kullan:** iç içe kutuya verirsen 720px'lik pencerede o kutu 36px içerikle bile 576px çizilir (ölçüldü, `platform_guide('page')` Kural 1f). Çerçeve/başlık gizlemek için wrapper değil `style` (`border:'none'`) kullan. Kurulmuş bir düğümün bayrağını `resize_component` micro-op'unun `states` alanı değiştirir — düğümü yeniden kurmak gerekmez |
114
122
  | `isSticky` | Kaydırmada yerinde kalır (header/sidebar; z-index'i otomatik) |
@@ -0,0 +1,185 @@
1
+ # Karar Rehberi — DMN karar tabloları
2
+
3
+ Eşik, seviye, oran, uygunluk gibi **kuralları süreç tanımından ayırır**: iş birimi tabloyu değiştirir, süreç
4
+ yeniden yayınlanmaz. Karar bir DMN 1.3 karar tablosu (`kind: table`) ya da tek bir FEEL ifadesidir
5
+ (`kind: literal`). Süreçte `decision` düğümüyle çağrılır; tek başına `decision_preview` ile değerlendirilir.
6
+ Karar **workflow değildir** (yan etkisi yoktur, veri okumaz — girdileri çağıran verir) ve **süreç değildir**
7
+ (beklemez).
8
+
9
+ ## Başlangıç
10
+
11
+ 1. **Tabloyu yazın** — `decision_create { decision }`. Taslak sürüm oluşur. Gateway yazmadan önce DMN-001 ve
12
+ DMN-002 denetimini çalıştırır (§Lint).
13
+ 2. **Deneyin** — `decision_preview { id, inputs }`. Her sınır değerini ayrı deneyin (§Deneme).
14
+ 3. **Yayınlayın** — `decision_publish { id }`. Motor yalnız aktif sürümü kullanır; production'a yayın yoktur
15
+ (BPM-001).
16
+ 4. **Süreçte kullanın** — `decision` düğümü (§Süreçte kullanım); tanımı `process_definition_preview` ile doğrulayın
17
+ (bilinmeyen `decisionSlug` → `DecisionUnknown`).
18
+
19
+ Düzeltmede tam modeli yeniden göndermeyin: `decision_get` → `decision_patch` (`/rules[id=<kural>]/…`).
20
+ Başka modelleyiciden (Camunda Modeler, Trisotech) gelen tablo için `decision_dmn_update { filePath }`.
21
+
22
+ ## Karar modeli
23
+
24
+ ```jsonc
25
+ {
26
+ "slug": "siparis-onay-limitleri", // tekil; yayından sonra değişmez
27
+ "name": { "tr": "Sipariş onay limitleri" },
28
+ "variable": "siparisOnayLimitleri", // üst kararların gördüğü ad; yoksa slug'daki '-' → '_'
29
+ "kind": "table", // table | literal
30
+ "hitPolicy": "unique", // §İsabet politikaları
31
+ "aggregation": null, // collect + tek çıktı: sum | min | max | count
32
+ "requires": [], // DRD: önce değerlendirilecek alt kararlar (slug)
33
+ "inputData": [], // { name, typeRef, source: "authority-limits", category }
34
+ "inputs": [
35
+ { "id": "tutar", "label": "Tutar", "expression": "tutar", "typeRef": "number" },
36
+ { "id": "kategori", "label": "Kategori", "expression": "kategori", "typeRef": "string", "allowedValues": "\"makine\", \"sarf\"" }
37
+ ],
38
+ "outputs": [
39
+ { "id": "seviye", "name": "seviye", "typeRef": "number", "allowedValues": "3, 2, 1", "defaultOutputEntry": "1" }
40
+ ],
41
+ "rules": [
42
+ { "id": "kucuk", "description": "10 binin altı", "inputEntries": ["< 10000", "-"], "outputEntries": ["1"] },
43
+ { "id": "orta", "inputEntries": ["[10000..100000)", "-"], "outputEntries": ["2"] },
44
+ { "id": "buyuk", "inputEntries": [">= 100000", "-"], "outputEntries": ["3"] }
45
+ ]
46
+ }
47
+ ```
48
+
49
+ - `inputEntries[i]` `inputs[i]`'nin **tekli testidir**, `outputEntries[j]` `outputs[j]`'nin **FEEL ifadesidir**.
50
+ Sütun sayısı eşleşmezse 422 `DecisionInvalid` (yol `/rules/{i}/inputEntries`).
51
+ - `inputs[].expression` girdinin bağlamdaki adıdır ya da ifadesidir (`siparis.tutar`, `tutar * 1.2`).
52
+ - Metin değerler FEEL'de **çift tırnaklıdır**: `"makine"`. Tırnaksız `makine` bir değişken adıdır ve `null` olur.
53
+ - `typeRef`: `number`, `string`, `boolean`, `date`, `time`, `dateTime`, `dayTimeDuration`,
54
+ `yearMonthDuration`, `list`, `context`. Dönüştürme yalnız metin girdiye uygulanır (`"2026-09-17"` → tarih).
55
+ - Literal karar: `{ "kind": "literal", "literalExpression": "tutar * oran", "typeRef": "number" }`.
56
+
57
+ ## İsabet politikaları
58
+
59
+ | Politika | Ne döner | Ne zaman |
60
+ |---|---|---|
61
+ | `unique` | En çok bir kural; ikisi eşleşirse 422 `DecisionHitPolicyViolated` | Kurallar kesin ayrık (varsayılan) |
62
+ | `any` | Eşleşenlerin çıktıları aynı olmalı, yoksa 422 | Aynı sonucu farklı yollardan veren kurallar |
63
+ | `first` | Kural sırasındaki ilk eşleşme | "Özel durum önce, genel en sonda" |
64
+ | `priority` | Çıktının `allowedValues` sırasına göre en yüksek (ilk yazılan) | Birden çok eşleşmede en katısı kazanır |
65
+ | `collect` | Eşleşenlerin listesi; `aggregation` ile tek sayı | Puanlama, kontrol listesi |
66
+ | `rule-order` | Eşleşenler kural sırasıyla | Sıralı öneriler |
67
+ | `output-order` | Eşleşenler `priority` sırasıyla | Önceliğe göre sıralı liste |
68
+
69
+ Tek çıktılı tabloda karar değeri çıktının kendisidir; çok çıktılıda `{ çıktıAdı: değer }`. Çok isabetli
70
+ politikada değer listedir. Hiç kural eşleşmezse `defaultOutputEntry` olan çıktılar varsayılanı alır, yoksa `null`
71
+ — `null` sonucu süreçte gateway koşulunu sessizce yanlış dala gönderebilir; ya varsayılan verin ya da son kurala
72
+ joker (`-`) koyup `first` kullanın.
73
+
74
+ ## FEEL
75
+
76
+ **Tekli testler** (`inputEntries`):
77
+
78
+ | Yazım | Anlamı |
79
+ |---|---|
80
+ | `-` ya da boş | her şey |
81
+ | `< 100` · `>= 5` | karşılaştırma |
82
+ | `[10..20)` · `]1..5]` | aralık; `[` `]` dahil, `(` `)` ya da ters köşe hariç |
83
+ | `"makine"` · `3` · `null` · `esik` | eşitlik (değer ya da bağlamdaki ad) |
84
+ | `"makine", "sarf"` | virgül = VEYA |
85
+ | `not("makine", "sarf")` | hiçbiri |
86
+ | `? > esik * 2` | `?` girdinin kendisi; ifade mantıksal döner |
87
+
88
+ **İfadeler** (`outputEntries`, `expression`, `literalExpression`): `+ - * / **`; `= != < <= > >=`;
89
+ `and`/`or` üç değerli (`true and null` → `null`); `x between 1 and 5`; `x in [1..5]`;
90
+ `if … then … else …`; `for x in liste return x * 2`; `some x in liste satisfies x > 3`; liste filtresi
91
+ `kalemler[tutar > 100]`, indeks `liste[1]` (1'den başlar), `liste[-1]` (son); yol `siparis.musteri.ad`; bağlam
92
+ `{ ad: "x", tutar: 5 }`; zamansal değişmez `@"2026-09-17"`, `@"P3D"`.
93
+
94
+ **Yerleşik işlevler** (tam liste; başkası DMN-002):
95
+ `date`, `time`, `date and time`, `duration`, `years and months duration`, `string length`, `substring`,
96
+ `substring before`, `substring after`, `upper case`, `lower case`, `contains`, `starts with`, `ends with`,
97
+ `matches`, `replace`, `string`, `number`, `not`, `list contains`, `count`, `sum`, `product`, `min`, `max`, `mean`,
98
+ `all`, `any`, `append`, `concatenate`, `flatten`, `reverse`, `distinct values`, `index of`, `get value`, `abs`,
99
+ `floor`, `ceiling`, `decimal` (yarıdan çifte yuvarlar), `modulo`, `sqrt`, `odd`, `even`.
100
+
101
+ Özellikler: tarihte `year month day weekday`, zamanda `hour minute second`, sürede `days hours minutes seconds`
102
+ ve `years months`, aralıkta `start end`.
103
+
104
+ **Yok:** `round up/down/half`, `sort`, `now()`/`today()` (bugünü girdi olarak verin), işlev tanımı, adlı
105
+ argüman, `instance of`, BKM çağrısı, saat dilimli zaman. Sözdizimi hatası 422 `ExpressionInvalid`; tür uyuşmazlığı,
106
+ sıfıra bölme ve tanımsız ad hata değil `null`'dır.
107
+
108
+ ## DRD ve girdi verisi
109
+
110
+ `requires: ["risk-skoru"]` alt kararı önce değerlendirir ve sonucunu `variable` adıyla (yoksa `risk_skoru`)
111
+ bağlama ekler; üst tablonun sütunu `{ "expression": "risk_skoru" }` olur. Döngü yayında 422 `DecisionInvalid`;
112
+ alt kararın aktif sürümü yoksa 422 `DecisionUnknown`. Silme: süreç başvuruyorsa 422 `ReferencedByProcess`,
113
+ başka karar `requires` ile başvuruyorsa 422 `DecisionInvalid`.
114
+
115
+ **Yetki limitleri:** `inputData: [{ "name": "limitler", "typeRef": "list", "source": "authority-limits",
116
+ "category": "makine" }]` — girdi verilmezse `process_authority_limit_list` satırları
117
+ `[{ subjectKind, subjectId, category, limit, currency }]` listesi olarak yüklenir. Tabloda
118
+ `count(limitler[limit >= tutar])` gibi kullanılır.
119
+
120
+ ## Süreçte kullanım
121
+
122
+ ```jsonc
123
+ { "id": "limit", "type": "decision", "description": "Onay seviyesini belirler",
124
+ "decisionSlug": "siparis-onay-limitleri",
125
+ "binding": "latest", // latest | deployed | "v:2" (sabit sürüm)
126
+ "input": { "tutar": "vars.tutar", "kategori": "row.kategori" }, // Jint; yoksa vars + row
127
+ "output": "vars.onay" } // yoksa her çıktı vars'a kendi adıyla
128
+ ```
129
+
130
+ Sonraki gateway'de `vars.onay.seviye >= 2` (çok çıktılı) ya da `vars.onay >= 2` (tek çıktılı). Değerlendirme
131
+ hatası örneği `faulted` yapar; `process_instance_get { view: 'timeline' }` → `decision-evaluated`
132
+ `{ decisionSlug, version, inputs, matchedRules, outputs }`. Tanım yayını karar yayınını beklemez ama motor
133
+ aktif sürüm ister: önce kararı yayınlayın.
134
+
135
+ ## Deneme
136
+
137
+ `decision_preview { id, inputs, version? }` yan etkisizdir; `version` yoksa taslak (yoksa aktif), alt kararlar da
138
+ taslak/son modelle çalışır. Yanıt `{ value, outputs, matchedRules, decisions[] }` — `decisions[]` DRD'deki her
139
+ kararın girdisini ve eşleşen kuralını gösterir.
140
+
141
+ Her kuralı en az bir kez tetikleyin ve **sınırları** ayrı deneyin: `[10000..100000)` için 9999, 10000, 99999,
142
+ 100000. Aralık uçlarındaki `[`/`)` hatası en sık kusurdur; DMN-001 bunu yakalamaz (§Lint).
143
+
144
+ ## DMN XML
145
+
146
+ - `decision_dmn_get { id, outPath? }` kararı ve alt kararlarını DMN 1.3 XML'e yazar; çok dilli ad, `kind`,
147
+ `variable`, `inputData` kaynağı `zeyrek:` uzantısıyla (`https://zeyrek.dev/dmn`) gidiş-dönüş kayıpsızdır.
148
+ - `decision_dmn_update { xml | filePath }` DMN 1.3/1.2/1.1 içe aktarır: `decision id` → slug (küçük harf),
149
+ var olan slug yeni taslak alır, yoksa oluşturulur; bir karar geçersizse hiçbiri yazılmaz. Kutulu bağlam/ilişki,
150
+ BKM ve DMNDI desteklenmez. İçe aktardıktan sonra `decision_preview` — başka motorun FEEL işlevleri (ör.
151
+ Camunda `round up`) içe aktarmada 422 ile reddedilir.
152
+ - Ortamlar arası taşıma: kararlar deployment/merge zincirinde **yoktur**; dışa aktarıp hedef dalda içe aktarın.
153
+
154
+ ## Lint
155
+
156
+ | Kural | Ne | Şiddet |
157
+ |---|---|---|
158
+ | DMN-001 | `unique` tabloda iki kural her girdi sütununda aynı testi ya da `-` taşıyor → aynı girdi ikisini eşler | block (istek gitmez) |
159
+ | DMN-002 | FEEL alt kümesinde olmayan işlev çağrısı | warn (istek gider; backend yazımı 422 ile reddeder) |
160
+
161
+ DMN-001 temkinlidir: yalnız **kesin** çakışmayı yakalar. `< 20` ile `< 10` ya da `[1..5]` ile `[5..9]` kesişir ama
162
+ yakalanmaz — `decision_preview` ile sınır değeri deneyin. Bilinçli istisna `policyOverride: true`.
163
+
164
+ ## Hata sözlüğü
165
+
166
+ | Kod | Anlamı | Ne yapılır |
167
+ |---|---|---|
168
+ | 422 `DecisionHitPolicyViolated` | unique/any tabloda çakışan kurallar (yanıtta kural kimlikleri) | Kuralları ayırın ya da politikayı değiştirin |
169
+ | 422 `ExpressionInvalid` | FEEL sözdizimi ya da bilinmeyen işlev (yol `/rules/{i}/…`) | §FEEL listesine bakın |
170
+ | 422 `DecisionInvalid` | Model hatası (sütun sayısı, politika, döngü) | Yoldaki alanı düzeltin |
171
+ | 422 `DecisionUnknown` | `requires` ya da süreç `decisionSlug`'ı aktif kararı bulamadı | Alt kararı yayınlayın |
172
+ | 422 `ReferencedByProcess` | Silinmek istenen karara süreç başvuruyor | Önce süreci değiştirin |
173
+
174
+ ## Sık tuzaklar
175
+
176
+ - **Tırnaksız metin:** `inputEntries: ["makine"]` değil `["\"makine\""]`. Tırnaksız ad bağlamda aranır, `null` olur ve
177
+ kural hiç eşleşmez.
178
+ - **Sayı metin geliyor:** satırdaki `"180000"` metni `number` sütunda karşılaştırılamaz; `typeRef: "number"` verin ya da
179
+ düğüm girdisinde `Number(row.tutar)`.
180
+ - **Boşluk bırakan aralıklar:** `< 10000` ve `(10000..100000)` → tam 10000 hiçbir kurala düşmez.
181
+ - **`null` sonuç:** eşleşme yoksa varsayılan yoksa `null` döner; süreçte koşul `vars.onay.seviye >= 2` `false`
182
+ olur, hata vermez.
183
+ - **Bugünün tarihi:** FEEL'de `today()` yok; süreç düğümü girdisinde `{ "bugun": "new Date().toISOString().slice(0, 10)" }`.
184
+ - **Taslakla çalıştığını sanmak:** `decision_preview` taslağı, süreç motoru aktif sürümü kullanır — yayınlamayı unutmak
185
+ "önizlemede doğruydu, süreçte eski sonuç" demektir.
@@ -14,8 +14,10 @@ Uydurma fonksiyon adı runtime'da `X is not defined` 500'üdür — yalnız bura
14
14
 
15
15
  **Değişkenler:** step çıktıları (`<stepAdı>.data`), middleware değişkenleri (`user`,
16
16
  `settings`, `permissions`… — `workflow_middleware_variables` ile keşfet), HTTP bağlamı:
17
- `cookie`, `header`, `queryString`, `body`, `triggerSource`/`context` (tetikleyen ucun
18
- type/name/roles/impersonatedUserId'ı). Gövde bir JSON **nesnesi** ise `body.alan` diye okunur,
17
+ `cookie`, `header`, `queryString`, `body`, `triggerSource` (tetikleyen ucun
18
+ type/id/name/slug/roles/pathAndQuery'si — emekliye ayrılacak) ve `context`
19
+ (type/name/roles/path/impersonatedUserId/language). **Kimlik devri yalnız `context.impersonatedUserId`**'dedir;
20
+ `triggerSource`'ta bu alan yoktur (MW-006). Gövde bir JSON **nesnesi** ise `body.alan` diye okunur,
19
21
  gövde bir JSON **dizisi** ise `body[0].alan` diye — 2026-09-04 öncesinde nesne gövde de diziye
20
22
  sarılıyordu ve `body.alan` sessizce `undefined` dönüyordu, bu yüzden gövdeye bakan yetki kapıları
21
23
  açık kalıyordu. Workflow'da istek girdisi `input.`, automation'da
@@ -97,14 +99,16 @@ dalından devam eder.
97
99
  |---|---|
98
100
  | `Page` | `Page.user`, `Page.variables`, `Page.components`, `Page.properties`, `Page.queryParams`, `Page.authorized(roles)` |
99
101
  | **Komponent adları** | Her komponent adıyla doğrudan değişkendir: `specialties_table.rows = data` hem prop'u yazar hem UI'ı günceller (change event). Addaki `-` silinir: `tickets-table` → `ticketstable` |
100
- | `state.page` / `state.app` | Kalıcı state (oku/yaz): `state.page.selectedId = row.id`. **Tanımlı değişkenler de buradadır:** `variable_create` ile yazılan her `key` sayfa düzeyinde `state.page.<key>`, uygulama düzeyinde `state.app.<key>` olur; `value` nesneyse alanlarına inilir (`state.page.MyTest.isActive`) |
102
+ | `state.page` / `state.app` | Sayfa/uygulama state'i (oku/yaz): `state.page.selectedId = row.id`. **Bellekte yaşar** — sayfa her açıldığında tanımlı `value`'dan başlar; mobil uygulamada kalıcı olması için değişkene `storage` verilir (`platform_guide('mobile')` §Kalıcı state). **Tanımlı değişkenler de buradadır:** `variable_create` ile yazılan her `key` sayfa düzeyinde `state.page.<key>`, uygulama düzeyinde `state.app.<key>` olur; `value` nesneyse alanlarına inilir (`state.page.MyTest.isActive`) |
101
103
  | `Steps` | Adım çıktıları: `Steps.load_specialties` — anahtar adımın **ADIdır**, `stepId` değil (`setStorage(task.name, …)`); `Steps.<adım>.error` o adımın hatası — ama YALNIZ HTTP durum metnidir (401 için `'Unauthorized'`), ucun mesajı değil. `Steps.error` ise hata akışı için doldurulur (`onError` koşmadan önce `setStorage('error', …)` yapar) ve **yalnız orada okunur**: storage sayfa başına tek `FlowMachine`'de yaşar, ama dışarıdan başlayan her akış başlarken `'error'`'u ve kendi adımlarının önceki değerlerini temizler (`flow-engine.ts` `run`, 2026-09-25) — normal akışta `Steps.error` boştur; hata akışı ve onun tetiklediği akış (`nested`) onu görür ve şekli `{ message, code, step: { id, name, type, data } }`'dir: kullanıcıya gösterilecek metin `Steps.error.message`'tır (`err.response.data.message`, boşsa durum metni). **Başarılı bir adımda `Steps.<adım>.data` gerçek bir `Array`'dir** — `.map` · `.filter` · `.concat` · `.length` çalışır. Adım HATA dönerse aynı alan ucun hata gövdesini taşır; aşağıdaki kutuya bakın |
102
- | `self` · `item` · `Row` / `RowIndex` | Tetikleyen komponent (yazılabilir) · repeater/tablo satırı (yazmak satırı günceller) |
104
+ | `self` · `item` · `Row` / `RowIndex` | Tetikleyen komponent (yazılabilir) · repeater/tablo satırı (yazmak YALNIZ o satırı günceller). Satır AKIŞINDA (satırdaki düğümün olayı) ARC-121 düzeltmesini (2026-09-27) taşıyan runtime gerekir, eskisinde boştu — sürümden bağımsız yol `<liste>.selectedItem` / `.selectedIndex`. Tekrarlayıcının KENDİ `change`/`select` akışında satır bağlamı yoktur. `item.x = …` yazımı tekrarlayıcının `change` olayı olarak iletilir: `change`'e bağlı akış her yazımda koşar, o akış da `item`'a yazarsa döngü olur |
103
105
  | `event` | `{name, data, source: {id, props}}` |
104
106
  | `cookie` | `cookie.get(name)` / `cookie.set(name, value, {expiresInHours, path})` / `cookie.remove(name)` — tarayıcı cookie'si |
105
107
  | `setComponentProperty(name, key, value)` / `getComponentProperty(name, key)` | fonksiyon alternatifi |
106
108
  | `resetForm(name)` | Formu sıfırlar: alanlar başlangıç değerine döner, form "gönderilmemiş" olur, doğrulama mesajları silinir. Kayıt sonrası "yeni kayıt" için alanları tek tek `null`'a çekme — gönderilmiş formda her biri "zorunlu alan" mesajı çıkarır. Ad ya da komponent değişkeni alır: `resetForm('risk_form')` / `resetForm(risk_form)`. **Yalnız UI flow kodunda** |
107
- | `LocalStorage` · `Widget` · `params` | yerel veri · widget bağlamı · olay parametreleri |
109
+ | `LocalStorage` · `Widget` · `params` | yerel veri · widget bağlamı · olay parametreleri. `LocalStorage` barındırıcının deposudur, salt okunur ve değerler METİNdir: web'de uygulamanın kökenindeki `localStorage` (Studio önizlemesinde Studio'nun kendi anahtarları da görünür), cihazda akışın `storage` deposu. `storage` adımı düz bir anahtara yazınca `LocalStorage.<anahtar>` aynı akışta yeni değeri verir ve sayfanın bağları yeniden değerlendirilir (`isSelected: {{ LocalStorage['zeyrek:theme-mode'] === 'dark' }}`). `state.page\|app.<key>`'e yazan adım `LocalStorage`'a girmez (ARC-147, 2026-09-29) |
110
+ | `Device` | Salt okunur cihaz durumu, barındırıcı günceller: `Device.isOnline` — ağ bağlantısı var mı (bilinmiyorsa `true`). Değişince sayfanın bütün bağları yeniden değerlendirilir; çevrimdışı bandı: `isHidden: {{ Device.isOnline }}`. Cihazda `expo-network`, web'de tarayıcının `online`/`offline` olayları. `Device` adında komponent ifade bağlamından süzülür (ayrılmış ad) |
111
+ | **Ayrılmış adlar** | Bu tablodaki globallerle (ve önsözün iç adlarıyla: `payload`, `error`, `repeaterId`, `_` ile başlayanlar…) aynı `name`'i taşıyan komponent (runtime yalnız İLK `-`'yi siler: `ite-m` da `item` sayılır) ifadede kendi adıyla GÖRÜNMEZ — süzülür, uyarı loglanır (liste: `@ng-apps/flow` `EXPRESSION_PRELUDE_NAMES`). Eskiden aynı ad sayfanın BÜTÜN ifadelerini `SyntaxError`'la düşürürdü (ARC-143). Gateway artık bu adların HEPSİNİ **PAGE-009** ile sayfa/layout yazma yollarında ve `page_schema_validate`'te istek gitmeden reddeder — komponente `t`, `state`, `event`, `item`, `self`, `Page`, `Row` gibi ad verme |
108
112
  | `t(key)` | Çeviri anahtarını çözer: aktif dil → projenin varsayılan dili → anahtarın kendisi. Boş string de "eksik" sayılır. Sözlük `machine.context.state.translations`'tan gelir; dil `language-selector` ile değişince bir sonraki çağrı yeni dili görür. **Yalnız UI flow kodunda vardır** — backend ifadelerinde karşılığı `Loc()`'tur (`platform_guide('workflow')`) | `t('home.welcome')` |
109
113
  | `log(...)` | console (proxy'leri temizler) |
110
114
  | `Functions` | **Kullanıcı fonksiyonları** (`function_create`): `Functions.toplamHesapla(fiyat, adet)` — uygulama kapsamlılar her sayfada, sayfa kapsamlılar yalnız kendi sayfasında. **Yalnız tarayıcı**; sunucuda bu ad alanı yoktur (2026-09-10, `WF-030`) |
@@ -125,6 +129,11 @@ dalından devam eder.
125
129
  > `runtimeErrors` taşır ve hangi komponentin hangi prop'unun yazılamadığını (`element` ·
126
130
  > `property`) söyler. Aynı defter hata dönen microservice adımlarını da kaydeder. **Kare
127
131
  > "çalışıyor" görünse bile `runtimeErrors` doluysa o adımlar işini YAPMAMIŞTIR.**
132
+ >
133
+ > **Prop'a bağlı ifade patlarsa** (Studio'da "Expression error" toast'ı) `page_screenshot` yanıtı
134
+ > `expressionErrors` taşır: `{ elementId, prop, expression, message, count }`, öğe başına en çok iki.
135
+ > Toast da öğeyi adlandırır (`Expression error · tx_baslik.content`); cihazda geliştirme paketi aynı
136
+ > satırı Metro günlüğüne basar (ZM-05).
128
137
 
129
138
  **Prop'a doğrudan ifade bağlama (`{{ }}`):** akış kurmadan bir prop'u ifadeye bağlamak için
130
139
  prop `type: 'code'` olur, **ifade `ref` alanına `{{ }}` içinde** yazılır, `data` tasarım zamanı
@@ -273,7 +273,7 @@ toplamHesapla(row.fiyat, row.adet) > 1000
273
273
  serbesttir — sunucuda o ad alanı yok.
274
274
  - **Önekli hata:** gövde hatası `Functions.<ad>: <mesaj>` (studio) ya da `<ad>: <mesaj>` (workflow)
275
275
  olarak gelir; `Steps.<adım>.error.message` ya da `runtimeErrors`'ta bu öneki ara.
276
- - **Mobil yok** (K11): `apps/mobile` runtime'ı `Functions`'ı boş nesne kurar.
276
+ - **Mobil uygulama:** mobil runtime (`@ng-apps/ui-native`) `appFunctions`/`pageFunctions`'ı `Functions`'a geçirir, çağrı web'deki gibi çalışır.
277
277
  - **Önbellek:** `/view` yolu eski gövdeyi birkaç saniye gösterebilir; `/dev` yolu anlıktır.
278
278
  - **Parametre konumsal:** `parameters` sırasını değiştirmek mevcut çağrıların anlamını değiştirir;
279
279
  `function` adımları ada göre eşlendiği için etkilenmez.
@@ -4,6 +4,10 @@ Sayfaların paylaştığı kabuk: yan menü, üst şerit, kullanıcı menüsü v
4
4
  gireceği delik. Şema gövdesi ve koordinat modeli için `platform_guide('page')` (Kural 1,
5
5
  1d, 1f); komponent sözleşmeleri için `platform_guide('component')`.
6
6
 
7
+ > **Mobil uygulamada** kabuk `app-bar` + tek `slot`'tur; sekmeler uygulama ayarı
8
+ > (`properties.mobile.tabs`), çekmece `drawer` widget'ıdır. Web kabuk bileşenleri (`navigations`,
9
+ > `sidebar`, `header`) `MOB-004` alır — `platform_guide('mobile')` §Gezinme.
10
+
7
11
  ## Karar kuralları
8
12
 
9
13
  **1. Layout, tek `slot` içeren SIRADAN bir komponent ağacıdır.** Ayrı bir dil yoktur:
@@ -39,20 +43,16 @@ göre kurmaktır. `version` bir **string**tir (mikrosaniye zaman damgası) — s
39
43
  **4. TEK slot.** Sayfa şeması **her** slot'a ayrı ayrı kopyalanır — iki slot, sayfayı iki
40
44
  kez çizer ve `elementId`'leri tekrarlar. (LAY-002 / LAY-006)
41
45
 
42
- **5. VARSAYILAN kabuğu kullan, sonra özelleştir (2026-09-29).** Yeni bir layout kurarken
43
- önce `ngapps://examples/layout-app-shell` örneğini `layout_create`'in `views` alanına olduğu
44
- gibi ver — Studio'da "New layout" ile açılan iskeletin birebir aynısıdır (aşağıdaki mini
45
- tarif). Sonra uygulamaya göre değiştir: menü öğeleri ve `href`'leri, başlık, ikonlar;
46
- gerekmeyen parçayı (arama, yardım, bildirim) sil. Kullanıcı açıkça başka bir kabuk isterse
47
- sıfırdan kur. Kabuk sıradan bileşenlerden oluşur: `container` + `navigations` + `icon` +
48
- `slot`. `layout` monoliti (sabit logo/menü/kullanıcı bandı — yalnız doldurulur) ve
49
- `layout-shell` + `layout-region` ikilisi **emekliye ayrıldı**; kayıtlı kalırlar ve mevcut
50
- layout'lar çalışır, ama yeni kabukta kullanılmaz — Studio iskeleti de artık onları kurmaz.
51
-
52
- **5a. Kök, sayfanın `page_container`'ının yerleşim ikizidir.** Varsayılan kabuk kökü şöyle
53
- kurar ve sen de aynısını yazmalısın: `states.isWrapper: true` (çerçevesiz, başlıksız,
54
- saydam) + `appearance.heightType: 'fill'` + `blocks` x0/w12. Sarmalayıcı olmayan bir kök,
55
- kenarlıklı beyaz bir kart olarak çizilir.
46
+ **5. Kabuğu `container` + `slot` ile kur.** `layout` monoliti (sabit logo/menü/kullanıcı
47
+ bandı — yalnız doldurulur) ve `layout-shell` + `layout-region` ikilisi **emekliye
48
+ ayrıldı**; kayıtlı kalırlar ve mevcut layout'lar çalışır, ama yeni kabuk `container` ile
49
+ kurulur. Sebebi: `container` zaten `layout-region`'ın yaptığının üstünü yapıyor (flex/ızgara
50
+ düzeni, hizalama, gap, wrap), region'ın kattığı tek şey `dock` sözlüğüydü.
51
+
52
+ **5a. Kök, sayfanın `page_container`'ının yerleşim ikizidir.** Studio'nun yeni layout
53
+ iskeleti (`getDefaultLayout`) tam olarak şunu kurar ve sen de aynısını yazmalısın:
54
+ `states.isWrapper: true` (çerçevesiz, başlıksız, saydam) + `appearance.heightType: 'fill'`
55
+ + `blocks` x0/w12. Sarmalayıcı olmayan bir kök, kenarlıklı beyaz bir kart olarak çizilir.
56
56
 
57
57
  **5b. Tam ekran kabuk `heightType: 'fill'` ile kurulur (2026-08-28).** Yükseklik ne
58
58
  içerikten (`auto`) ne satır sayısından (`fixed`) gelir — ebeveynin bıraktığı yerden gelir:
@@ -65,7 +65,7 @@ yapılan eski numaraya artık gerek yok.
65
65
  NEREDE durduğunu değil, BİÇİMİNİ söyler (dikey kolon / yatay şerit / dolgu yüzeyi). Hem
66
66
  runtime hem Studio tuvali bölgeleri 12 kolonluk ızgarayla yerleştirir.
67
67
 
68
- **7. Mobilde flex YIĞILMAZ.** Runtime'ın mobil kuralı yalnız ızgara özelliklerini ezer.
68
+ **7. Dar ekranda flex YIĞILMAZ.** Runtime'ın dar ekran kuralı yalnız ızgara özelliklerini ezer.
69
69
  Telefonda alt alta düşmesi gereken satırı `layout:'grid'` ile kur; `layout:'flex'` +
70
70
  `direction:'row'` telefonda da yan yana kalır (375px'te ölçüldü: ızgara çocukları 375/375px
71
71
  alt alta, flex çocukları 49/310px yan yana). Not: `wrap` varsayılanı artık açık (2026-09-01) —
@@ -76,48 +76,45 @@ yana kalmaya devam eder.
76
76
  gerçek çıktıyı, layout'a bağlı bir sayfanın runtime paketinde görürsün (slot yerleşimi
77
77
  dahil). Slot kurgusu için ayrıca `page_state` → `layoutSlots`.
78
78
 
79
- ## Mini tarif — uygulama kabuğu (VARSAYILAN)
79
+ ## Mini tarif — uygulama kabuğu
80
80
 
81
- Sol menü + üst şerit + ortada boş içerik alanı ve slot. Studio'nun `getDefaultLayout`
82
- iskeletiyle birebir aynı ağaç; `layout_create`'in `views` alanına doğrudan verilebilir
83
- (`resource: layout-app-shell`).
81
+ Yan menü + üst şerit + içerik. Studio'nun `getDefaultLayout` iskeletiyle birebir aynı ağaç;
82
+ `layout_create`'in `views` alanına doğrudan verilebilir (`resource: layout-app-shell`).
84
83
 
85
84
  ```
86
- container shell_root isWrapper · fill · flex row · gap none · stretch
87
- └ navigations shell_menu layout:'sidebar' · fill · başlık + menüde arama + daraltma
88
- └ container shell_main fill · flex column · wrap:false · center · zemin surface-alt · taşma gizli
89
- ├ container shell_topbar fixed 64px · flex row · stretch/middle · wrap:false · alt çizgi
90
- │ ├ navigations shell_crumbs layout:'breadcrumb' · 30px · fill
91
- │ ├ navigations shell_search layout:'command' · 393px × 36px · "Sayfa ara…"
92
- │ ├ icon shell_help help · tooltip "Yardım"
93
- │ └ icon shell_bell notifications · tooltip "Bildirimler"
94
- └ container shell_content fill · isScrollable · isWrapper · dolgu 28/32/32/32
95
- └ container shell_page fill · en fazla 1600px · ortalı
96
- └ slot shell_slot fill
85
+ container isWrapper:true heightType:'fill' layout:'flex' direction:'row' gap:'none'
86
+ │ verticalAlign:'stretch' block w12 x0
87
+ ├ container heightType:'fill' layout:'flex' direction:'column' block w2 ← yan menü
88
+ │ └ navigations block w12
89
+ └ container heightType:'fill' layout:'flex' direction:'column' block w10 x2
90
+ ├ container layout:'flex' direction:'row' states.isSticky block w12 h6
91
+ │ └ breadcrumb block w12 h3
92
+ └ slot heightType:'fill' block w12 y6
97
93
  ```
98
94
 
99
- - **Menü bir kaptır.** `navigations` droppable'dır ve içine bırakılanı KENDİ YANINA çizer:
100
- `shell_main` kökün değil menünün çocuğudur. Ana sütunu köke kardeş koyarsan satıra
101
- sığmaz ve menünün altına sarar (ölçüldü 2026-09-29).
102
- - **Tek menü, üç görünüm.** Menü, kırıntı yolu (`layout:'breadcrumb'`) ve arama
103
- (`layout:'command'`) AYNI `navigations` ağacını taşır; kırıntı aktif sayfanın yolunu, komut
104
- paleti sonuçları bu ağaçtan çıkarır. Menüyü değiştirirken üçünü birlikte güncelle.
105
- - **Örnek menü adressizdir.** Öğelere `href` olarak sayfa slug'ı ya da `{ page: '<id>' }` ver;
106
- başlıkları ve ikonları uygulamanın diline göre değiştir. Menü başlığı (`title`) uygulamanın
107
- adıdır. Renkler tema token'ıdır (`var(--ng-text-primary)` …) — sabit hex yazma, koyu temada
108
- okunmaz.
109
- - **Yerleşim prop'larını açıkça yaz.** `layout_create` katalog varsayılanlarını düğüme
110
- yazmaz: `layout` prop'u olmayan `container` ızgara çizer. Örnekte her kapta
111
- `layout:'flex'` + yön/hizalama/gap/wrap yazılıdır; kapatılan bayrak da (`wrap:false`,
112
- `crumbSiblings:false`) açıkça yazılır.
113
- - **Yükseklik `fill`'dir**, `size.h` değil: kök ekranı doldurur, menü ve ana sütun kökün
114
- bıraktığını, içerik alanı üst şeritten artanı, slot da içerik alanını alır. İçerik alanı
115
- `isScrollable` olduğu için uzun sayfa kabuğu itmez, içeride kaydırır.
116
- - **Menü satırlarını biçimlendirme:** `navigations`'ın tipli grupları ve renk prop'ları
117
- (`textColor`, `mutedColor`, `iconColor`, `bgColor` …) — bkz. `component_get('navigations')`.
118
- - **Mobil:** menü ≤768px'te kendi çekmecesine ve hamburger düğmesine döner (bağımsız
119
- `navigations`'ta `mobileBehavior:'drawer'` varsayılandır); üst şerit ve içerik tam genişliğe
120
- yayılır.
95
+ - **Genişlik `appearance.widthType`'tan gelir (2026-09-01); kolon payı fallback'tir.**
96
+ Yan menü için `widthType: 'fixed'` + `widthString: "240px"` (serbest CSS uzunluğu:
97
+ `"50%"`, `"10vw"`, `calc(...)` de geçer; yalnız flex kabın çocuğunda okunur, mutlak
98
+ ızgara kabında okunmaz). `'fill'` kabın tüm genişliğini alır, `'auto'` içeriğe oturur;
99
+ `widthType` HİÇ yazılmazsa `w:2` = 12'de 2 → 1440px tasarım genişliğinde 240px payı
100
+ geçerlidir. String yalnız `'fixed'` modda okunur — tek başına `widthString` ölüdür.
101
+ - **Yükseklik `fill`'dir**, `size.h` değil: kök ekranı doldurur, yan menü ve içerik sütunu
102
+ kökün bıraktığını, slot da üst şeritten artanı alır. Slot'un grid satırı ayrıca açık
103
+ uçludur (`y / auto`), yani sayfa uzadıkça slot uzar.
104
+ - **Kaydırma:** `fill` + `states.isScrollable:true` verilen düğüm büyümek yerine İÇİNDE
105
+ kaydırır — uzun içerikte kabuğu sabit tutmanın yolu budur.
106
+ - **Slot'un kenar boşluğu margin'dir, padding değil.** Slot droppable değildir; ona yazılan
107
+ `paddingType`/`paddingValue` hiçbir kutuya çizilmez (LAY-010). Her sayfanın kenardan uzak
108
+ durmasını tek yerden istiyorsan slot'a `appearance.marginType: 'custom'` + `marginValue: 24`
109
+ yaz — margin slot'un sarmalayıcısına iç boşluk olarak iner ve slot'un zemini olmadığı için
110
+ sonuç padding'le aynıdır. Studio iskeleti slot'a zaten 8px custom margin verir. Değer SAYIDIR
111
+ (`24`, `"24px"` değil — LAY-011). Her sayfaya sarmalayıcı container eklemek gerekmez.
112
+ - **MOBİL UYARISI:** bu ağaç `flex` olduğu için telefonda YIĞILMAZ (Kural 7) — 375px'te yan
113
+ menü ince bir şerite iner. Telefonda alt alta düşmesi gereken bir kabuk için kökü
114
+ `layout:'grid'` kur; o zaman `fill`'in flex anlamı (`flex:1 1 auto`) devreye girmez,
115
+ yükseklik yine `blocks` satırlarından gelir. İkisini aynı anda veren bir yol bugün yok.
116
+ - Menü satırlarını biçimlendirme: **bugün mümkün değil.** `navigations`'ın `style` prop'u
117
+ ölüdür (bkz. `component_get('navigations')`).
121
118
 
122
119
  ## Mini tarif — menüde aktif satır
123
120
 
@@ -147,8 +144,8 @@ bağlantı nesnesi ya da tam yol).
147
144
  "direction": { "type": "static", "data": "row" } },
148
145
  "blocks": [{ "breakpoint": 1024, "size": { "w": 12, "h": 80 }, "position": { "x": 0, "y": 0 } }] }
149
146
 
150
- // KÖTÜ — telefonda 49px'lik yan menü: row flex mobilde yığılmaz (Kural 7)
151
- // Mobilde alt alta düşmesi gerekiyorsa kökü layout:'grid' kur — bedeli, fill'in
147
+ // KÖTÜ — telefonda 49px'lik yan menü: row flex dar ekranda yığılmaz (Kural 7)
148
+ // Dar ekranda alt alta düşmesi gerekiyorsa kökü layout:'grid' kur — bedeli, fill'in
152
149
  // flex anlamının devreye girmemesi.
153
150
  ```
154
151
 
@@ -186,9 +183,9 @@ bunlardan biri olabilir:
186
183
  |---|---|
187
184
  | ~~`heightType` yalnız `auto` \| `fixed`~~ | **28 Ağustos'ta kapandı:** üçüncü değer `fill` (Kural 5b) |
188
185
  | ~~Kök kap viewport'a kilitlenmez~~ | **28 Ağustos'ta kapandı:** `fill` verilmiş kök 100vh (Kural 5b) |
189
- | Flex mobilde yığılmaz | Kural 7 — kabuk bugün bir MASAÜSTÜ kabuğudur |
190
- | Kırılıma duyarlı prop yok | `direction`/`gap` masaüstü ve mobilde AYNI; yalnız `blocks` ve `appearance.hideOn` kırılım bilir |
191
- | ~~Mobil çekmece (overlay) yok~~ | **Kapandı:** `navigations` (`layout:'sidebar'`) ≤768px'te kendi çekmecesine ve hamburger düğmesine döner — varsayılan kabuğun sol menüsü bunu kendiliğinden yapar |
186
+ | Flex dar ekranda yığılmaz | Kural 7 — kabuk bugün bir MASAÜSTÜ kabuğudur |
187
+ | Kırılıma duyarlı prop yok | `direction`/`gap` masaüstü ve dar ekranda AYNI; yalnız `blocks` ve `appearance.hideOn` kırılım bilir |
188
+ | Dar ekranda çekmece (overlay) yok | Telefon genişliğinde içeriğin üstüne binen panel kurulamaz (mobil UYGULAMADA çekmece `drawer` widget'ıdır — `platform_guide('mobile')`) |
192
189
 
193
190
  ---
194
191
 
@@ -196,7 +193,7 @@ bunlardan biri olabilir:
196
193
  (`injectPageSchemaIntoSlots`, `getResolvedLayoutViews`), `apps/studio/src/features/page/api/page.mappers.ts`
197
194
  (`mapPageLayoutToPreview`), `packages/ng-apps-ui/src/shared/render/render.functions.ts`
198
195
  (`resolveNodeBoxStyle` — slot'un `y / auto` satırı, flex çocuk genişliği),
199
- `packages/ng-apps-ui/src/shared/render/RenderComponent.svelte` (mobil media kuralı),
196
+ `packages/ng-apps-ui/src/shared/render/RenderComponent.svelte` (dar ekran media kuralı),
200
197
  `packages/ng-apps-screen-builder/src/flex-layout.ts` (`getFlexChildStyle` — `widthType`
201
198
  fill/fixed/auto dalları, `normalizeCssSize` kabul kuralı; tuval ve runtime aynı fonksiyonu okur),
202
199
  `apps/studio/src/features/page/components/appearance/appearance-size.functions.ts` (panelin