@atezer/figma-mcp-bridge 1.9.6 → 1.9.8

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.
@@ -6,7 +6,7 @@
6
6
 
7
7
  // v1.8.0+: Plugin version reported in WebSocket "ready" handshake.
8
8
  // Keep in sync with package.json and src/core/version.ts.
9
- var FMCP_PLUGIN_VERSION = '1.9.6';
9
+ var FMCP_PLUGIN_VERSION = '1.9.8';
10
10
 
11
11
  /**
12
12
  * v1.9.6: Post-execute scan — figma_execute sonrasında oluşturulan node'ları
@@ -2939,6 +2939,211 @@ figma.ui.onmessage = async (msg) => {
2939
2939
  }
2940
2940
  }
2941
2941
 
2942
+ // ============================================================================
2943
+ // CREATE_MINI_DS (v1.9.7) — Boş dosyada minimal Design System kur.
2944
+ // 2-phase batched: Phase 1 = Variable Collections + Variables + Text Styles
2945
+ // Phase 2 = Components (Button/Input/Card)
2946
+ // Her phase ayrı promise chain, timeout 30s içinde tamamlanır.
2947
+ // ============================================================================
2948
+ else if (msg.type === 'CREATE_MINI_DS') {
2949
+ try {
2950
+ console.log('🌉 [F-MCP v1.9.7] CREATE_MINI_DS starting...');
2951
+
2952
+ var primaryColor = msg.primaryColor || '#1464FF';
2953
+ var fontFamily = msg.fontFamily || 'Inter';
2954
+ var dsName = msg.name || 'Mini DS';
2955
+ var includeComponents = msg.includeComponents !== false;
2956
+
2957
+ // ---------- Hex → RGB ----------
2958
+ function hexToRgb(hex) {
2959
+ var h = hex.replace('#', '');
2960
+ if (h.length === 3) h = h[0]+h[0]+h[1]+h[1]+h[2]+h[2];
2961
+ var r = parseInt(h.slice(0,2), 16) / 255;
2962
+ var g = parseInt(h.slice(2,4), 16) / 255;
2963
+ var b = parseInt(h.slice(4,6), 16) / 255;
2964
+ return { r: r, g: g, b: b };
2965
+ }
2966
+ function mix(a, b, t) { return { r: a.r*(1-t)+b.r*t, g: a.g*(1-t)+b.g*t, b: a.b*(1-t)+b.b*t }; }
2967
+
2968
+ var primaryRgb = hexToRgb(primaryColor);
2969
+ var black = { r: 0, g: 0, b: 0 };
2970
+ var white = { r: 1, g: 1, b: 1 };
2971
+
2972
+ // ---------- PHASE 1: Variable Collections + Variables + Text Styles ----------
2973
+ var colorCollection = figma.variables.createVariableCollection(dsName + ' — Colors');
2974
+ var modeId = colorCollection.defaultModeId;
2975
+ var colorVars = {};
2976
+
2977
+ function addColorVar(name, rgb) {
2978
+ var v = figma.variables.createVariable(name, colorCollection, 'COLOR');
2979
+ v.setValueForMode(modeId, rgb);
2980
+ colorVars[name] = v;
2981
+ }
2982
+
2983
+ addColorVar('primary/default', primaryRgb);
2984
+ addColorVar('primary/hover', mix(primaryRgb, black, 0.1));
2985
+ addColorVar('primary/disabled', mix(primaryRgb, white, 0.5));
2986
+ addColorVar('bg/level-0', white);
2987
+ addColorVar('bg/level-1', { r: 0.97, g: 0.97, b: 0.98 });
2988
+ addColorVar('bg/level-2', { r: 0.93, g: 0.94, b: 0.96 });
2989
+ addColorVar('text/primary', { r: 0.1, g: 0.1, b: 0.1 });
2990
+ addColorVar('text/secondary', { r: 0.4, g: 0.4, b: 0.45 });
2991
+ addColorVar('text/on-primary', white);
2992
+ addColorVar('success/default', { r: 0.18, g: 0.73, b: 0.39 });
2993
+ addColorVar('error/default', { r: 0.91, g: 0.22, b: 0.27 });
2994
+ addColorVar('warning/default', { r: 0.98, g: 0.69, b: 0.13 });
2995
+
2996
+ var sizingCollection = figma.variables.createVariableCollection(dsName + ' — Sizing');
2997
+ var sizingMode = sizingCollection.defaultModeId;
2998
+ var sizingVars = {};
2999
+ function addSizingVar(name, value) {
3000
+ var v = figma.variables.createVariable(name, sizingCollection, 'FLOAT');
3001
+ v.setValueForMode(sizingMode, value);
3002
+ sizingVars[name] = v;
3003
+ }
3004
+ addSizingVar('spacing/xs', 4);
3005
+ addSizingVar('spacing/sm', 8);
3006
+ addSizingVar('spacing/md', 16);
3007
+ addSizingVar('spacing/lg', 24);
3008
+ addSizingVar('spacing/xl', 32);
3009
+ addSizingVar('radius/sm', 4);
3010
+ addSizingVar('radius/md', 8);
3011
+ addSizingVar('radius/lg', 16);
3012
+
3013
+ // Text Styles (font loading required)
3014
+ await figma.loadFontAsync({ family: fontFamily, style: 'Semi Bold' }).catch(function() {});
3015
+ await figma.loadFontAsync({ family: fontFamily, style: 'Regular' }).catch(function() {});
3016
+
3017
+ function createTextStyle(name, fontSize, lineHeight, fontStyle) {
3018
+ var ts = figma.createTextStyle();
3019
+ ts.name = name;
3020
+ try {
3021
+ ts.fontName = { family: fontFamily, style: fontStyle };
3022
+ ts.fontSize = fontSize;
3023
+ ts.lineHeight = { unit: 'PIXELS', value: lineHeight };
3024
+ } catch (e) {
3025
+ console.warn('TextStyle ' + name + ' font set failed:', e.message);
3026
+ }
3027
+ return ts;
3028
+ }
3029
+
3030
+ var titleStyle = createTextStyle(dsName + '/Title/Large', 24, 32, 'Semi Bold');
3031
+ var bodyStyle = createTextStyle(dsName + '/Body/Default', 14, 20, 'Regular');
3032
+ var captionStyle = createTextStyle(dsName + '/Caption/Small', 12, 16, 'Regular');
3033
+
3034
+ console.log('🌉 [F-MCP v1.9.7] Phase 1 done — variables + text styles created');
3035
+
3036
+ // ---------- PHASE 2: Components ----------
3037
+ var componentIds = {};
3038
+ if (includeComponents) {
3039
+ // Button component
3040
+ var buttonFrame = figma.createFrame();
3041
+ buttonFrame.name = dsName + '/Button/Primary';
3042
+ buttonFrame.layoutMode = 'HORIZONTAL';
3043
+ buttonFrame.primaryAxisSizingMode = 'AUTO';
3044
+ buttonFrame.counterAxisSizingMode = 'AUTO';
3045
+ buttonFrame.primaryAxisAlignItems = 'CENTER';
3046
+ buttonFrame.counterAxisAlignItems = 'CENTER';
3047
+ buttonFrame.setBoundVariable('paddingLeft', sizingVars['spacing/md']);
3048
+ buttonFrame.setBoundVariable('paddingRight', sizingVars['spacing/md']);
3049
+ buttonFrame.setBoundVariable('paddingTop', sizingVars['spacing/sm']);
3050
+ buttonFrame.setBoundVariable('paddingBottom', sizingVars['spacing/sm']);
3051
+ buttonFrame.setBoundVariable('cornerRadius', sizingVars['radius/md']);
3052
+ buttonFrame.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: primaryRgb }, 'color', colorVars['primary/default'])];
3053
+
3054
+ var buttonText = figma.createText();
3055
+ try {
3056
+ buttonText.fontName = { family: fontFamily, style: 'Semi Bold' };
3057
+ buttonText.characters = 'Button';
3058
+ await buttonText.setTextStyleIdAsync(bodyStyle.id).catch(function() {});
3059
+ buttonText.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }, 'color', colorVars['text/on-primary'])];
3060
+ } catch (e) { console.warn('Button text fail:', e.message); }
3061
+ buttonFrame.appendChild(buttonText);
3062
+ var buttonComp = figma.createComponentFromNode(buttonFrame);
3063
+ componentIds.button = buttonComp.id;
3064
+
3065
+ // Input component
3066
+ var inputFrame = figma.createFrame();
3067
+ inputFrame.name = dsName + '/Input/Default';
3068
+ inputFrame.resize(240, 40);
3069
+ inputFrame.layoutMode = 'HORIZONTAL';
3070
+ inputFrame.primaryAxisAlignItems = 'CENTER';
3071
+ inputFrame.setBoundVariable('paddingLeft', sizingVars['spacing/md']);
3072
+ inputFrame.setBoundVariable('paddingRight', sizingVars['spacing/md']);
3073
+ inputFrame.setBoundVariable('cornerRadius', sizingVars['radius/md']);
3074
+ inputFrame.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 0.97, g: 0.97, b: 0.98 } }, 'color', colorVars['bg/level-1'])];
3075
+ inputFrame.strokes = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 0.9, g: 0.9, b: 0.92 } }, 'color', colorVars['bg/level-2'])];
3076
+ inputFrame.strokeWeight = 1;
3077
+
3078
+ var placeholder = figma.createText();
3079
+ try {
3080
+ placeholder.fontName = { family: fontFamily, style: 'Regular' };
3081
+ placeholder.characters = 'Placeholder';
3082
+ await placeholder.setTextStyleIdAsync(bodyStyle.id).catch(function() {});
3083
+ placeholder.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 0.4, g: 0.4, b: 0.45 } }, 'color', colorVars['text/secondary'])];
3084
+ } catch (e) {}
3085
+ inputFrame.appendChild(placeholder);
3086
+ var inputComp = figma.createComponentFromNode(inputFrame);
3087
+ componentIds.input = inputComp.id;
3088
+
3089
+ // Card component
3090
+ var cardFrame = figma.createFrame();
3091
+ cardFrame.name = dsName + '/Card/Default';
3092
+ cardFrame.layoutMode = 'VERTICAL';
3093
+ cardFrame.primaryAxisSizingMode = 'AUTO';
3094
+ cardFrame.counterAxisSizingMode = 'AUTO';
3095
+ cardFrame.setBoundVariable('paddingLeft', sizingVars['spacing/lg']);
3096
+ cardFrame.setBoundVariable('paddingRight', sizingVars['spacing/lg']);
3097
+ cardFrame.setBoundVariable('paddingTop', sizingVars['spacing/lg']);
3098
+ cardFrame.setBoundVariable('paddingBottom', sizingVars['spacing/lg']);
3099
+ cardFrame.setBoundVariable('itemSpacing', sizingVars['spacing/sm']);
3100
+ cardFrame.setBoundVariable('cornerRadius', sizingVars['radius/lg']);
3101
+ cardFrame.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }, 'color', colorVars['bg/level-0'])];
3102
+ cardFrame.strokes = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 0.93, g: 0.94, b: 0.96 } }, 'color', colorVars['bg/level-2'])];
3103
+ cardFrame.strokeWeight = 1;
3104
+
3105
+ var cardTitle = figma.createText();
3106
+ try {
3107
+ cardTitle.fontName = { family: fontFamily, style: 'Semi Bold' };
3108
+ cardTitle.characters = 'Card title';
3109
+ await cardTitle.setTextStyleIdAsync(titleStyle.id).catch(function() {});
3110
+ cardTitle.fills = [figma.variables.setBoundVariableForPaint({ type: 'SOLID', color: { r: 0.1, g: 0.1, b: 0.1 } }, 'color', colorVars['text/primary'])];
3111
+ } catch (e) {}
3112
+ cardFrame.appendChild(cardTitle);
3113
+ var cardComp = figma.createComponentFromNode(cardFrame);
3114
+ componentIds.card = cardComp.id;
3115
+
3116
+ console.log('🌉 [F-MCP v1.9.7] Phase 2 done — 3 components created');
3117
+ }
3118
+
3119
+ figma.ui.postMessage({
3120
+ type: 'CREATE_MINI_DS_RESULT',
3121
+ requestId: msg.requestId,
3122
+ success: true,
3123
+ dsName: dsName,
3124
+ variableCollectionIds: { colors: colorCollection.id, sizing: sizingCollection.id },
3125
+ textStyleIds: { title: titleStyle.id, body: bodyStyle.id, caption: captionStyle.id },
3126
+ componentIds: componentIds,
3127
+ summary: {
3128
+ colorVariableCount: Object.keys(colorVars).length,
3129
+ sizingVariableCount: Object.keys(sizingVars).length,
3130
+ textStyleCount: 3,
3131
+ componentCount: Object.keys(componentIds).length,
3132
+ },
3133
+ hint: "v1.9.7 Mini DS hazir. Ekran kurmak icin figma_execute kullan: importVariableByKeyAsync + importComponentByKeyAsync ile key'leri al, instance + setBoundVariable yaparak olustur.",
3134
+ });
3135
+ } catch (error) {
3136
+ var errorMsg = error && error.message ? error.message : String(error);
3137
+ console.error('🌉 [F-MCP v1.9.7] CREATE_MINI_DS error:', errorMsg);
3138
+ figma.ui.postMessage({
3139
+ type: 'CREATE_MINI_DS_RESULT',
3140
+ requestId: msg.requestId,
3141
+ success: false,
3142
+ error: errorMsg,
3143
+ });
3144
+ }
3145
+ }
3146
+
2942
3147
  // ============================================================================
2943
3148
  // DELETE_NODE - Delete a node
2944
3149
  // ============================================================================
@@ -424,7 +424,7 @@
424
424
  window.__figmaFileName = null;
425
425
  // v1.8.0+: Plugin version reported in WebSocket "ready" handshake.
426
426
  // Keep in sync with package.json, src/core/version.ts, f-mcp-plugin/code.js.
427
- var FMCP_PLUGIN_VERSION = '1.9.6';
427
+ var FMCP_PLUGIN_VERSION = '1.9.8';
428
428
 
429
429
  // v1.9.2+ Startup log — Figma plugin iframe'de yeni kod yüklendiğini doğrulamak için.
430
430
  // Console'da bu log görünüyorsa plugin güncel. Görünmüyorsa iframe eski kopyayı tutuyor
@@ -778,11 +778,28 @@
778
778
  if (options.format) params.format = options.format; // PNG, JPG
779
779
  if (options.scale != null) params.scale = options.scale; // 1, 2, 4, etc.
780
780
  if (options.jpegQuality != null) params.jpegQuality = options.jpegQuality; // 30-100 (v1.8.0)
781
+ // v1.9.5 method selection params
782
+ if (options.returnMode) params.returnMode = options.returnMode;
783
+ if (options.regionStrategy) params.regionStrategy = options.regionStrategy;
784
+ if (options.maxRegions != null) params.maxRegions = options.maxRegions;
785
+ if (options.sliceHeight != null) params.sliceHeight = options.sliceHeight;
786
+ if (options.requestedSlices) params.requestedSlices = options.requestedSlices;
781
787
  }
782
788
  return window.sendPluginCommand('CAPTURE_SCREENSHOT', params, 30000)
783
789
  .catch(function(err) { return { success: false, error: err.message || String(err) }; });
784
790
  };
785
791
 
792
+ // v1.9.7: Create Mini DS — variables + text styles + components in one call
793
+ window.createMiniDs = (params) => {
794
+ return window.sendPluginCommand('CREATE_MINI_DS', {
795
+ primaryColor: params.primaryColor || '#1464FF',
796
+ fontFamily: params.fontFamily || 'Inter',
797
+ name: params.name || 'Mini DS',
798
+ includeComponents: params.includeComponents !== false,
799
+ }, 45000) // 45s — font loading + 3 component creation takes time
800
+ .catch(function(err) { return { success: false, error: err.message || String(err) }; });
801
+ };
802
+
786
803
  // Batch export nodes as SVG/PNG/JPG/PDF with base64
787
804
  window.batchExportNodes = (nodeIds, format, scale, svgOutlineText, svgIncludeId, svgSimplifyStroke) => {
788
805
  return window.sendPluginCommand('BATCH_EXPORT_NODES', {
@@ -1856,6 +1873,7 @@
1856
1873
  if (method === 'refreshVariables') return window.refreshVariables();
1857
1874
  if (method === 'getLocalComponents') return window.getLocalComponents(params.currentPageOnly, params.limit);
1858
1875
  if (method === 'searchLibraryAssets') return window.searchLibraryAssets(params.query, params.assetTypes, params.limit, params.currentPageOnly);
1876
+ if (method === 'getCodeConnectHints') return window.getCodeConnectHints(params.nodeIds, params.scanCurrentPage, params.maxNodes);
1859
1877
  if (method === 'instantiateComponent') return window.instantiateComponent(params.componentKey, params.options);
1860
1878
  if (method === 'setNodeDescription') return window.setNodeDescription(params.nodeId, params.description, params.descriptionMarkdown);
1861
1879
  if (method === 'captureScreenshot') return window.captureScreenshot(params.nodeId, params.options);
@@ -1881,6 +1899,7 @@
1881
1899
  if (method === 'setNodeCornerRadius') return window.setNodeCornerRadius(params.nodeId, params.radius);
1882
1900
  if (method === 'cloneScreenToDevice') return window.cloneScreenToDevice(params);
1883
1901
  if (method === 'validateScreen') return window.validateScreen(params);
1902
+ if (method === 'createMiniDs') return window.createMiniDs(params);
1884
1903
  if (method === 'cloneNode') return window.cloneNode(params.nodeId);
1885
1904
  if (method === 'deleteNode') return window.deleteNode(params.nodeId);
1886
1905
  if (method === 'renameNode') return window.renameNode(params.nodeId, params.newName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atezer/figma-mcp-bridge",
3
- "version": "1.9.6",
3
+ "version": "1.9.8",
4
4
  "description": "F-MCP ATezer: MCP server and Figma plugin bridge for Claude/Cursor. No REST token required.",
5
5
  "type": "module",
6
6
  "main": "dist/local-plugin-only.js",
@@ -27,7 +27,8 @@
27
27
  "LICENSE"
28
28
  ],
29
29
  "scripts": {
30
- "prepublishOnly": "npm run build && npm run validate:fmcp-skills",
30
+ "prepublishOnly": "npm run generate:embedded-skills && npm run build && npm run validate:fmcp-skills",
31
+ "generate:embedded-skills": "node scripts/generate-embedded-skills.mjs",
31
32
  "dev": "node dist/local-plugin-only.js",
32
33
  "build:run": "npm run build && node dist/local-plugin-only.js",
33
34
  "build": "tsc -p tsconfig.local.json",
@@ -28,18 +28,32 @@ Bu SKILL bu üç soruyu **upstream** çözer. Claude intent'i netleştirmeden hi
28
28
 
29
29
  Kullanıcı F-MCP ile ilgili herhangi bir talep yaptığında Claude bu 9 adımı SIRAYLA uygular. Hiçbir adım atlanmaz.
30
30
 
31
- ### 🚨 Adım 0 — DS GATE (v1.9.1+ MUTLAK İLK KAPI)
31
+ ### 🚨 Adım 0 — DS GATE + BLANK FILE CHECK (v1.9.7+ MUTLAK İLK KAPI)
32
32
 
33
33
  **Herhangi bir intent analysis veya figma_* tool çağrısından ÖNCE:**
34
34
 
35
- 1. `.claude/design-systems/active-ds.md` dosyasını oku
36
- 2. `Status:` alanını kontrol et:
37
- - **`✅ Aktif`** DS net, Adım 1'e (Intent Analysis) geç
38
- - **`❌ Henüz seçilmedi`** VEYA dosya yok **DUR**, hiçbir tool çağırma, kullanıcıya DS sorusu sor:
39
- > "Aktif bir design system belirlenmemiş. Hangi DS ile ilerlemek istersiniz?
40
- > (Mevcut seçenekler için library listesini vermenizi istiyorum, veya SUI gibi spesifik bir isim verin.)
41
- > Bu sorunun cevabı gelmeden hiçbir keşif / tarama yapmayacağım."
42
- 3. Kullanıcı cevabı gelince `active-ds.md`'yi güncelle (`Status: Aktif`, `Library Name: <isim>`), sonra Adım 1'e geç.
35
+ 1. `figma_get_status` çağır — plugin bağlı mı, response'ta `_bootstrap` varsa direktifleri OKU (v1.9.7)
36
+ 2. `.claude/design-systems/active-ds.md` dosyasını oku
37
+ 3. `Status:` alanını kontrol et:
38
+ - **`✅ Aktif`** → DS net, Blank File Sub-Check'e geç (madde 5)
39
+ - **`❌ Henüz seçilmedi`** VEYA dosya yok → kullanıcıya DS sorusu sor (madde 4)
40
+ 4. **DS Sorusu (klasik):** "Aktif bir design system belirlenmemiş. Hangi DS ile ilerlemek istersiniz? (SUI / Material / kendi library)"
41
+
42
+ 5. **BLANK FILE SUB-CHECK (v1.9.7, ZORUNLU):** `figma_get_design_system_summary` çağır.
43
+ - `components === 0 && componentSets === 0 && variableCollections.length === 0` ise **BOŞ DOSYA** tespit edildi.
44
+ - `_nextStep: "BLANK_FILE_DIALOG_REQUIRED"` response'ta görünüyorsa, **kullanıcıya 4 seçenek sun** (AskUserQuestion tek call, 4 option):
45
+ ```
46
+ Q: "Bu dosyada henüz Design System yok. Nasıl ilerleyelim?"
47
+ (a) Team library import — "Hangi library? SUI, Material 3, iOS HIG, veya kendi library'niz?"
48
+ (b) Mini DS kur otomatik — figma_create_mini_ds tool'u çağrılır (12 color + 8 sizing + 3 text style + Button/Input/Card)
49
+ (c) Referans DS kopyala — "Material 3 template / iOS HIG template"
50
+ (d) DS'siz ilerle — linter tolerant mode, hardcoded değerler kabul (explicit acceptance)
51
+ ```
52
+ - **Seçim yapılmadan `figma_execute createFrame` YASAK.** Claude ham createFrame denerse plugin `_DESIGN_SYSTEM_VIOLATIONS_BLOCKING` flag'i döndürür, retry zorunlu olur.
53
+ - Kullanıcı "(b)" derse Claude `figma_create_mini_ds({ primaryColor, fontFamily, name })` tek tool çağrısı yapar, sonra ekran üretimine geçer.
54
+ - Kullanıcı "(a)" derse Claude `figma_get_library_variables(libraryName)` ile listeleme yapar, seçenek sunar.
55
+
56
+ 6. Seçim sonrası `active-ds.md`'yi güncelle (`Status: ✅ Aktif`, `Library Name: <isim>`), sonra Adım 1'e geç.
43
57
 
44
58
  **Neden bu kadar katı:**
45
59
  - DS belirsizken `figma_search_assets`, `figma_get_file_data`, `figma_get_library_variables` çağırmak = kullanıcının istemediği library'leri enumere etmek = **token israfı + UX bozulması**
@@ -144,6 +144,32 @@ Benchmark/görselden DEĞER alma YASAK. Sadece NİYET: layout yönü, hiyerarşi
144
144
  2. **Content** — DS instance yerleşimi → screenshot → onay
145
145
  3. **Polish** — spacing, states, edge cases → son screenshot → audit
146
146
 
147
+ ### v1.9.7 Anti-Suppression Kuralı (MUTLAK — HARD enforcement)
148
+
149
+ BLOCKING response gördüğünde YASAK ifadeler:
150
+ - "bu projede geçerli değil"
151
+ - "dosyada DS yok, bu uyarılar önemsiz"
152
+ - "şimdilik skip edelim"
153
+ - "sonra düzeltiriz"
154
+ - "yine de devam ediyorum"
155
+
156
+ **Server seviyesi enforcement (Katman 3):** Claude BLOCKING flag gördükten sonra **aynı nodeId** üzerinde ikinci `figma_execute` mutation yaparsa server **HARD_ERROR** döndürür — tool fail eder, response değil error. Claude bunu skip edemez.
157
+
158
+ **Override escape hatch:** Sadece kullanıcı onayı ile `// FORCE_OVERRIDE` comment'i kod başına ekleyerek bypass edilebilir.
159
+
160
+ **ZORUNLU davranış BLOCKING gördüğünde:**
161
+ 1. BLOCKING'i OKU — hangi nodeId, hangi kategori? (_postExecuteViolations.violations)
162
+ 2. Kök nedeni analiz et:
163
+ - UNBOUND_FILL → setBoundVariableForPaint eksik
164
+ - UNBOUND_PADDING → setBoundVariable eksik
165
+ - UNBOUND_TEXTSTYLE → setTextStyleIdAsync eksik
166
+ - NO_INSTANCE_USAGE → DS component yok, import edilmeli
167
+ 3. Kullanıcıya sor SADECE şu koşullarda:
168
+ - DS gerçekten yok → Adım 0 Blank File sub-check'e dön (4 option)
169
+ - Override gerekli → "BLOCKING'i geçici bypass etmek istiyor musun?"
170
+ 4. Kullanıcı override isterse `// FORCE_OVERRIDE` comment ile kod tekrar çalıştır
171
+ 5. Aksi takdirde kodu DÜZELT ve retry
172
+
147
173
  ### v1.9.5 Discovery Budget Rule (SERT)
148
174
 
149
175
  - **Maks 3 discovery çağrısı** (figma_get_*, figma_search_*, figma_execute read-only) sonra plan sun.