@atezer/figma-mcp-bridge 1.7.29 → 1.9.0

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 (57) hide show
  1. package/CHANGELOG.md +403 -0
  2. package/README.md +4 -3
  3. package/agents/_orchestrator-protocol.md +185 -0
  4. package/agents/ds-auditor.md +73 -22
  5. package/agents/screen-builder.md +60 -22
  6. package/agents/token-syncer.md +63 -19
  7. package/dist/core/code-warnings.d.ts +38 -0
  8. package/dist/core/code-warnings.d.ts.map +1 -0
  9. package/dist/core/code-warnings.js +191 -0
  10. package/dist/core/code-warnings.js.map +1 -0
  11. package/dist/core/device-presets.d.ts +49 -0
  12. package/dist/core/device-presets.d.ts.map +1 -0
  13. package/dist/core/device-presets.js +141 -0
  14. package/dist/core/device-presets.js.map +1 -0
  15. package/dist/core/instructions.d.ts +4 -2
  16. package/dist/core/instructions.d.ts.map +1 -1
  17. package/dist/core/instructions.js +239 -29
  18. package/dist/core/instructions.js.map +1 -1
  19. package/dist/core/plugin-bridge-connector.d.ts +32 -0
  20. package/dist/core/plugin-bridge-connector.d.ts.map +1 -1
  21. package/dist/core/plugin-bridge-connector.js +31 -2
  22. package/dist/core/plugin-bridge-connector.js.map +1 -1
  23. package/dist/core/plugin-bridge-server.d.ts +8 -0
  24. package/dist/core/plugin-bridge-server.d.ts.map +1 -1
  25. package/dist/core/plugin-bridge-server.js +27 -2
  26. package/dist/core/plugin-bridge-server.js.map +1 -1
  27. package/dist/core/response-guard.d.ts +23 -0
  28. package/dist/core/response-guard.d.ts.map +1 -1
  29. package/dist/core/response-guard.js +113 -0
  30. package/dist/core/response-guard.js.map +1 -1
  31. package/dist/core/version.d.ts +1 -1
  32. package/dist/core/version.d.ts.map +1 -1
  33. package/dist/core/version.js +1 -1
  34. package/dist/core/version.js.map +1 -1
  35. package/dist/local-plugin-only.d.ts.map +1 -1
  36. package/dist/local-plugin-only.js +504 -85
  37. package/dist/local-plugin-only.js.map +1 -1
  38. package/f-mcp-plugin/code.js +514 -29
  39. package/f-mcp-plugin/ui.html +62 -6
  40. package/package.json +1 -1
  41. package/skills/SKILL_INDEX.md +13 -1
  42. package/skills/apply-figma-design-system/SKILL.md +37 -0
  43. package/skills/audit-figma-design-system/SKILL.md +38 -0
  44. package/skills/code-design-mapper/SKILL.md +37 -0
  45. package/skills/design-token-pipeline/SKILL.md +44 -0
  46. package/skills/figma-canvas-ops/SKILL.md +200 -240
  47. package/skills/fmcp-ds-audit-orchestrator/SKILL.md +205 -0
  48. package/skills/fmcp-intent-router/SKILL.md +574 -0
  49. package/skills/fmcp-project-rules/SKILL.md +9 -5
  50. package/skills/fmcp-screen-orchestrator/SKILL.md +166 -0
  51. package/skills/fmcp-screen-recipes/SKILL.md +528 -0
  52. package/skills/fmcp-token-sync-orchestrator/SKILL.md +198 -0
  53. package/skills/generate-figma-library/SKILL.md +38 -0
  54. package/skills/generate-figma-screen/SKILL.md +382 -19
  55. package/skills/implement-design/SKILL.md +32 -0
  56. package/skills/inspiration-intake/SKILL.md +220 -0
  57. package/skills/visual-qa-compare/SKILL.md +33 -0
@@ -6,6 +6,61 @@ metadata:
6
6
  personas:
7
7
  - designer
8
8
  - uidev
9
+ required_inputs:
10
+ - name: device
11
+ type: enum
12
+ options:
13
+ - "iPhone 17 (402×874)"
14
+ - "iPhone 16 Pro Max (440×956)"
15
+ - "iPhone 16 (393×852)"
16
+ - "iPhone 13/14 (390×844)"
17
+ - "Android Compact (412×917)"
18
+ - "Android Medium (700×840)"
19
+ - "iPad Pro 11 (834×1194)"
20
+ - "iPad Pro 13 (1024×1366)"
21
+ - "Desktop (1440×1024)"
22
+ - "Custom (width×height ver)"
23
+ question: "Hangi device boyutunda olsun?"
24
+ required: true
25
+ default_source: ".claude/design-systems/last-intent.md#device"
26
+ - name: design_system
27
+ type: from_state
28
+ source: ".claude/design-systems/active-ds.md#Library Name"
29
+ fallback_question: "Hangi tasarım sistemi kullanılsın? (❖ SUI / Material / Apple HIG / Custom)"
30
+ required: true
31
+ - name: reference_benchmark
32
+ type: node_id_or_none
33
+ question: "Referans alınacak benchmark ekranı var mı? (Node ID veya Figma URL, yoksa 'yok')"
34
+ required: false
35
+ affects: ["screen_type", "sections"]
36
+ - name: screen_type
37
+ type: enum
38
+ options:
39
+ - "Dashboard / özet"
40
+ - "Liste / arama sonuçları"
41
+ - "Detay / profil"
42
+ - "Form / veri girişi"
43
+ - "Login / onboarding"
44
+ - "Confirmation / success"
45
+ - "Empty state"
46
+ - "Error / 404"
47
+ question: "Ne tür bir ekran?"
48
+ required: true
49
+ skip_if: "reference_benchmark != none"
50
+ - name: sections
51
+ type: string_list
52
+ question: "Hangi ana içerik bölümlerini istiyorsun? (örn: header, balance card, quick actions, transactions, bottom nav)"
53
+ required: true
54
+ skip_if: "reference_benchmark != none"
55
+ - name: variants
56
+ type: enum
57
+ options:
58
+ - "Tek varyant"
59
+ - "Light + Dark mode"
60
+ - "2-3 layout alternatifi"
61
+ question: "Kaç varyant istiyorsun?"
62
+ required: false
63
+ default: "Tek varyant"
9
64
  ---
10
65
 
11
66
  # Generate Figma Screen — Kod/Açıklamadan Figma Ekranı
@@ -43,6 +98,33 @@ Topluluk `figma-generate-design` skill'inden uyarlanmış, F-MCP Bridge araçlar
43
98
 
44
99
  **Bu adımları sırayla uygula. Adım atlama.**
45
100
 
101
+ ### Step 0: Aktif Tasarım Sistemi Kontrolü (ZORUNLU - v1.8.0+)
102
+
103
+ **Ekran yapmaya başlamadan önce DS context'inin belirli olduğundan emin ol.**
104
+
105
+ ```
106
+ 1. Read .claude/design-systems/active-ds.md
107
+ 2. Status alanı:
108
+ ✅ Aktif → Library Name'i not al, Step 1'e geç
109
+ ❌ Henüz seçilmedi → Kullanıcıya sor:
110
+ "Hangi tasarım sistemi ile ilerleyelim?
111
+ - ❖ SUI (varsa)
112
+ - Material Design
113
+ - Apple HIG
114
+ - Kendi DS'iniz (Figma library URL verin)
115
+ - Hiçbiri (ham Figma)"
116
+ 3. Kullanıcı yanıtladıktan sonra active-ds.md'yi update et:
117
+ - Status: ✅ Aktif
118
+ - Library Name: <seçim>
119
+ - Selected At: <bugün>
120
+ 4. Sonraki turlarda bu soruyu TEKRAR SORMA — active-ds.md zaten dolu.
121
+ Kullanıcı açıkça "DS değiştir" demediği sürece aynı DS'i kullan.
122
+ ```
123
+
124
+ **Bypass:** Kullanıcı "DS'siz devam et" derse `Status: DS bypass mode` olarak işaretle. Token binding kuralı esnetilir ama yine de kullanıcıya hardcoded değer kullandığını bildir.
125
+
126
+ Detay: [figma-canvas-ops SKILL Section 0 — Design System Context](../figma-canvas-ops/SKILL.md#0-design-system-context-zorunlu--v180).
127
+
46
128
  ### Step 1: Plugin Bağlantısını Doğrula
47
129
 
48
130
  ```
@@ -109,13 +191,33 @@ Proje kökünde `.fmcp-brand-profile.json` varsa:
109
191
 
110
192
  Üç şey gerekiyor: **bileşenler**, **variable'lar**, **stiller**.
111
193
 
112
- **CACHE-FIRST KURALI (ZORUNLU):** Figma API'ye gitmeden önce `.claude/libraries/<ds>.md` dosyasını kontrol et. Cache varsa:
113
- - Text style key'leri cache'den oku (API çağrısı yapma)
114
- - Variable key'leri cache'den oku
115
- - Component key'leri + override notları → cache'den oku
116
- - Font ailesi → cache'den oku
194
+ **⚠️ MCP TOOL SEÇİMİ (v1.8.0+):**
195
+ - F-MCP plugin bağlıysa **`figma_search_assets`** veya **`figma_get_library_variables`** kullan
196
+ - Resmi Figma MCP'nin **`search_design_system`** tool'unu **ÇAĞIRMA** — "Resource links not supported" / "file could not be accessed" hatası verir
197
+ - Detay: FMCP_INSTRUCTIONS "TOOL SELECTION" bölümü
198
+
199
+ **CACHE-FIRST KURALI (MUTLAK ZORUNLU - PRE-FLIGHT BLOCKER):**
200
+
201
+ Figma API'ye gitmeden önce `.claude/design-systems/<library-id>/` cache'ini kontrol et:
202
+
203
+ ```
204
+ 1. Read .claude/design-systems/<library-id>/_meta.md
205
+
206
+ ✅ Var, sync güncel (24h içinde) → cache'leri kullan, devam et
207
+ ❌ Yok / sync eski / yarım kalmış → Step 3a-3d'yi ÇALIŞTIR ve cache'i doldur,
208
+ ANCAK O ZAMAN ekran üretimine başla
209
+ ```
210
+
211
+ **Cache eksik veya stale ise ekran üretimi BAŞLAYAMAZ** — önce keşif/cache, sonra üretim. Bu, hardcoded fallback'leri ve tekrar tekrar API çağrılarını engeller.
212
+
213
+ - Text style key'leri → `.claude/design-systems/<library-id>/tokens.md` (text style key cache)
214
+ - Variable key'leri → `.claude/design-systems/<library-id>/tokens.md`
215
+ - Component key'leri + override notları → `.claude/design-systems/<library-id>/components.md`
216
+ - Font ailesi + available weights → `.claude/design-systems/<library-id>/tokens.md` (Font Weights bölümü)
217
+
218
+ Cache doldurulduktan sonra her oturumda 24 saat boyunca tekrar API'ye gitmeden okunabilir. **Bu, sonraki oturumlarda token tüketimini %60-70 düşürür.**
117
219
 
118
- Cache yoksa veya eksikse keşif yap, sonucu cache'e yaz. **Bu, sonraki oturumlarda token tüketimini %60-70 düşürür.**
220
+ **Cache Invalidation:** Cache dosyasının başına `lastUpdated: YYYY-MM-DD HH:mm` ekle. 24 saatten eski cache'ler otomatik yenilenmelidir. Kütüphane güncellendiğinde key'ler değişebilir.
119
221
 
120
222
  #### Kütüphane Cache Şablonu
121
223
 
@@ -201,27 +303,83 @@ Text style ve effect style'ları not al.
201
303
  Ekran oluşturmadan önce kullanılacak tüm DS token'larının **variable key'lerini** topla. Bu adım atlanamaz.
202
304
 
203
305
  1. **Kütüphane dosyasını oku:** `.claude/libraries/` dizinindeki kütüphane dosyasından font ailesi, variable collection ve text style bilgilerini al.
204
- 2. **DS dosyasında variable key'lerini çek:** Ekranda kullanılacak renk, spacing, text style token'larının key'lerini DS dosyasında `figma_execute` ile oku:
306
+ 2. **HEDEF dosyada variable key'lerini çek** (DS dosyasına bağlanmak GEREKMEZ):
307
+ ```
308
+ figma_get_library_variables({ libraryName: "❖ SUI" })
309
+ ```
310
+ Veya `figma_execute` ile:
205
311
  ```js
206
- // DS dosyasında çalıştır (fileKey = DS dosyasının file key'i)
207
- const varIds = ["VariableID:...", "VariableID:..."];
208
- const result = [];
209
- for (const id of varIds) {
210
- const v = await figma.variables.getVariableByIdAsync(id);
211
- if (v) result.push({ name: v.name, key: v.key, type: v.resolvedType });
312
+ // HEDEF dosyada çalıştır DS dosyası değil!
313
+ var cols = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
314
+ var target = cols.filter(function(c) { return c.libraryName === "❖ SUI"; });
315
+ var results = [];
316
+ for (var ci = 0; ci < target.length; ci++) {
317
+ var vars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(target[ci].key);
318
+ for (var vi = 0; vi < vars.length; vi++) {
319
+ results.push({ name: vars[vi].name, key: vars[vi].key, type: vars[vi].resolvedType, collection: target[ci].name });
320
+ }
212
321
  }
213
- return result;
322
+ return results;
214
323
  ```
215
- 3. **Text style ID'lerini çek:** DS dosyasında text style'ları al:
324
+ 3. **Text style key'lerini çek:** Kütüphane cache'inde key varsa oku. Yoksa REST API ile DS dosyasından: `figma_rest_api GET /v1/files/{DS_FILE_KEY}/styles`
325
+ Alternatif: Hedef dosyada zaten import edilmiş style'lar:
216
326
  ```js
217
- // DS dosyasında çalıştır
218
- const styles = await figma.getLocalTextStylesAsync();
219
- return styles.map(s => ({ id: s.id, name: s.name, key: s.key }));
327
+ var styles = await figma.getLocalTextStylesAsync();
328
+ return styles.map(function(s) { return { id: s.id, name: s.name, key: s.key }; });
220
329
  ```
221
- 4. **Font ailesi:** Kütüphane dosyasındaki `Font Ailesi` alanından oku. Bulunamazsa kullanıcıya sor. Kullanıcı "sen seç" derse `Inter` kullan.
330
+ 4. **Font ailesi:** Kütüphane dosyasındaki `Font Ailesi` alanından oku. Bulunamazsa DS text style'larından font bilgisini çıkar. Kullanıcıya sor. Kullanıcı "sen seç" derse VE DS fontu bulunamadıysa `Inter` kullan.
222
331
 
223
332
  Bu adımda toplanan key'ler, sonraki adımlarda `importVariableByKeyAsync` ile hedef dosyaya import edilecek.
224
333
 
334
+ ### Step 3.5: Clone Tool'u Tuzağı — Ne Zaman Clone, Ne Zaman Sıfırdan İnşa (v1.8.2+ ZORUNLU)
335
+
336
+ `figma_clone_screen_to_device` tool'u v1.8.1'de eklendi ama **sadece dar bir use-case için** kullanılmalıdır. Yanlış kullanım, benchmark'ın mevcut yanlışlıklarını (hardcoded rectangle, eksik token binding, non-responsive layout) kopyalayarak disiplin ihlaline yol açar.
337
+
338
+ #### Karar Matrisi
339
+
340
+ | Kullanıcı isteği | Doğru yaklaşım | Tool |
341
+ |---|---|---|
342
+ | "Aynı ekranı iPhone 17'ye migrate et" (sadece boyut değişir) | Clone | `figma_clone_screen_to_device` |
343
+ | "Aynı DS ile benzer ekran" (tek varyant) | Clone + validate | `figma_clone_screen_to_device` + Step 6.5 |
344
+ | **"3 farklı alternatif tasarım"** | **Build from scratch** ⭐ | `figma_execute` + Step 4-5 |
345
+ | **"Hero Card varyasyonu yap"** | **Build from scratch** | `figma_execute` + Step 4-5 |
346
+ | **"Yeni ekran sıfırdan"** | **Build from scratch** | `figma_execute` + Step 4-5 |
347
+ | **"Benchmark'tan ilham al, daha iyisini yap"** | **Build from scratch** (benchmark = inspiration only) | `figma_execute` + Step 4-5 |
348
+ | "Mevcut ekranda DS uyumunu düzelt" | Apply-DS workflow | `apply-figma-design-system` SKILL |
349
+
350
+ #### Kullanıcının Gerçek İstediği Nedir?
351
+
352
+ Kullanıcı "3 alternatif tasarım" dediğinde **neredeyse her zaman** istediği:
353
+ - Farklı layout/renk/tipografi yaklaşımları
354
+ - Her biri gerçekten **AYRI** (sadece isim değil, içerik de)
355
+ - Hepsinde DS uyumu (instance + token binding)
356
+ - Hepsi responsive (auto-layout + FILL sizing)
357
+
358
+ Bu **clone'un kapsamında DEĞİL**. Clone sadece "kopyala, isim değiştir" yapar. Sonuçta **3 identik kopya** + farklı isimler olur. Bu kullanıcının istediği **GERÇEK varyasyon değildir**.
359
+
360
+ #### Doğru Akış: Build-from-Scratch (Step 4-5)
361
+
362
+ Benchmark varsa:
363
+ 1. **Step 3.x'te benchmark'ı `figma_get_design_context` ile OKU** — yapısal anlayış için
364
+ 2. Benchmark'ta kullanılan SUI instance'ları not al (NavigationTopBar, PillTabs, vb.)
365
+ 3. Benchmark'ta **yanlış olan şeyleri kopyalama**:
366
+ - Hardcoded rectangle separator'lar → DS Divider component kullan
367
+ - Non-responsive iç frame'ler → auto-layout FILL'e çevir
368
+ - Missing token bindings → her yerde `setBoundVariable*` kullan
369
+ 4. **Step 4 + Step 5 akışını takip et** — sıfırdan, SUI kurallarıyla
370
+ 5. Her alternatif için benzersiz layout çözümü:
371
+ - Hero Card: bakiye kartı büyütülmüş, quick actions altta sade
372
+ - Liste Odaklı: hesap listesi dominant, özet sağ-altta
373
+ - Dark Header: root fill `Global/primary/default`, text'ler `on-primary` token
374
+ 6. Step 6.5 validate → skor ≥ 80
375
+
376
+ #### Kısıtlama Kuralı
377
+
378
+ **Kullanıcı şu kelimelerden birini kullandıysa → `figma_clone_screen_to_device` KULLANMA:**
379
+ - "alternatif", "varyasyon", "farklı", "yeni", "tasarla", "iyileştir", "redesign"
380
+
381
+ Intent Router bu kelimeleri algıladığında `approach = build-from-scratch` otomatik set eder ve Claude'u Step 4-5 rotasına yönlendirir.
382
+
225
383
  ### Step 4: Boş Alan Bul ve Wrapper Frame Oluştur
226
384
 
227
385
  ```js
@@ -409,6 +567,44 @@ Screen: VERTICAL, counterAxis=CENTER, layoutSizingVertical=HUG
409
567
 
410
568
  **Mode adı eşleşmesi DİKKAT:** `indexOf("Web")` "Mobil & Web Mobil"i de yakalar. `indexOf("Desktop")` kullan.
411
569
 
570
+ ### Step 5.17: Quality Gate — Her Bölüm Yazıldıktan Sonra (ZORUNLU — v1.8.2+)
571
+
572
+ Her bölüm (`figma.createFrame()` sonrası) için **aşağıdaki checklist ZORUNLU**. Herhangi biri ❌ ise → bölümü **yeniden yaz**. Claude bu checklist'i kendi kendine uygulamakla yükümlüdür.
573
+
574
+ ```
575
+ [ ] Frame'in layoutMode'u atandı mı? (ASLA "NONE" olmamalı — HORIZONTAL veya VERTICAL)
576
+ [ ] primaryAxisSizingMode doğru mu? (Hug: AUTO, Fixed width: FIXED)
577
+ [ ] counterAxisSizingMode doğru mu?
578
+ [ ] Tüm fills setBoundVariableForPaint ile DS token'a bağlı mı? (hardcoded SOLID YASAK)
579
+ [ ] Tüm padding (top/bottom/left/right) setBoundVariable ile DS spacing token'a bağlı mı?
580
+ [ ] itemSpacing setBoundVariable ile DS spacing token'a bağlı mı?
581
+ [ ] cornerRadius (varsa) setBoundVariable ile DS radius token'a bağlı mı?
582
+ [ ] Her text node setTextStyleIdAsync ile DS text style'a bağlı mı? (ASLA sadece fontSize hardcoded)
583
+ [ ] Text fills setBoundVariableForPaint ile DS text color token'a bağlı mı?
584
+ [ ] Bölüm içinde en az 1 DS INSTANCE var mı? (importComponentByKeyAsync ile).
585
+ İstisna: Sadece text + frame olan bölümler (ör. başlık row) — bu durumda yine spacing/padding/renk token'ları zorunlu.
586
+ [ ] Tüm child'lar appendChild sonrası layoutSizingHorizontal = "FILL" mi? (text istisna: HUG)
587
+ [ ] Hiçbir node'un fills'i raw hex literal ile atandı mı? (grep: `{r:`, `color:` literal)
588
+ ```
589
+
590
+ **Otomatik kontrol örneği:**
591
+
592
+ ```js
593
+ // Her createFrame sonrası Claude bu kontrolü yapar:
594
+ if (frame.layoutMode === "NONE") throw new Error("Quality Gate FAIL: NO_AUTO_LAYOUT");
595
+ if (!frame.boundVariables || !frame.boundVariables.paddingLeft) {
596
+ console.warn("Quality Gate WARN: padding token binding eksik");
597
+ }
598
+ ```
599
+
600
+ **Quality Gate FAIL olursa ne yap?**
601
+ 1. Bölümü sil: `frame.remove()`
602
+ 2. Eksik token/instance'ı `figma_search_assets` + `figma_get_library_variables` ile ara
603
+ 3. Bölümü **yeniden yaz** — bu sefer tüm kuralları uyarak
604
+ 4. Tekrar kontrol et
605
+
606
+ **Skor hedef:** `figma_validate_screen` sonrası ≥ 80 (Step 6.5). Quality Gate çalışırsa validate zaten geçer.
607
+
412
608
  ### Step 5.2: Instance Override Rehberi (ZORUNLU)
413
609
 
414
610
  **Component PROPERTY (TEXT/BOOLEAN/VARIANT tipi) → `setProperties`:**
@@ -469,6 +665,56 @@ Estetik yön belirlendiyse (Step 2.5), bölüm inşa sırasında şu detaylar ek
469
665
 
470
666
  > **NOT:** Bu öneriler DS bileşen kütüphanesi varsa DS'nin izin verdiği ölçüde uygulanır. DS token'ları dışında hardcoded değer eklenmez.
471
667
 
668
+ ### Step 5.6: Dark Mode / Theme Variants Workflow (ZORUNLU — v1.9.0+)
669
+
670
+ Intent router `variants` input'unda "Light + Dark mode" seçildiyse (veya kullanıcı açıkça dark+light istiyorsa), Step 6'ya geçmeden önce bu alt adımı uygula.
671
+
672
+ **Ön koşul:** DS'de theme modlar tanımlı bir variable collection var. SUI için tipik: `Colors` collection + `Light` mode + `Dark` mode.
673
+
674
+ **Akış (4 adım):**
675
+
676
+ 1. **Light ekranı doğrula (Step 5 sonu):** Wrapper frame ID'sini al. Tüm fill/stroke/background'lar `setBoundVariableForPaint` ile bağlı olmalı (Step 5.17 Quality Gate zaten sağladı). Eğer hardcoded değer varsa Step 5'e dön, düzelt.
677
+
678
+ 2. **Klon oluştur:**
679
+ ```javascript
680
+ // figma_execute
681
+ const lightFrame = await figma.getNodeByIdAsync("<wrapper_id>");
682
+ const darkFrame = lightFrame.clone();
683
+ figma.currentPage.appendChild(darkFrame);
684
+ darkFrame.x = lightFrame.x + lightFrame.width + 80; // sağda, 80px boşluk
685
+ darkFrame.name = lightFrame.name + " — Dark";
686
+ return { darkFrameId: darkFrame.id };
687
+ ```
688
+
689
+ 3. **Dark mode'u klon frame'e uygula:**
690
+ ```javascript
691
+ // figma_execute (ayrı çağrı)
692
+ const collections = await figma.variables.getLocalVariableCollectionsAsync();
693
+ const colorCol = collections.find(c => c.name === "Colors" || c.name.toLowerCase().includes("color"));
694
+ if (!colorCol) throw new Error("Theme collection bulunamadı — DS'de mode tanımlı değil");
695
+ const darkMode = colorCol.modes.find(m => m.name.toLowerCase().includes("dark"));
696
+ if (!darkMode) throw new Error("Dark mode bulunamadı — DS tek modlu");
697
+
698
+ const darkFrame = await figma.getNodeByIdAsync("<darkFrameId>");
699
+ darkFrame.setExplicitVariableModeForCollection(colorCol, darkMode.modeId);
700
+ return { status: "dark mode applied", mode: darkMode.name };
701
+ ```
702
+
703
+ **Sihir burada:** `setExplicitVariableModeForCollection` ile tüm bound variable'lar otomatik olarak dark mode değerleri kullanır. Manuel swap gerekmez — tek bir API çağrısı tüm renkleri günceller. **Bu yüzden Step 5.17'de her fill/stroke mutlaka variable'a bağlı olmalı** — hardcoded kalanlar dark mode'da güncellenmez, light rengini taşır.
704
+
705
+ 4. **Her iki frame'i ayrı validate et:**
706
+ ```javascript
707
+ figma_validate_screen(nodeId: <lightFrameId>, minScore: 80)
708
+ figma_validate_screen(nodeId: <darkFrameId>, minScore: 80)
709
+ ```
710
+ İkisi de ≥80 olmalı. Biri fail ederse hardcoded değerler kaldı demektir — Step 5.17 Quality Gate'e dön.
711
+
712
+ **Edge case:** DS'de dark mode yoksa (sadece light), `variants: "Light + Dark"` seçimi kullanıcıya hata raporla: "Aktif DS'de dark mode tanımlı değil, sadece light üretildi. Dark mode için DS'nin `Colors` collection'ında `Dark` modu eklenmelidir."
713
+
714
+ **Responsive + theme kombinasyonu:** `variants: ["Light + Dark", "Mobile + Web"]` seçilirse matris oluşur (Light+Mobile / Light+Web / Dark+Mobile / Dark+Web = 4 frame). Her biri için ayrı wrapper, ayrı mode/device binding, ayrı validate. Turn budget'e dikkat — 4 frame için 4 turn harca (inter-screen checkpoint gate Step 6.6).
715
+
716
+ **Known limitation:** `figma_validate_screen` skorlama algoritması **dark mode variable binding coverage'ını ayrıca ölçmez** (plugin-side: f-mcp-plugin/code.js). Dark frame'de hardcoded renk kalmış olsa bile skor ≥80 alabilir. Bu yüzden Step 5.17 Quality Gate ve Step 5.6 adım 4'teki manuel binding kontrolü zorunludur — scora tek başına güvenme.
717
+
472
718
  ### Step 6: Görsel Doğrulama
473
719
 
474
720
  ```
@@ -489,6 +735,123 @@ Screenshot'ı incele:
489
735
 
490
736
  Sorun varsa hedefli `figma_execute` ile düzelt.
491
737
 
738
+ ### Step 6.5: Self-Audit Mandate (ZORUNLU — v1.8.1+)
739
+
740
+ **Ekranı kullanıcıya sunmadan ÖNCE kendi kendini denetle.** Bu adım **atlanamaz** — screenshot yeterli değil çünkü Claude görsel olarak "güzel" görünen ama token/bileşen disiplininden uzak ekranları fark edemez.
741
+
742
+ #### Adım 1 — `figma_validate_screen` çağır
743
+
744
+ ```
745
+ figma_validate_screen(nodeId="wrapper-frame-id", expectedDs="❖ SUI", minScore=80)
746
+ ```
747
+
748
+ Tool şunu döner:
749
+ ```json
750
+ {
751
+ "score": 92,
752
+ "passed": true,
753
+ "minScore": 80,
754
+ "breakdown": {
755
+ "instanceCoverage": 85,
756
+ "libraryInstanceCount": 7,
757
+ "autoLayoutCoverage": 100,
758
+ "tokenBindingCoverage": 90
759
+ },
760
+ "violations": [],
761
+ "recommendation": "Score 92/100 passed minimum 80. Screen is DS-compliant."
762
+ }
763
+ ```
764
+
765
+ #### Adım 2 — Skor değerlendirmesi
766
+
767
+ | Skor | Karar | Davranış |
768
+ |---|---|---|
769
+ | **≥ 80** | ✅ Passed | Kullanıcıya sun, rapor et |
770
+ | **60-79** | ⚠️ Kısmi | Violations listesini oku, targeted fix'ler uygula, tekrar validate et |
771
+ | **< 60** | ❌ Failed | **Ekranı sil** (`figma_execute` → `node.remove()`), Step 3-5'e dön, DS bileşenleriyle yeniden inşa et |
772
+
773
+ #### Adım 3 — Retry Loop (max 3 deneme)
774
+
775
+ Eğer ilk denemede score < 80 ise:
776
+ 1. Violations listesini oku (en kritik 5'i)
777
+ 2. Her bir violation için `figma_execute` ile targeted fix uygula:
778
+ - `HARDCODED_FILL` → `figma_bind_variable` ile binding ekle
779
+ - `NO_AUTO_LAYOUT` → `layoutMode = "VERTICAL"` ekle
780
+ 3. Tekrar `figma_validate_screen` çağır
781
+ 4. **Max 3 deneme.** 3. denemede de fail ise:
782
+ - Ekranı sil
783
+ - Kullanıcıya rapor et: "3 denemede de minimum skoru yakalayamadım. Muhtemel sebepler: [list]. Elle düzeltmek mi, farklı yaklaşım mı denemek istersiniz?"
784
+
785
+ #### Adım 4 — Pass sonrası raporlama
786
+
787
+ Validation passed ise kullanıcıya özet çıkar:
788
+ ```
789
+ ✅ Ekran hazır: "Vadesiz TL - iPhone 17"
790
+ 📊 DS Compliance Score: 92/100
791
+ 🧩 Library Instances: 7
792
+ 🎨 Token Bindings: 24
793
+ 📐 Auto-Layout Coverage: 100%
794
+ ⏱️ Süre: 18 saniye
795
+ ```
796
+
797
+ #### Anti-patterns (Self-Audit atlamak)
798
+
799
+ ❌ **YANLIŞ:** "Screenshot güzel görünüyor, validate'e gerek yok" → Bu bir **disiplin kaçırmasıdır**
800
+ ✅ **DOĞRU:** Screenshot güzel olsa bile validate çalıştır. Token binding eksikliği gözle görülmez.
801
+
802
+ ❌ **YANLIŞ:** Score 75 → "yeterince iyi, kullanıcıya sun"
803
+ ✅ **DOĞRU:** Score < 80 → retry loop, ekranı düzelt
804
+
805
+ ❌ **YANLIŞ:** Self-audit'i opsiyonel sayma
806
+ ✅ **DOĞRU:** generate-figma-screen akışının **tamamlanma koşulu** bu adımdır. Validate çalıştırılmadan akış TAMAMLANMIŞ sayılmaz.
807
+
808
+ ### Step 6.6: Inter-Screen Checkpoint Gate + Turn Budget (ZORUNLU — v1.8.2+)
809
+
810
+ Kullanıcı birden fazla alternatif istediğinde (N > 1), her alternatif **ayrı bir turn** olmalıdır. Tek turn'de 2+ alternatif yapmak **YASAK** — tool-use limit'e takılır, chat donar.
811
+
812
+ #### Turn Budget Kuralı
813
+
814
+ **Her turn'ün bütçesi:**
815
+ - Maksimum **90 saniye** toplam süre
816
+ - Maksimum **2 başarısız tool call** (timeout/error)
817
+
818
+ Eğer turn içinde:
819
+ - 2 başarısız tool call (timeout/error) olursa, **VEYA**
820
+ - 60+ saniye geçti ve sonuç gelmediyse
821
+
822
+ → **Turn'ü "FAILED" olarak işaretle.** Orphan cleanup uygula (fmcp-intent-router Tool Failure Recovery Protocol). Kullanıcıya checkpoint sorusunu sor.
823
+
824
+ #### Checkpoint Gate (Her Turn Sonrası)
825
+
826
+ Alternatif N tamamlandığında (başarılı veya fail), kullanıcıya `AskUserQuestion` ile sor:
827
+
828
+ ```
829
+ ✅/⚠️ Alternatif N/M ({name}) tamamlandı
830
+ Node ID: 173:xxxxx
831
+ Skor: XX/100
832
+ Library instances: X
833
+ Token bindings: Y
834
+ Süre: Xs
835
+
836
+ Ne yapayım?
837
+ [✅ Beğendim, Alternatif N+1'e geç]
838
+ [✏️ Revize et (ne değişsin söyle)]
839
+ [🛑 Dur, bu yeter]
840
+ ```
841
+
842
+ **Kullanıcı yanıtı gelmeden bir sonraki alternatife GEÇME.** Turn boundary kuralı budur.
843
+
844
+ #### Yasaklar
845
+
846
+ ❌ **YANLIŞ:** Tek turn'de 3 alternatifi de yap, en sonda tek özet
847
+ ✅ **DOĞRU:** Her alternatif ayrı turn, her biri sonunda checkpoint
848
+
849
+ ❌ **YANLIŞ:** Turn içinde 3+ retry (sonsuz döngü)
850
+ ✅ **DOĞRU:** 2 retry max, sonra Turn FAILED + kullanıcıya sor
851
+
852
+ ❌ **YANLIŞ:** Alternatif N başarısız, sessizce N+1'e geç
853
+ ✅ **DOĞRU:** N başarısız olunca orphan cleanup + rapor + checkpoint
854
+
492
855
  ### Step 7: Güncelleme Senaryosu
493
856
 
494
857
  Mevcut bir ekranı güncellerken:
@@ -5,6 +5,38 @@ metadata:
5
5
  mcp-server: user-figma-mcp-bridge
6
6
  personas:
7
7
  - uidev
8
+ required_inputs:
9
+ - name: source_node_id
10
+ type: string
11
+ question: "Hangi Figma node'unu kodlayalım? (node ID veya Figma URL)"
12
+ required: true
13
+ - name: target_platform
14
+ type: enum
15
+ options:
16
+ - "iOS (SwiftUI)"
17
+ - "iOS (UIKit)"
18
+ - "Android (Jetpack Compose)"
19
+ - "Android (XML)"
20
+ - "Web (React + TypeScript)"
21
+ - "Web (Vue)"
22
+ - "Web (vanilla HTML/CSS)"
23
+ question: "Hangi platform için kod üretelim?"
24
+ required: true
25
+ - name: output_dir
26
+ type: string
27
+ question: "Kod nereye yazılsın? (örn: ./src/components veya 'chat' - çıktıyı inline göster)"
28
+ required: false
29
+ default: "chat"
30
+ - name: include_tests
31
+ type: boolean
32
+ question: "Unit test dosyaları da üretilsin mi?"
33
+ required: false
34
+ default: false
35
+ - name: use_existing_components
36
+ type: boolean
37
+ question: "Mevcut proje component'lerini kullanıp genişleteyim mi, yoksa sıfırdan mı?"
38
+ required: false
39
+ default: true
8
40
  ---
9
41
 
10
42
  # Implement Design (Multi-Platform)