@appaflytech/zeyrek-ai-mcp 0.0.8 → 0.0.9

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 (39) hide show
  1. package/README.md +27 -21
  2. package/dist/config.js +2 -0
  3. package/dist/knowledge/componentCatalog.js +122 -27
  4. package/dist/knowledge/componentEvents.js +35 -4
  5. package/dist/knowledge/errorPath.js +1 -1
  6. package/dist/knowledge/normalize.js +15 -0
  7. package/dist/knowledge/rules.js +3 -1
  8. package/dist/knowledge/styleResolve.js +46 -4
  9. package/dist/knowledge/themeResolve.js +936 -0
  10. package/dist/knowledge/themeRules.js +221 -0
  11. package/dist/knowledge/themeSchema.js +335 -0
  12. package/dist/platform/domSummary.js +144 -0
  13. package/dist/platform/screenshot.js +414 -23
  14. package/dist/platform/screenshotMemory.js +55 -0
  15. package/dist/resources/examples/layout-app-shell.json +1 -1
  16. package/dist/resources/examples/theme-brand.json +162 -0
  17. package/dist/resources/guides/component.md +7 -1
  18. package/dist/resources/guides/getting-started.md +4 -0
  19. package/dist/resources/guides/layout.md +30 -26
  20. package/dist/resources/guides/microservice.md +55 -1
  21. package/dist/resources/guides/page.md +87 -44
  22. package/dist/resources/guides/theme.md +210 -0
  23. package/dist/resources/guides/translation.md +6 -4
  24. package/dist/resources/guides/workflow.md +91 -6
  25. package/dist/resources/schema-fingerprint.json +2 -2
  26. package/dist/server.js +52 -43
  27. package/dist/tools/components.js +8 -0
  28. package/dist/tools/designSchemaPatch.js +152 -0
  29. package/dist/tools/flows.js +15 -18
  30. package/dist/tools/layouts.js +4 -4
  31. package/dist/tools/microservices.js +5 -5
  32. package/dist/tools/pages.js +196 -323
  33. package/dist/tools/projects.js +66 -9
  34. package/dist/tools/schemaOps.js +280 -0
  35. package/dist/tools/screenWrite.js +2 -1
  36. package/dist/tools/screens.js +0 -7
  37. package/dist/tools/themes.js +163 -0
  38. package/dist/tools/workflows.js +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,210 @@
1
+ # Tema Rehberi (proje düzeyi tasarım)
2
+
3
+ Bir projenin rengi, yazı tipi, köşe/boşluk ölçekleri, gölgesi ve yeniden kullanılan stilleri
4
+ **tek bir kayıtta** yaşar: `projects.theme`. Runtime onu her sayfada `--ng-*` CSS
5
+ değişkenlerine çevirir, yani temayı değiştirmek bütün ekranları birden değiştirir.
6
+
7
+ Okuma `theme_get`, yazma `theme_update`. Studio'nun tema paneli de aynı kaydı yazar — MCP'den
8
+ yazdığınızı panel açar, panelin yazdığını MCP okur.
9
+
10
+ **Tema PROJE kaydıdır, ortam kaydı değil.** `environment` parametresi yoktur: yazma o an
11
+ projenin bütün ortamlarının runtime'ına iner (development de production da). Sayfa/entity
12
+ yazmalarının aksine burada "önce development'ta dene" diye bir ayrım YOKTUR.
13
+
14
+ ## Veri modeli
15
+
16
+ `theme_get(view:'raw')` kaydın kendisini, `view:'resolved'` ekrana inen hâlini verir.
17
+
18
+ | Alan | Ne yapar | Ürettiği değişken(ler) |
19
+ |---|---|---|
20
+ | `mode` | `'light'` (varsayılan) \| `'dark'` — yayınlanan uygulamanın modu | palet tabanını seçer |
21
+ | `palette` | AYDINLIK moddaki renk override'ları | `--ng-accent-*` · `--ng-background-*` · `--ng-text-*` · `--ng-border-*` · `--ng-status-*` |
22
+ | `paletteDark` | KARANLIK moddaki renk override'ları | aynı küme |
23
+ | `fontFamily` · `headingFontFamily` | Gövde ve başlık yazı tipi (Google Fonts adı) | `--ng-font` · `--ng-font-heading` |
24
+ | `fontSize` · `fontWeight` | Taban punto ve ağırlık | `--ng-font-size` · `--ng-font-weight` |
25
+ | `typeScale` | Metin seviyelerinin tabana ORANI (h1…small) | `--ng-font-size-h1` … `-small` (+ `-mobile`) |
26
+ | `spacing` · `spacingScale` | Taban boşluk ve kademe oranları | `--ng-spacing` · `--ng-spacing-xs..xl` |
27
+ | `borderRadius` · `radiusScale` | Taban köşe ve kademeler (`pill` sabit uzunluk) | `--ng-rounded` · `--ng-radius-sm/md/lg/pill` |
28
+ | `shadow` | Tek gölge tarifi (offset/blur/spread/color/opacity) | `--ng-shadow-sm/md/lg` |
29
+ | `defaultInputSize` | Form girdilerinin varsayılan boyu (`sm`/`md`/`lg`) | `--ng-form-default-size` |
30
+ | `colors` | Renk RAMPALARI (aile → ton) | `--ng-blue-500`, `--ng-grey-200` … |
31
+ | `actions` | Grafik/veri görselleştirme serisi renkleri | `--ng-action-blue` … |
32
+ | `presets` | **Adlı stiller** — düğümden `style.$preset` ile çağrılır | CSS değişkeni üretmez |
33
+ | `componentPresets` | Bir TİPİN yeni düğümlerde başlayacağı prop varsayılanları | CSS değişkeni üretmez |
34
+ | `componentStyles` | **EMEKLİ** — tipin her örneğine canlı uygulanan stil | CSS değişkeni üretmez |
35
+
36
+ **Yalnız SAPAN değer yazılır.** `typeScale`, `radiusScale`, `spacingScale` ve `actions`
37
+ kayıtta yalnız varsayılandan farklı olan kademeleri/renkleri taşır; dokunulmayan kademe
38
+ platformun varsayılanını İZLEMEYE devam eder. Hepsini birden yazmak onları o günkü değerlere
39
+ dondurur — yazmayın.
40
+
41
+ Değişkenlerin tam listesi ve o projedeki değerleri: `theme_get(view:'resolved')` → `cssVars`
42
+ (~190 giriş). Bir sayfada tek seferlik sapma için `platform_guide('page')` Kural 1h.
43
+
44
+ ## Karar kuralları
45
+
46
+ **1. Önce tema, sonra preset, en son düğüm stili.** Aynı görünüm üç yerden verilebilir ve
47
+ sırası bellidir: projenin tamamı için tema token'ı (`theme_update`), tekrar eden bir kalıp için
48
+ adlı preset (`presets` + `style.$preset`), yalnız o düğüme özgü karar için düğümün kendi
49
+ `style`'ı. Sabit hex yazmak yerine `var(--ng-accent-primary)` yazmak, düğümü temaya BAĞLI
50
+ tutar.
51
+
52
+ **2. Marka rengi tek çağrıdır.** `theme_update({ palette: { accent: { primary, hover } } })`
53
+ sayfadaki her butonu, odak halkasını, seçili satırı ve grafik serisini birden çevirir. Komponent
54
+ komponent stil yazmak hem uzun sürer hem yeni komponent eklendiğinde tutarsızlık üretir.
55
+
56
+ **3. "Her X böyle görünsün" ile "yeni X şöyle başlasın" AYRI şeylerdir.**
57
+
58
+ | İstek | Yol | Mevcut düğümlere etkisi |
59
+ |---|---|---|
60
+ | Her kart aynı yüzeyi paylaşsın | `presets.kart` + düğümde `style.$preset: 'kart'` | Bağlı olanların hepsi anında değişir |
61
+ | Yeni bırakılan her button `lg` olsun | `componentPresets.button` | **YOK** — yalnız bundan sonra kurulanlar |
62
+ | (emekli) Her button kalın olsun | `componentStyles.button` | Studio paneli ilk kayıtta bunu `componentPresets`'e taşır ve canlı bağ kopar |
63
+
64
+ `componentPresets` bir KASKAD DEĞİL, başlangıç değeridir: değerler düğüm kurulurken prop'lara
65
+ yazılır ve `style.$componentPreset` yalnız "hangi versiyondan geldi"yi anar. Temada versiyonu
66
+ sonradan değiştirmek o düğümleri güncellemez.
67
+
68
+ **4. Koyu mod ayrı bir palettir ve proje `light` olsa da devreye girebilir.** Karanlıkta
69
+ runtime `paletteDark`'a bakar, `palette`'e değil. İki ayrı durum aynı sonucu verir:
70
+
71
+ - Kaydın kendisi `mode: 'dark'` ve yalnız `palette` yazılmış → renkler hiç görünmez.
72
+ - Kayıt `mode: 'light'` ama **ZİYARETÇİ** koyu moda geçmiş (`theme-toggle` komponenti,
73
+ tarayıcıda kalıcı; `page_screenshot(colorScheme: 'dark')` aynı yolu kullanır) → yine
74
+ `paletteDark` okunur ve markanız yerine platformun kendi koyu paleti çizilir.
75
+
76
+ Ölçüldü (2026-09-15): yalnız `palette` yazılmış bir projede aydınlık kare markanın indigo'sunu,
77
+ koyu kare platformun `#4C8DFF` mavisini gösterdi. **Uygulama koyu modda açılabiliyorsa
78
+ `paletteDark` da yazılır** — THEME-009 bunu her iki durumda da uyarır.
79
+
80
+ **5. Yazmadan önce `dryRun`.** `theme_update(dryRun: true, …)` hiçbir şey yazmadan hangi
81
+ yolların değişeceğini (`changed`) ve hangi CSS değişkeninin hangi değerden hangi değere
82
+ gideceğini (`cssVarsChanged`) söyler. Bir rengin türetilmiş etkisini (odak halkası, grafik
83
+ serisi, kontrast metin) görmenin en ucuz yolu budur.
84
+
85
+ **6. Kısmi yaz, `unset` ile sil.** `theme_update` verdiğiniz alanları mevcut kayda DERİN
86
+ birleştirir: bir rengi değiştirmek preset'leri düşürmez. Silmek `null` yazmakla değil
87
+ `unset: ['presets.kart']` ile olur; kaydın tamamını değiştirmek `replace: true` ister.
88
+
89
+ ## Tarifler
90
+
91
+ **Marka paleti (aydınlık + karanlık):**
92
+
93
+ ```jsonc
94
+ theme_update({ theme: {
95
+ palette: { accent: { primary: "#4F46E5", hover: "#4338CA" } },
96
+ paletteDark: { accent: { primary: "#818CF8", hover: "#A5B4FC" } }
97
+ } })
98
+ ```
99
+
100
+ **Yazı tipi ve ölçek:** `fontFamily` panelin Google Fonts listesinden bir ad olmalı — runtime
101
+ fontu ADIYLA Google'dan çeker, tanınmayan ad sessizce sans-serif'e düşer (THEME-008).
102
+
103
+ ```jsonc
104
+ theme_update({ theme: {
105
+ fontFamily: "Inter Tight", headingFontFamily: "Sora",
106
+ fontSize: "15px", typeScale: { h1: 2.5 }
107
+ } })
108
+ ```
109
+
110
+ **Ölçekler:** oran `0 < r ≤ 20` aralığında olmalı; aralık dışı değer runtime'da SESSİZCE yok
111
+ sayılır (THEME-007 bunu yazmadan önce durdurur).
112
+
113
+ ```jsonc
114
+ theme_update({ theme: { borderRadius: "8px", radiusScale: { lg: 2 }, spacing: "12px" } })
115
+ ```
116
+
117
+ **Gölge:** `color` altı haneli hex OLMALI; başka bir yazım üç gölgeyi birden görünmez yapar
118
+ (THEME-004).
119
+
120
+ ```jsonc
121
+ theme_update({ theme: { shadow: { offsetY: 6, blur: 12, spread: -2, color: "#1E1B4B", opacity: 18 } } })
122
+ ```
123
+
124
+ **Adlı preset kurup bir düğüme bağlamak** — iki adım, ikincisi sayfa tarafında:
125
+
126
+ ```jsonc
127
+ // 1) temaya yaz
128
+ theme_update({ theme: { presets: { kart: {
129
+ padding: "16px", borderRadius: "12px",
130
+ background: "var(--ng-background-surface)", boxShadow: "var(--ng-shadow-md)"
131
+ } } } })
132
+
133
+ // 2) düğüme bağla (page_schema_patch)
134
+ { "op": "replace_prop", "target": "kart_1", "prop": "style", "value": { "$preset": "kart" } }
135
+ ```
136
+
137
+ Preset gövdesinde sabit hex yerine `var(--ng-*)` kullanın: preset de temayı izlesin.
138
+
139
+ **Bileşen preseti (yeni düğümlerin başlangıç değeri):** `props` ham prop varsayılanlarıdır
140
+ (`component_get` → `defaults` ile aynı şekil); `appearance` yalnız BOŞLUK alanlarını taşır
141
+ (margin/padding) — ölçü ve hizalama o örneğin ızgaradaki geometrisidir, tipin kararı değil.
142
+
143
+ ```jsonc
144
+ theme_update({ applicationId: "<app>", theme: { componentPresets: { button: {
145
+ defaultVersion: "V1",
146
+ versions: { V1: { props: { size: "lg" }, appearance: { marginType: "custom", marginValues: { bottom: 12 } } } }
147
+ } } } })
148
+ ```
149
+
150
+ Bir tip en fazla 5 versiyon taşır ve `defaultVersion` versiyonlar arasında olmalıdır
151
+ (THEME-002). `applicationId` verirseniz gateway tipin o uygulamanın kataloğunda gerçekten
152
+ var olduğunu da denetler (THEME-011).
153
+
154
+ **Grafik paleti ve rampalar:** `actions` grafik serisi renkleri (`--ng-action-*`), `colors`
155
+ ise ton rampaları (`--ng-blue-500` gibi). İkisi de yalnız veri yoluyla ayarlanır; panelde
156
+ rampa arayüzü yoktur.
157
+
158
+ **Temayı sıfırlamak:** `theme_update({ replace: true, theme: {} })`.
159
+
160
+ ## Doğrulama
161
+
162
+ Sıra sabittir; her adım bir öncekinin kanıtını üretir:
163
+
164
+ 1. `theme_update(dryRun: true, …)` → `cssVarsChanged` beklediğiniz değişkenleri taşıyor mu?
165
+ 2. `theme_update(…)` → `changed.set` / `changed.unset` yazılanı doğruluyor mu?
166
+ 3. `theme_get(view:'resolved')` → `cssVars['--ng-accent-primary']` yeni değeri mi?
167
+ 4. `page_screenshot(…)` → **ekranda** gerçekten öyle mi? Koyu mod için aynı çağrıya
168
+ `colorScheme: 'dark'`; sayfada `theme-toggle` komponenti bulunması GEREKMEZ.
169
+ 5. Preset bağladıysanız `page_runtime_get(resolveStyles: true)` → düğümün
170
+ `styleLayers.preset` alanı preset adını söylüyor mu, `resolvedStyle` preset'in
171
+ değerlerini taşıyor mu?
172
+
173
+ ## Tuzaklar
174
+
175
+ **`project_update` tema alanı verilmezse temayı SİLERDİ.** Platformun `PUT /projects/{id}`
176
+ ucu REPLACE'tir: gövdede `Theme` yoksa tema `null` yazılır ve bütün ortamlara yayılır. Gateway
177
+ artık mevcut temayı okuyup gövdeye geri koyuyor ve bunu `gatewayNormalized` ile bildiriyor —
178
+ ama temayı DEĞİŞTİRMEK için `project_update` değil `theme_update` kullanın.
179
+
180
+ **Studio tema paneli açık ve kaydedilmemişse yazmanız ezilir.** Panel durumunu açılışta
181
+ okur; siz MCP'den yazarken panel açıksa panelin sonraki "Save"i kendi kopyasını üstüne yazar.
182
+ Panel kapalıyken yazın. Gateway bunu tespit edemez — proje kaydında sürüm alanı yoktur.
183
+
184
+ **Silinen preset sessizce kaybolur.** Çözümleyici eşleşmeyen bir `$preset` adını hata vermeden
185
+ atlar (bir preset silindi diye sayfalar boşalmasın diye). Düğüm kendi stiline düşer ve kimse
186
+ bir şey söylemez — silmeden önce `page_schema_get` ile o adı arayın (THEME-010 uyarır ama
187
+ tarama yapmaz).
188
+
189
+ **`componentStyles` yazmak canlı kaskadı kalıcı kılmaz.** Runtime onu hâlâ uyguluyor ama
190
+ Studio tema paneli açıldığı ilk kayıtta içeriği `componentPresets`'e taşıyıp anahtarı siliyor:
191
+ o an "her örneğe uygulanan stil", "yalnız yeni düğümlere varsayılan"a döner ve sayfadaki
192
+ mevcut düğümler görünüşlerini kaybeder (THEME-003).
193
+
194
+ **Çıplak sayı CSS uzunluğu değildir.** `fontSize: 16` → `--ng-font-size: 16` geçersizdir ve
195
+ tarayıcı bildirimi sessizce atar. Gateway sayıyı `'16px'`e çevirip `gatewayNormalized` ile
196
+ bildirir; birimli yazmak daha açıktır.
197
+
198
+ **Tanınmayan anahtar kayıtta yaşar.** `projects.theme` doğrulanmayan bir jsonb blob'udur:
199
+ `pallete` yazan istek 200 döner ve panel o anahtarı körce geri yazar. `theme_update` şeması
200
+ bunu istek gitmeden reddeder; eski kayıtlardaki kalıntıları `theme_get` `unknownKeys` ile
201
+ gösterir ve `unset` temizler.
202
+
203
+ **Markanın koyu karşılığı ayrı yazılır.** Aydınlık paleti yazıp bitirdiğinizi sanmak en kolay
204
+ hata: ziyaretçi koyu moda geçtiği anda uygulamanız platformun varsayılan mavisine döner. İki
205
+ kareyi de alın: `page_screenshot(…)` ve `page_screenshot(…, colorScheme: 'dark')`; ikisinin de
206
+ `theme_get(view:'resolved', mode: …)` ile aynı şeyi söylediğini doğrulayın.
207
+
208
+ **Renkler hex olmalı.** CSS `rebeccapurple`'ı çizer ama studio'nun renk alanları hex bekler
209
+ ve vurgu üstündeki metin rengi (`--ng-text-on-accent`) accent'i karakter karakter okuyup
210
+ kontrast hesapladığı için tanımadığı değerde beyaza düşer (THEME-005).
@@ -87,7 +87,7 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
87
87
  > yeniden eklemeyi öneriyordu; o öneri uygulanınca düğüme yazan setter iteratee'lerinin `element`'i
88
88
  > silindi (bir panoda alt başlık ve tarih aralığı boş kaldı). Ref'siz translation sarmalı istek
89
89
  > gönderilmeden reddedilir; nesne `data` silinir. Eş yol `set_prop_type`'tır — mevcut `data`'yı
90
- > tasarım yedeği olarak taşır ve layout ağacında (micro-op hattı yok) tek yoldur:
90
+ > tasarım yedeği olarak taşır:
91
91
  >
92
92
  > ```jsonc
93
93
  > { "op": "set_prop_type", "target": "welcome_text", "prop": "text",
@@ -95,9 +95,11 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
95
95
  > ```
96
96
  >
97
97
  > İkisi de düğümün olay/setter bağlarını korur. **Prop tipini değiştirmek için
98
- > `remove_component` + `add_component` yapmayın.** Taşıyıcı alan tipe göre değişir: `static` →
99
- > `data`, `code` ve `translation` → `ref`. Eksik taşıyıcı istek platforma gitmeden reddedilir ve
100
- > `page_schema_validate` aynı kararı verir.
98
+ > `remove_component` + `add_component` yapmayın.** İki op da platformun kendi sözlüğündedir ve
99
+ > yamanın geri kalanıyla aynı PATCH'te gider — sayfada `page_schema_patch`, layout'ta
100
+ > `layout_schema_patch`, widget'ta `component_schema_patch`. Taşıyıcı alan tipe göre değişir:
101
+ > `static` → `data`, `code` ve `translation` → `ref`. Eksik taşıyıcı istek platforma gitmeden
102
+ > reddedilir ve `page_schema_validate` aynı kararı verir.
101
103
  >
102
104
  > Ölçüldü 2026-09-08 (yerel `dil-dogrulama/dil-app`): kurulu bir `statcard`'ın `title` prop'u tek
103
105
  > `set_prop_type` op'uyla `f11.tam` anahtarına bağlandı; gerçek ekranda `tr` → "iki dilde dolu",
@@ -139,6 +139,85 @@ yoktur** (ölçüm: 2026-09-07). Yazmayı doğrulamak istiyorsan sorguyu kaydet,
139
139
 
140
140
  Tool açıklamaları bu bölüme işaret eder; iki kaynak çelişirse **bu rehber** doğrudur.
141
141
 
142
+ ## Önizleme çıktısını okumak: adım izi, hata alanları ve canlı koşudan farkı
143
+
144
+ `workflow_preview` / `automation_preview` yanıtı `WorkflowPreviewDto`'dur — Studio'daki "Önizleme"
145
+ düğmesinin okuduğu gövdenin aynısı (`WorkflowDetail.svelte` `handlePreview` →
146
+ `POST workflows/{appId}/preview`). Studio'nun yaptığı tek şey listeyi düzleştirip **`hasError: true`
147
+ olan ilk adıma** odaklanmaktır; hata yoksa son adıma. Aynı okumayı sen de yap:
148
+
149
+ ```jsonc
150
+ { "input": { "id": 12 }, // previewPayload'ın değerlendirilmiş hâli — BOŞSA girdi hiç bağlanmamıştır (WF-016)
151
+ "output": { … }, // akışın döndürdüğü gövde (response adımı)
152
+ "executionSuccess": true, // YALNIZ son adıma bakar — hata dalından dönen akışta da true olabilir
153
+ "steps": [
154
+ { "step": { "id": "…", "name": "readRow", "type": "table" },
155
+ "input": [ { "expression": "input.id", "value": 12, "source": "filter", "member": "id" } ],
156
+ "output": { … }, // adımın ürettiği veri; patlayan adımda boş
157
+ "hasError": true,
158
+ "errorType": "RowNotFoundException", "errorCode": "RowNotFound",
159
+ "errorMessage": "…lokalize mesaj…", "errorDetail": "…iç ayrıntı (SQL/JS hatası)…",
160
+ "elapsedMilliseconds": 7.3,
161
+ "nextStep": { "id": "…", "name": "gatewayOnError", "type": "response" }, // akış buradan nereye gitti
162
+ "children": [ … ], // loop iterasyonları / alt workflow: her biri { kind, name, steps, input, output, executionSuccess }
163
+ "automations": [ … ] // table adımının tetiklediği automation'lar: { id, name, entityId, operation, row, previousRow, status, errorMessage, executionSuccess, steps }
164
+ } ],
165
+ "runtimeErrors": [ "readRow (table): RowNotFound — …" ] // GATEWAY ekler; platform gövdesinde yoktur
166
+ }
167
+ ```
168
+
169
+ **Okuma sırası:**
170
+
171
+ 1. **`runtimeErrors`** — gateway tüm ağacı tarar (`steps[].children[].steps[]` ve
172
+ `steps[].automations[].steps[]` dâhil). Boşsa akış hiçbir adımda patlamamıştır.
173
+ `executionSuccess`'e güvenme: platform onu son adımın `hasError`'ından hesaplar
174
+ (`WorkflowPreviewDto.cs:25`); ortada patlayıp `gatewayOnError`'dan 500 dönen akış `true` gösterir.
175
+ 2. **Patlayan adımın satırı** — `errorType` exception tipi, `errorMessage` lokalize mesaj,
176
+ `errorDetail` iç ayrıntı. `input[]` adımın hangi ifadeyi hangi değere bağladığını gösterir:
177
+ satırda `value` yoksa ifade `undefined`/null üretmiştir — hatanın gerçek sebebi çoğu zaman bir
178
+ üst adımın çıktısı ya da bağlanmamış girdidir (`"input": {}`).
179
+ 3. **`nextStep`** — adımdan sonra akışın nereye gittiği. Hata dalına düşen adımın `nextStep`'i
180
+ global-error dalının ilk adımıdır; `fail` dalı bağlıysa o adımdır.
181
+ 4. **`elapsedMilliseconds`** — koşunun toplamı beklenenden çok kısaysa (yazma akışı 90 ms gibi)
182
+ akış ilk adımlarda patlayıp hata dalından dönmüştür; adım sürelerinden nerede durduğunu oku.
183
+ 5. **HTTP 200 ≠ geçti, HTTP 400/500 ≠ adım hatası.** Yanıt 200 iken akış patlamış olabilir
184
+ (yukarıdaki alanlar). Yanıt 400/500 ise koşum **hiç başlamamıştır**: validator reddi (WF-026),
185
+ `previewPayload`'ın nesne gönderilmesi (`Unexpected end of input`), `previewVariables`
186
+ ifadesinin patlaması. İkisini ayır: ilkinde adımı, ikincisinde gövdeyi düzelt.
187
+
188
+ **Kayıtlı bir akışı çalıştırmadan koşturmak** (Studio'nun "Önizleme" düğmesinin MCP karşılığı):
189
+
190
+ 1. `workflow_get(applicationId, id)` — varsayılan `view:'full'` gövde `steps`, `parameterDtoId`,
191
+ **`previewPayload`** ve **`previewVariables`** alanlarını taşır: Studio'da yazılan test girdisi
192
+ tanımla birlikte saklanır (`Workflow.PreviewPayload` / `PreviewVariables`) ve Studio'nun
193
+ önizlemesi de onu kullanır.
194
+ 2. Yanıttaki `data` gövdesini `workflow_preview(definition)` ile olduğu gibi gönder: `id`,
195
+ `createdAt` gibi fazladan alanlar platformda yok sayılır; `parameterDtoId` yoksa gateway
196
+ `previewPayload`'ı düşürür. Girdiyi değiştirmek için yalnız `previewPayload`'ı yeniden yaz
197
+ (`"({ … })"` biçimi, Kural 4).
198
+ 3. `runtimeErrors` boş + `input` dolu ⇒ akış bu girdiyle geçiyor. Ancak ondan sonra kaydet, uca
199
+ bağla ya da zamanla. Zamanlanmış iş için sıra ve tuzaklar: `platform_guide('microservice')`
200
+ §"Zamanlanmış işin gerçek sonucunu görmek".
201
+
202
+ **Önizleme neyi kanıtlar, neyi kanıtlamaz** (kaynak: `PreviewWorkflowCommand`, `WorkflowContext`,
203
+ `ExecuteMicroserviceBehavior`, `MicroserviceJob`):
204
+
205
+ | Konu | `workflow_preview` | Canlı uç (`/m/`, sayfa akışı) | Zamanlanmış iş (`schedule-job`) |
206
+ |---|---|---|---|
207
+ | Yazmalar | tek transaction, sonunda **rollback** | 2xx'te commit, 4xx/5xx'te rollback | 2xx'te commit; bağlanmamış fail ya da 2xx dışı sonuçta **rollback** (2026-09-16'dan beri; öncesinde her durumda commit ediyordu) |
208
+ | Girdi | `previewPayload` (JS kaynak metni) | isteğin gövdesi/query/route, DTO'ya bağlanır | **boş** (`MicroserviceExecuteParameter.Create()`); `input.x` hep `undefined` |
209
+ | `request.*` | **yok** (Preview'da yüklenmez) | var | **yok** (HttpContext yok) |
210
+ | `context` / `triggerSource` | kurulmaz (GEN-005) | var | kurulmaz |
211
+ | Middleware ve `user` | koşmaz | koşar | **koşmaz** — `user` yok |
212
+ | `email`, `http`, `code` içi HTTP | **gerçekten koşar** (SMTP gönderilir, dış uç çağrılır) | gerçek | gerçek |
213
+ | `microfunction` | `preview: true` bayrağıyla çağrılır | gerçek | gerçek |
214
+ | `table` / `file` yazmaları | geri alınır | yukarıdaki commit/rollback | yukarıdaki commit/rollback |
215
+ | Adım izi | **tam** (bu bölüm) | yok — yalnız yanıt gövdesi; ağaç için `microservice_debug` | yok — geçmiş satırı `status + süre + errorMessage` (`Step 'x' failed: <sebep>` ya da `The job's workflow returned 500 (<code>): <mesaj>`) |
216
+
217
+ Yani önizleme akışın **şeklini** kanıtlar: ifadeler, dallar, DTO uyumu, tablo/sorgu hataları.
218
+ Kanıtlamadıkları: dile bağlı dal (`context.language`), `user`'a bağlı kapsam, `request`'ten okunan
219
+ parametre — bunları `microservice_execute` ile ölç (§İstek dili, `platform_guide('middleware')`).
220
+
142
221
  ## Hata yolu
143
222
 
144
223
  **Gateway workflow ve middleware tanımlarına hata yolunu otomatik ekler** (yanıtta
@@ -176,8 +255,11 @@ yapıyı dışarı sızdırır.
176
255
  - **`automation` tipinde `response` adımı yasaktır**, bu yüzden gateway bu tipe enjeksiyon
177
256
  yapmaz. Hata yolunu kendin yaz: global-error dalını `revert` (kapsamı `isQueue`'ya
178
257
  bağlı — §izin matrisi) ya da `email`/`table` adımına bağla. Bağlı hata yolu yoksa `WF-021` uyarır.
179
- - **Hata yolu hiç yoksa** akış patladığında platform 500 + ham exception mesajı döner. Çalışır,
180
- ama çıktı denetimsizdir ve lokalize değildir.
258
+ - **Hata yolu hiç yoksa** (fail dalı ve global-error dalı bağlı değil) adım patladığında motor
259
+ canlıda `WorkflowStepFailedException` fırlatır (2026-09-16): HTTP yanıt 500 +
260
+ `{ code, message, detail, type }` (patlayan adımın hatası), zamanlanmış iş ve automation geçmişi
261
+ `failed` + `Step 'x' failed: <sebep>`, senkron automation tetikleyen satır yazımını düşürür.
262
+ Önizlemede fırlatmaz, ağaç döner. Çalışır, ama çıktı lokalize değildir.
181
263
 
182
264
  > **Preview HTTP 200 dönerken bile akış patlamış olabilir.** `executionSuccess` yalnız SON adıma
183
265
  > bakar; ortada patlayıp hata dalından dönen akış `true` gösterir. Gateway tüm adımları (iç içe
@@ -186,10 +268,13 @@ yapıyı dışarı sızdırır.
186
268
  >
187
269
  > **`runtimeErrors` her tool'da aynı şeyi ölçmez.** Alan yalnız `steps[]` taşıyan yanıtlarda adım
188
270
  > adım tarama yapar. `microservice_execute` / `microservice_debug` / `microservice_preview`
189
- > yanıtlarında gateway sadece `httpStatus >= 400` durumunu bulgu sayar: bu tool'lar adım ağacını
190
- > `executionItems` olarak döner ve o düğümlerde hata işareti yoktur, yani HTTP 200 gövdesine gömülü
191
- > bir microservice hatası `runtimeErrors` üretmez. Orada `body`'yi kendin oku ve şüpheliyse
192
- > `microservice_debug` ile adım adım bak. `query_preview` yanıtları hiç kapsanmaz.
271
+ > yanıtlarında gateway sadece `httpStatus >= 400` durumunu bulgu sayar — bu üç uçta HTTP durumu
272
+ > akışın kendi `httpStatusCode`'udur (`MicroservicesController.HandleResult`), yani hata dalından
273
+ > 500 dönen akış yakalanır, ama 200 ile `{ success: false }` dönen akış yakalanmaz. Adım ağacını
274
+ > (`executionItems`) yalnız `microservice_debug` döner ve o düğümlerde hata işareti yoktur:
275
+ > patlayan adımın `output`'u boştur, hata gövdesi hata dalındaki response adımının çıktısındadır.
276
+ > Orada `body`'yi kendin oku. Adım başına hata alanı isteyen teşhis için akışı `workflow_preview`
277
+ > ile koştur (§Önizleme çıktısını okumak). `query_preview` yanıtları hiç kapsanmaz.
193
278
 
194
279
  ## Condition step kuralları
195
280
 
@@ -1,6 +1,6 @@
1
1
  {
2
- "hash": "cafe3a6b082c7828cece4eaa1c0115ba28581f157eac3288abcf068c7f6f8533",
3
- "generatedAt": "2026-09-15T10:24:42.398Z",
2
+ "hash": "54430a8d4050fd201aaee88608a5d06b947edf6d561ad31354914422df4e94ce",
3
+ "generatedAt": "2026-09-16T11:17:11.569Z",
4
4
  "types": 185,
5
5
  "files": 107,
6
6
  "note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
package/dist/server.js CHANGED
@@ -1,42 +1,44 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { registerMicroserviceTools } from './tools/microservices.js';
3
- import { registerMicrofunctionTools } from './tools/microfunctions.js';
4
- import { registerApplicationTools } from './tools/applications.js';
5
- import { registerDeploymentTools } from './tools/deployments.js';
6
- import { registerDatasourceTools } from './tools/datasources.js';
7
- import { registerAutomationTools } from './tools/automations.js';
8
- import { registerOrganizationTools } from './tools/organizations.js';
9
- import { registerExternalComponentTools } from './tools/externalComponents.js';
10
- import { registerComponentTools } from './tools/components.js';
11
- import { registerPlatformTools } from './tools/platformInfo.js';
12
- import { registerTemplateTools } from './tools/templates.js';
13
- import { registerWorkflowTools } from './tools/workflows.js';
14
- import { registerLayoutTools } from './tools/layouts.js';
15
- import { registerAccessTools } from './tools/access.js';
16
- import { registerTranslationTools } from './tools/translations.js';
17
- import { registerFlowTools } from './tools/flows.js';
18
- import { registerKnowledgeResources } from './resources/knowledge.js';
19
- import { registerSchemaResources } from './resources/schemas.js';
20
- import { registerRuleResources } from './resources/rules.js';
21
- import { instrumentServer } from './observability/trace.js';
22
- import { rejectUnknownArguments } from './platform/strictArguments.js';
23
- import { registerProjectTools } from './tools/projects.js';
24
- import { registerEntityTools } from './tools/entities.js';
25
- import { registerDependencyTools } from './tools/dependencies.js';
26
- import { registerVariableTools } from './tools/variables.js';
27
- import { registerFunctionTools } from './tools/functions.js';
28
- import { registerFolderTools } from './tools/folders.js';
29
- import { registerQueryTools } from './tools/queries.js';
30
- import { registerViewTools } from './tools/views.js';
31
- import { registerPageTools } from './tools/pages.js';
32
- import { registerFileTools } from './tools/files.js';
33
- import { registerRowTools } from './tools/rows.js';
34
- import { registerImportTools } from './tools/imports.js';
35
- import { registerEnvironmentTools } from './tools/environments.js';
36
- import { registerMergeTools } from './tools/merges.js';
37
- import { registerRevisionTools } from './tools/revisions.js';
38
- import { registerActivityTools } from './tools/activities.js';
39
- import { registerDtoTools } from './tools/dtos.js';
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { registerMicroserviceTools } from "./tools/microservices.js";
3
+ import { registerMicrofunctionTools } from "./tools/microfunctions.js";
4
+ import { registerApplicationTools } from "./tools/applications.js";
5
+ import { registerDeploymentTools } from "./tools/deployments.js";
6
+ import { registerDatasourceTools } from "./tools/datasources.js";
7
+ import { registerAutomationTools } from "./tools/automations.js";
8
+ import { registerOrganizationTools } from "./tools/organizations.js";
9
+ import { registerExternalComponentTools } from "./tools/externalComponents.js";
10
+ import { registerComponentTools } from "./tools/components.js";
11
+ import { registerPlatformTools } from "./tools/platformInfo.js";
12
+ import { registerTemplateTools } from "./tools/templates.js";
13
+ import { registerWorkflowTools } from "./tools/workflows.js";
14
+ import { registerLayoutTools } from "./tools/layouts.js";
15
+ import { registerDesignSchemaPatchTool } from "./tools/designSchemaPatch.js";
16
+ import { registerAccessTools } from "./tools/access.js";
17
+ import { registerTranslationTools } from "./tools/translations.js";
18
+ import { registerFlowTools } from "./tools/flows.js";
19
+ import { registerKnowledgeResources } from "./resources/knowledge.js";
20
+ import { registerSchemaResources } from "./resources/schemas.js";
21
+ import { registerRuleResources } from "./resources/rules.js";
22
+ import { instrumentServer } from "./observability/trace.js";
23
+ import { rejectUnknownArguments } from "./platform/strictArguments.js";
24
+ import { registerProjectTools } from "./tools/projects.js";
25
+ import { registerEntityTools } from "./tools/entities.js";
26
+ import { registerDependencyTools } from "./tools/dependencies.js";
27
+ import { registerVariableTools } from "./tools/variables.js";
28
+ import { registerFunctionTools } from "./tools/functions.js";
29
+ import { registerFolderTools } from "./tools/folders.js";
30
+ import { registerQueryTools } from "./tools/queries.js";
31
+ import { registerViewTools } from "./tools/views.js";
32
+ import { registerPageTools } from "./tools/pages.js";
33
+ import { registerThemeTools } from "./tools/themes.js";
34
+ import { registerFileTools } from "./tools/files.js";
35
+ import { registerRowTools } from "./tools/rows.js";
36
+ import { registerImportTools } from "./tools/imports.js";
37
+ import { registerEnvironmentTools } from "./tools/environments.js";
38
+ import { registerMergeTools } from "./tools/merges.js";
39
+ import { registerRevisionTools } from "./tools/revisions.js";
40
+ import { registerActivityTools } from "./tools/activities.js";
41
+ import { registerDtoTools } from "./tools/dtos.js";
40
42
  const moduleRegistrations = {
41
43
  platform: registerPlatformTools,
42
44
  project: registerProjectTools,
@@ -53,10 +55,17 @@ const moduleRegistrations = {
53
55
  dto: registerDtoTools,
54
56
  view: registerViewTools,
55
57
  page: registerPageTools,
56
- component: registerComponentTools,
58
+ theme: registerThemeTools,
59
+ component: (server, platform) => {
60
+ registerComponentTools(server, platform);
61
+ registerDesignSchemaPatchTool(server, platform, "component");
62
+ },
57
63
  externalComponent: registerExternalComponentTools,
58
64
  flow: registerFlowTools,
59
- layout: registerLayoutTools,
65
+ layout: (server, platform) => {
66
+ registerLayoutTools(server, platform);
67
+ registerDesignSchemaPatchTool(server, platform, "layout");
68
+ },
60
69
  variable: registerVariableTools,
61
70
  function: registerFunctionTools,
62
71
  folder: registerFolderTools,
@@ -70,10 +79,10 @@ const moduleRegistrations = {
70
79
  environment: registerEnvironmentTools,
71
80
  merge: registerMergeTools,
72
81
  activity: registerActivityTools,
73
- revision: registerRevisionTools
82
+ revision: registerRevisionTools,
74
83
  };
75
84
  export function createGatewayServer(platform) {
76
- const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: 'ngapps', version: '0.1.0' }), platform.config));
85
+ const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: "ngapps", version: "0.1.0" }), platform.config));
77
86
  for (const moduleName of platform.config.modules) {
78
87
  moduleRegistrations[moduleName](server, platform);
79
88
  }
@@ -1,6 +1,7 @@
1
1
  import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
2
2
  import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, withNormalization } from '../knowledge/normalize.js';
3
3
  import { eventContractsFor, eventPayloadNote } from '../knowledge/componentEvents.js';
4
+ import { componentPresetDefaults, readProjectTheme } from '../knowledge/themeSchema.js';
4
5
  import { knowledgeFor, knowledgeNote, APPEARANCE_TOKEN_SETS, STATE_FLAG_NOTES, INTERNAL_ROLES_BY_TYPE } from '../knowledge/componentCatalog.js';
5
6
  import { componentUpdateBody, fetchHost, schemaParam, unwrap } from './screens.js';
6
7
  import { PlatformApiError } from '../platform/errors.js';
@@ -160,6 +161,12 @@ export function registerComponentTools(server, platform) {
160
161
  : [];
161
162
  const componentSlug = typeof component.slug === 'string' ? component.slug : undefined;
162
163
  const knowledge = knowledgeFor(componentSlug);
164
+ // S-3 — `defaults` HAM katalogdur; Studio'da bırakılan düğüm ise temanın bileşen preseti
165
+ // kaplanmış katalogdan kurulur (`withThemeComponentDefaults`). Tema okunamazsa (uç düşer,
166
+ // yetki yoksa) alan yanıta HİÇ girmez: uydurulmuş bir varsayılan yanlış bilgidir.
167
+ const themeDefaults = componentSlug === undefined
168
+ ? undefined
169
+ : componentPresetDefaults(readProjectTheme(await platform.org('GET', `/p/${platform.resolveProject(project)}`).catch(() => undefined)), componentSlug);
163
170
  return {
164
171
  id: component.id,
165
172
  slug: component.slug,
@@ -188,6 +195,7 @@ export function registerComponentTools(server, platform) {
188
195
  internalRolesNote: "Bu komponentin İÇ kontrolleri dışarıdan adreslenebilir: page_screenshot actions hedefine '<elementId>__<rol>' yazın (ör. 'tbl_vacancy__pager-next'). Kimlikler runtime'ın data-element-id özniteliğidir; ikinci bir mekanizma yoktur."
189
196
  }
190
197
  : {}),
198
+ ...(themeDefaults ? { themeDefaults } : {}),
191
199
  appearanceValues: APPEARANCE_TOKEN_SETS,
192
200
  stateFlags: STATE_FLAG_NOTES,
193
201
  validations: definition.validations,