@atezer/figma-mcp-bridge 1.9.6 → 1.9.7

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.
package/CHANGELOG.md CHANGED
@@ -12,6 +12,73 @@ Bu dosya [Keep a Changelog](https://keepachangelog.com/tr/1.1.0/) biçimine uygu
12
12
 
13
13
  Bu changelog'a ekleme öncesi sürümlerin tam ayrıntıları için `git log` kullanılabilir.
14
14
 
15
+ ## [1.9.7] - 2026-04-17
16
+
17
+ ### Zero-Click Enforcement — Blank File DS Gate + Mini DS + BLOCKING Suppression Prevention + Response Bootstrap
18
+
19
+ **Hedef:** Kullanıcı Claude Desktop'ta hiç setup yapmadan (Project Knowledge boş, başlangıç prompt'u kopyalamadan) sadece "figma linki + ödeme ekranı tasarla" diyince tüm agent + skill chain'in otomatik devreye girmesi. Başarı oranı: Claude Desktop %90-95, Claude Code %98-99.
20
+
21
+ **Motivasyon:** Gerçek test raporunda (boş Figma dosyası `KsERiwGveHKi0nTNh6oLIZ`, 17 Nisan) Claude:
22
+ - İlk soru olarak DS değil stil sordu (yanlış sıra)
23
+ - 0 component/0 variable tespit edince "sıfırdan çizeceğim" deyip ham createFrame + hardcoded değerlerle ekran kurdu
24
+ - FMCP linter BLOCKING döndürünce "dosyada DS yok, geçerli değil" deyip **bastırdı**. v1.9.6 flag'leri dil seviyesinde skip edildi.
25
+
26
+ **7 katmanlı çözüm:**
27
+
28
+ **Katman 1 — Skill: Blank File Detection (fmcp-intent-router Adım 0 genişletme)**
29
+ DS GATE artık dosya boşsa 4 seçenekli dialog sunuyor: (a) team library import, (b) mini DS auto-create, (c) template kopyala, (d) linter-off mode.
30
+
31
+ **Katman 2 — Yeni tool `figma_create_mini_ds`**
32
+ Tek tool çağrısı ile minimal DS: 12 color variable + 8 sizing variable + 3 text style + Button/Input/Card component. 2-phase batched (variables önce, components sonra). 45s timeout.
33
+
34
+ **Katman 3 — Server BLOCKING Suppression Prevention (src/core/blocking-tracker.ts YENİ)**
35
+ Session-level state tracker. figma_execute sonrası BLOCKING flag'li nodeId'leri kaydet. Sonraki execute aynı nodeId'ye mutation yaparsa server **HARD_ERROR** döndürür. Override için kod başına `// FORCE_OVERRIDE` comment gerekli. 5dk TTL. Dil seviyesinde skip imkansız.
36
+
37
+ **Katman 4 — Skill Anti-Suppression (fmcp-screen-orchestrator)**
38
+ Yasaklı dil kalıpları: "bu projede geçerli değil", "şimdilik skip edelim", "yine de devam". Claude pattern match ile kendi cevabını denetler.
39
+
40
+ **Katman 5 — Response Bootstrap (src/core/bootstrap-injector.ts YENİ)**
41
+ `figma_get_status` ilk call'da response'a `_bootstrap.critical_rules` (8 direktif) + `_bootstrap.anti_patterns` + `_nextStep` hints inject edilir. Claude her tool response'undan kuralları hatırlatılmış olarak alır.
42
+
43
+ **Katman 6 — Embedded Skills (src/core/embedded-skills.ts YENİ, auto-generated)**
44
+ Build-time script (`scripts/generate-embedded-skills.mjs`) 5 kritik skill'i (intent-router, orchestrator, canvas-ops, screen-recipes, project-rules) minify edip `EMBEDDED_SKILLS_SUMMARY` constant'ı üretir (~9K token). `figma_get_status` bootstrap'a gömülür. Kullanıcı Project Knowledge upload yapmasa bile Claude skill'i bilir. `prepublishOnly` hook'una eklendi.
45
+
46
+ **Katman 7 (NOT IMPLEMENTED IN 1.9.7) — MCP Resources/Prompts capability** v1.9.8'e bırakıldı (platform bağımlılığı çok yüksek).
47
+
48
+ **Version sync fix:** `src/core/version.ts` HARDCODED "1.9.2" → "1.9.7" (package.json ile senkron).
49
+
50
+ **Skill güncellemeleri:**
51
+ - `skills/fmcp-intent-router/SKILL.md` Adım 0 genişletildi (Blank File sub-check + 4-option dialog)
52
+ - `skills/fmcp-screen-orchestrator/SKILL.md` Anti-Suppression Kuralı eklendi (server HARD_ERROR referansı)
53
+
54
+ **Doc güncellemeleri:**
55
+ - `install/claude-desktop/HOW-TO-ENFORCE.md` Zero-Click Workflow bölümü eklendi + sürüm matrisi güncellendi
56
+ - Version bump: `package.json`, `f-mcp-plugin/code.js`, `f-mcp-plugin/ui.html` → 1.9.7
57
+ - `package.json` prepublishOnly hook'a `generate:embedded-skills` eklendi
58
+
59
+ **Plugin tarafı (f-mcp-plugin):**
60
+ - `code.js` CREATE_MINI_DS handler (214 satır) — Phase 1 (variables + text styles) + Phase 2 (Button/Input/Card components)
61
+ - `ui.html` `window.createMiniDs` dispatcher + method router (`createMiniDs` → CREATE_MINI_DS)
62
+ - `ui.html` `window.captureScreenshot` v1.9.5 params (returnMode/regionStrategy/maxRegions/sliceHeight/requestedSlices) eklendi — önceden eksik olan v1.9.5 bug fix bonus
63
+
64
+ **Regresyon:** Sıfır. Backwards compatible:
65
+ - `figma_get_status` response'una yeni `_bootstrap` field eklendi, eski alanlar korunur
66
+ - `figma_execute` suppression check BLOCKING flag olmadığı durumda skip edilir (temiz kod normal çalışır)
67
+ - Eski `figma_create_mini_ds` çağrısı olmayan kullanıcılar etkilenmez (yeni opsiyonel tool)
68
+
69
+ **Test matrisi:**
70
+ - TypeScript type-check: PASS
71
+ - Build: PASS
72
+ - `generate-embedded-skills.mjs`: 9176 token üretti (plan'da 6K hedefi %53 aşıldı — plugin size threshold 250KB'den uzak, kabul edilebilir)
73
+ - Embedded skills include: fmcp-intent-router (2399), screen-orchestrator (887), canvas-ops (2369), screen-recipes (2092), project-rules (1370)
74
+
75
+ **Kullanıcı için upgrade:**
76
+ ```bash
77
+ npm install -g @atezer/figma-mcp-bridge@1.9.7
78
+ bash scripts/cleanup-ports.sh # zombie temizle
79
+ ```
80
+ Claude Desktop + Figma plugin yeniden aç. Console'da `[F-MCP v1.9.7]` gör.
81
+
15
82
  ## [1.9.6] - 2026-04-17
16
83
 
17
84
  ### Post-Execute Scan + Negative Intent Detection
@@ -0,0 +1,68 @@
1
+ /**
2
+ * v1.9.7: BLOCKING Suppression Prevention — session-level state.
3
+ *
4
+ * Plan'daki Katman 3 implementasyonu. Amaç: Claude BLOCKING flag'i gördükten
5
+ * sonra aynı nodeId üzerinde ikinci bir mutation execute'ı denerse, server
6
+ * tarafında HARD_ERROR dönerek rasyonalize ederek skip'i engelle.
7
+ *
8
+ * Tespit mekanizması:
9
+ * - Her figma_execute sonrasında _designSystemViolations veya _postExecuteScan
10
+ * döndüyse, response'dan nodeId'leri ayıkla ve `recordBlocking()` çağır.
11
+ * - Sonraki figma_execute öncesi `checkSuppression(code)` çağırılır.
12
+ * - Kod aynı nodeId'yi içeriyorsa ve explicit `// FORCE_OVERRIDE` comment yoksa
13
+ * error döndürülür — tool fail olur, Claude skip edemez.
14
+ *
15
+ * Override escape hatch:
16
+ * - Kod başına `// FORCE_OVERRIDE` comment (`/^\s*\/\/\s*FORCE_OVERRIDE\b/m`)
17
+ * eklendiğinde suppression check bypass edilir. Kullanıcı explicit onay ile
18
+ * override edebilir, Claude sessizce atlayamaz.
19
+ *
20
+ * TTL: 5 dakika. Aynı oturumda yeni intent geldiğinde BLOCKING state zamanla
21
+ * temizlenir (false positive engellenir).
22
+ */
23
+ export type SuppressionCheckResult = {
24
+ /** If set, tool should return error (Claude suppression attempt detected) */
25
+ error?: string;
26
+ /** Convenience flag — true when explicit override comment found */
27
+ forceOverride?: boolean;
28
+ /** Node IDs in code that matched tracked blocking state */
29
+ matchedNodeIds?: string[];
30
+ };
31
+ export declare class BlockingTracker {
32
+ private lastBlockingTimestamp;
33
+ private lastBlockingNodeIds;
34
+ private lastBlockingCategories;
35
+ /**
36
+ * Record a BLOCKING event from a figma_execute response.
37
+ * Call this after figma_execute if _designSystemViolations or _postExecuteScan had violations.
38
+ */
39
+ recordBlocking(nodeIds: string[], categories?: string[]): void;
40
+ /**
41
+ * Check if an incoming figma_execute code is attempting to suppress a prior BLOCKING.
42
+ * Returns error if suppression detected, empty object if clean.
43
+ */
44
+ checkSuppression(executeCode: string): SuppressionCheckResult;
45
+ /**
46
+ * Manual reset (e.g. new intent, explicit clear).
47
+ */
48
+ reset(): void;
49
+ /**
50
+ * Introspection (for _nextStep hint generation, debugging).
51
+ */
52
+ getState(): {
53
+ nodeCount: number;
54
+ categories: string[];
55
+ timestamp: number;
56
+ };
57
+ }
58
+ /**
59
+ * Extract nodeIds from figma_execute response (for recordBlocking).
60
+ * Checks _postExecuteScan.violations and _designSystemViolations.
61
+ */
62
+ export declare function extractBlockingNodeIds(response: unknown): {
63
+ nodeIds: string[];
64
+ categories: string[];
65
+ };
66
+ /** Singleton for server process lifetime */
67
+ export declare const blockingTracker: BlockingTracker;
68
+ //# sourceMappingURL=blocking-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocking-tracker.d.ts","sourceRoot":"","sources":["../../src/core/blocking-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,MAAM,MAAM,sBAAsB,GAAG;IACpC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,qBAAa,eAAe;IAC3B,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,sBAAsB,CAAgB;IAE9C;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,IAAI;IAQlE;;;OAGG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB;IAyC7D;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CAO1E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAsCrG;AAED,4CAA4C;AAC5C,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * v1.9.7: BLOCKING Suppression Prevention — session-level state.
3
+ *
4
+ * Plan'daki Katman 3 implementasyonu. Amaç: Claude BLOCKING flag'i gördükten
5
+ * sonra aynı nodeId üzerinde ikinci bir mutation execute'ı denerse, server
6
+ * tarafında HARD_ERROR dönerek rasyonalize ederek skip'i engelle.
7
+ *
8
+ * Tespit mekanizması:
9
+ * - Her figma_execute sonrasında _designSystemViolations veya _postExecuteScan
10
+ * döndüyse, response'dan nodeId'leri ayıkla ve `recordBlocking()` çağır.
11
+ * - Sonraki figma_execute öncesi `checkSuppression(code)` çağırılır.
12
+ * - Kod aynı nodeId'yi içeriyorsa ve explicit `// FORCE_OVERRIDE` comment yoksa
13
+ * error döndürülür — tool fail olur, Claude skip edemez.
14
+ *
15
+ * Override escape hatch:
16
+ * - Kod başına `// FORCE_OVERRIDE` comment (`/^\s*\/\/\s*FORCE_OVERRIDE\b/m`)
17
+ * eklendiğinde suppression check bypass edilir. Kullanıcı explicit onay ile
18
+ * override edebilir, Claude sessizce atlayamaz.
19
+ *
20
+ * TTL: 5 dakika. Aynı oturumda yeni intent geldiğinde BLOCKING state zamanla
21
+ * temizlenir (false positive engellenir).
22
+ */
23
+ /** Explicit override regex — multiline, start-of-line // FORCE_OVERRIDE comment */
24
+ const FORCE_OVERRIDE_REGEX = /^\s*\/\/\s*FORCE_OVERRIDE\b/m;
25
+ /** 5 dakika TTL — aynı oturumda state expiration */
26
+ const BLOCKING_TTL_MS = 5 * 60 * 1000;
27
+ export class BlockingTracker {
28
+ constructor() {
29
+ this.lastBlockingTimestamp = 0;
30
+ this.lastBlockingNodeIds = new Set();
31
+ this.lastBlockingCategories = [];
32
+ }
33
+ /**
34
+ * Record a BLOCKING event from a figma_execute response.
35
+ * Call this after figma_execute if _designSystemViolations or _postExecuteScan had violations.
36
+ */
37
+ recordBlocking(nodeIds, categories = []) {
38
+ this.lastBlockingTimestamp = Date.now();
39
+ for (const id of nodeIds) {
40
+ if (id && typeof id === "string")
41
+ this.lastBlockingNodeIds.add(id);
42
+ }
43
+ this.lastBlockingCategories = categories;
44
+ }
45
+ /**
46
+ * Check if an incoming figma_execute code is attempting to suppress a prior BLOCKING.
47
+ * Returns error if suppression detected, empty object if clean.
48
+ */
49
+ checkSuppression(executeCode) {
50
+ // TTL expiration
51
+ const timeSince = Date.now() - this.lastBlockingTimestamp;
52
+ if (timeSince > BLOCKING_TTL_MS) {
53
+ this.reset();
54
+ return {};
55
+ }
56
+ // No recorded blocking — clean pass
57
+ if (this.lastBlockingNodeIds.size === 0)
58
+ return {};
59
+ // Explicit override — user/Claude asked to force
60
+ if (FORCE_OVERRIDE_REGEX.test(executeCode)) {
61
+ return { forceOverride: true };
62
+ }
63
+ // Scan code for tracked nodeIds
64
+ const matched = [];
65
+ for (const id of this.lastBlockingNodeIds) {
66
+ if (executeCode.includes(id))
67
+ matched.push(id);
68
+ }
69
+ if (matched.length === 0)
70
+ return {};
71
+ const preview = matched.slice(0, 3).join(", ");
72
+ const categoryHint = this.lastBlockingCategories.length > 0
73
+ ? ` Onceki BLOCKING kategorileri: ${this.lastBlockingCategories.slice(0, 3).join(", ")}.`
74
+ : "";
75
+ return {
76
+ matchedNodeIds: matched,
77
+ error: `❌ BLOCKING_SUPPRESSION_DETECTED: Node${matched.length > 1 ? "'lar" : ""} ${preview} icin son figma_execute'ta BLOCKING flag donmustu.${categoryHint} ` +
78
+ `Ayni nodeId'ye yeni mutation denendi — rasyonalize ederek skip ediyor olabilirsin. ` +
79
+ `Kok nedeni cozmeden devam edilemez:\n` +
80
+ ` 1. BLOCKING sebebini duzelt (unbound fill/padding/radius/textStyle bind et).\n` +
81
+ ` 2. Eger gercekten bypass gerekli ise kullaniciya acikca sor: "BLOCKING'i override etmek istiyor musun?"\n` +
82
+ ` 3. Kullanici onayi ile kod basina "// FORCE_OVERRIDE" comment ekleyerek tekrar calistir.`,
83
+ };
84
+ }
85
+ /**
86
+ * Manual reset (e.g. new intent, explicit clear).
87
+ */
88
+ reset() {
89
+ this.lastBlockingNodeIds.clear();
90
+ this.lastBlockingCategories = [];
91
+ this.lastBlockingTimestamp = 0;
92
+ }
93
+ /**
94
+ * Introspection (for _nextStep hint generation, debugging).
95
+ */
96
+ getState() {
97
+ return {
98
+ nodeCount: this.lastBlockingNodeIds.size,
99
+ categories: [...this.lastBlockingCategories],
100
+ timestamp: this.lastBlockingTimestamp,
101
+ };
102
+ }
103
+ }
104
+ /**
105
+ * Extract nodeIds from figma_execute response (for recordBlocking).
106
+ * Checks _postExecuteScan.violations and _designSystemViolations.
107
+ */
108
+ export function extractBlockingNodeIds(response) {
109
+ const nodeIds = [];
110
+ const categories = [];
111
+ if (!response || typeof response !== "object")
112
+ return { nodeIds, categories };
113
+ const r = response;
114
+ // v1.9.6 _postExecuteScan.violations
115
+ const scan = r._postExecuteScan;
116
+ if (scan?.violations) {
117
+ for (const v of scan.violations) {
118
+ if (v.nodeId)
119
+ nodeIds.push(v.nodeId);
120
+ if (v.category)
121
+ categories.push(v.category);
122
+ }
123
+ }
124
+ // Also _postExecuteViolations (server-side wrapper, v1.9.6)
125
+ const postViol = r._postExecuteViolations;
126
+ if (postViol?.violations) {
127
+ for (const v of postViol.violations) {
128
+ if (v.nodeId)
129
+ nodeIds.push(v.nodeId);
130
+ if (v.category)
131
+ categories.push(v.category);
132
+ }
133
+ }
134
+ // v1.8.1 _designSystemViolations (static code analysis; node IDs usually embedded in messages)
135
+ const dsViol = r._designSystemViolations;
136
+ if (dsViol?.violations) {
137
+ for (const v of dsViol.violations) {
138
+ if (v.category)
139
+ categories.push(v.category);
140
+ // Regex: extract node IDs like "241:11896" from message text
141
+ if (v.message) {
142
+ const matches = v.message.match(/\d+:\d+/g);
143
+ if (matches)
144
+ nodeIds.push(...matches);
145
+ }
146
+ }
147
+ }
148
+ return { nodeIds: Array.from(new Set(nodeIds)), categories: Array.from(new Set(categories)) };
149
+ }
150
+ /** Singleton for server process lifetime */
151
+ export const blockingTracker = new BlockingTracker();
152
+ //# sourceMappingURL=blocking-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocking-tracker.js","sourceRoot":"","sources":["../../src/core/blocking-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * v1.9.7: Bootstrap Injector — response-level zero-click enforcement.
3
+ *
4
+ * Plan'daki Katman 5 implementasyonu.
5
+ *
6
+ * Amaç: Claude Desktop'ta kullanıcı hiç setup yapmadan ("figma linki + ödeme
7
+ * ekranı tasarla" gibi genel prompt ile) tüm agent/skill chain'in otomatik
8
+ * devreye girmesi için plugin MCP response'larında gömülü directive göndermek.
9
+ *
10
+ * Strateji:
11
+ * - İlk `figma_get_status` çağrısında FULL bootstrap (critical_rules + embedded
12
+ * skills) ~6K token gönderilir. Claude okur, oturum boyunca bellekte tutar.
13
+ * - Sonraki çağrılarda sadece kısa reminder (~100 token).
14
+ * - Her tool response'a `_nextStep` hint eklenir — Claude'u bir sonraki doğru
15
+ * adıma yönlendirir.
16
+ */
17
+ export type BootstrapPayload = {
18
+ version: string;
19
+ self_instruction: string;
20
+ critical_rules?: string[];
21
+ anti_patterns?: string[];
22
+ embedded_skills?: string;
23
+ embedded_instructions_token_estimate?: number;
24
+ skill_cache_hint?: string;
25
+ reference_docs?: string;
26
+ reminder?: string;
27
+ session_tool_count?: number;
28
+ };
29
+ /**
30
+ * Bootstrap injector — session-level state.
31
+ */
32
+ export declare class BootstrapInjector {
33
+ private firstCallMade;
34
+ private toolCallCount;
35
+ /**
36
+ * Get bootstrap payload for a figma_get_status call.
37
+ * First call: full directives + embedded skills.
38
+ * Subsequent: short reminder.
39
+ */
40
+ getBootstrap(): BootstrapPayload;
41
+ /**
42
+ * Generate _nextStep hint for a given tool + result.
43
+ * Claude-facing string directing the next logical action.
44
+ */
45
+ injectNextStep(toolName: string, result: unknown): string | undefined;
46
+ reset(): void;
47
+ }
48
+ /** Singleton for server process lifetime */
49
+ export declare const bootstrapInjector: BootstrapInjector;
50
+ //# sourceMappingURL=bootstrap-injector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-injector.d.ts","sourceRoot":"","sources":["../../src/core/bootstrap-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAwBH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC,CAAC,EAAE,MAAM,CAAC;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAK;IAE1B;;;;OAIG;IACH,YAAY,IAAI,gBAAgB;IA2BhC;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAoDrE,KAAK,IAAI,IAAI;CAIb;AAED,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * v1.9.7: Bootstrap Injector — response-level zero-click enforcement.
3
+ *
4
+ * Plan'daki Katman 5 implementasyonu.
5
+ *
6
+ * Amaç: Claude Desktop'ta kullanıcı hiç setup yapmadan ("figma linki + ödeme
7
+ * ekranı tasarla" gibi genel prompt ile) tüm agent/skill chain'in otomatik
8
+ * devreye girmesi için plugin MCP response'larında gömülü directive göndermek.
9
+ *
10
+ * Strateji:
11
+ * - İlk `figma_get_status` çağrısında FULL bootstrap (critical_rules + embedded
12
+ * skills) ~6K token gönderilir. Claude okur, oturum boyunca bellekte tutar.
13
+ * - Sonraki çağrılarda sadece kısa reminder (~100 token).
14
+ * - Her tool response'a `_nextStep` hint eklenir — Claude'u bir sonraki doğru
15
+ * adıma yönlendirir.
16
+ */
17
+ import { EMBEDDED_SKILLS_SUMMARY, EMBEDDED_SKILLS_TOKEN_ESTIMATE } from "./embedded-skills.js";
18
+ /** Critical rules (Katman 5 — 8 direktif) */
19
+ const CRITICAL_RULES = [
20
+ "1. FIRST: figma_get_design_system_summary cagir, DS state kontrol et",
21
+ "2. BLANK FILE: 0 component/0 variable tespit edilirse 4 secenek sun: (a) team library import, (b) figma_create_mini_ds, (c) template kopyala, (d) linter-off — secim yapilmadan createFrame YASAK",
22
+ "3. POST-EXECUTE: Her figma_execute sonrasi _POST_EXECUTE_SCAN_BLOCKING flag'i kontrol, varsa kodu duzelt ve retry — 'dosyada DS yok, gecerli degil' diye SKIP ETME",
23
+ "4. SCREENSHOT: returnMode 'file'/'summary'/'regions' kullan, 'base64' sadece kullanici explicit isterse",
24
+ "5. DISCOVERY: maks 12 figma_get_* cagrisi sonra plan sun",
25
+ "6. SCAN: Ekran tamamlandiginda figma_scan_ds_compliance(threshold=85) ZORUNLU, skor <85 ise duzelt",
26
+ "7. NEGATIVE INTENT: Kullanici 'X atla', 'X'e bakma', 'X disinda' dediyse exclude_references state'e yaz",
27
+ "8. SUPPRESSION: BLOCKING flag'i 'bu projede gecerli degil', 'simdilik skip' gibi rasyonellestirme YASAK — kok nedeni duzelt. Aksi halde server HARD_ERROR doner.",
28
+ ];
29
+ const ANTI_PATTERNS = [
30
+ "Ham createFrame + hardcoded fill/padding/fontSize — DS'siz uretim denemesi",
31
+ "BLOCKING flag'i 'bu projede yok' diye skip etme",
32
+ "base64 screenshot default kullanma (~30K token context)",
33
+ "Discovery 12+ call (plan sunmadan)",
34
+ "ask_user_input_v0 3+ soru ust uste",
35
+ ];
36
+ /**
37
+ * Bootstrap injector — session-level state.
38
+ */
39
+ export class BootstrapInjector {
40
+ constructor() {
41
+ this.firstCallMade = false;
42
+ this.toolCallCount = 0;
43
+ }
44
+ /**
45
+ * Get bootstrap payload for a figma_get_status call.
46
+ * First call: full directives + embedded skills.
47
+ * Subsequent: short reminder.
48
+ */
49
+ getBootstrap() {
50
+ this.toolCallCount++;
51
+ if (!this.firstCallMade) {
52
+ this.firstCallMade = true;
53
+ return {
54
+ version: "1.9.7",
55
+ self_instruction: "Bu directives'i bir kere oku ve oturum boyunca uygula. Kullanici explicit aksini soylemedikce sapma.",
56
+ critical_rules: CRITICAL_RULES,
57
+ anti_patterns: ANTI_PATTERNS,
58
+ embedded_skills: EMBEDDED_SKILLS_SUMMARY,
59
+ embedded_instructions_token_estimate: EMBEDDED_SKILLS_TOKEN_ESTIMATE,
60
+ skill_cache_hint: "Bu embedded_skills oturum boyunca etkili. Sadece ilk figma_get_status'ta gelir, sonraki call'larda _bootstrap.reminder doner (~100 token). LLM prompt cache ile 5 dk icinde yeniden enjeksiyon bedavadir.",
61
+ reference_docs: "MCP resources: fmcp://skills/master-instructions, fmcp://skills/blank-file-workflow. MCP prompts: fmcp-start-session, fmcp-design-screen, fmcp-audit-screen.",
62
+ };
63
+ }
64
+ return {
65
+ version: "1.9.7",
66
+ self_instruction: CRITICAL_RULES.slice(0, 3).join(" | "),
67
+ reminder: "Rules from first figma_get_status call still in effect. See critical_rules in initial _bootstrap response.",
68
+ session_tool_count: this.toolCallCount,
69
+ };
70
+ }
71
+ /**
72
+ * Generate _nextStep hint for a given tool + result.
73
+ * Claude-facing string directing the next logical action.
74
+ */
75
+ injectNextStep(toolName, result) {
76
+ if (!result || typeof result !== "object")
77
+ return undefined;
78
+ const r = result;
79
+ switch (toolName) {
80
+ case "figma_get_status": {
81
+ if (r.pluginConnected)
82
+ return "verify_ds_state_with_figma_get_design_system_summary";
83
+ return "plugin_not_connected_ask_user_to_open_figma_plugin";
84
+ }
85
+ case "figma_get_design_system_summary": {
86
+ const comps = r.components ?? 0;
87
+ const sets = r.componentSets ?? 0;
88
+ const vars = r.variableCollections?.length ?? 0;
89
+ if (comps === 0 && sets === 0 && vars === 0) {
90
+ return "BLANK_FILE_DIALOG_REQUIRED: 4 secenek sun (a) library import (b) figma_create_mini_ds (c) template (d) linter-off — secim yapmadan createFrame YASAK";
91
+ }
92
+ return "load_components_and_variables_via_team_library_api";
93
+ }
94
+ case "figma_execute": {
95
+ if (r._POST_EXECUTE_SCAN_BLOCKING || r._DESIGN_SYSTEM_VIOLATIONS_BLOCKING) {
96
+ return "BLOCKING_detected — fix_unbound_nodes_and_retry — DO NOT rationalize or skip";
97
+ }
98
+ if (r._DISCOVERY_BUDGET_EXCEEDED_BLOCKING) {
99
+ return "discovery_budget_exceeded — plan_sun_to_user_and_await_approval";
100
+ }
101
+ return "continue_with_next_section_or_call_figma_scan_ds_compliance_when_done";
102
+ }
103
+ case "figma_scan_ds_compliance":
104
+ case "figma_validate_screen": {
105
+ if (r.passed === false) {
106
+ return "bind_violations_listed_in_samples_then_rescan";
107
+ }
108
+ return "ready_to_report_to_user_with_coverage_summary";
109
+ }
110
+ case "figma_capture_screenshot": {
111
+ const mode = r.mode ?? "unknown";
112
+ if (mode === "base64") {
113
+ return "next_time_prefer_returnMode_file_or_summary_to_save_context";
114
+ }
115
+ return "continue_with_design_or_validation_flow";
116
+ }
117
+ case "figma_create_mini_ds": {
118
+ if (r.success) {
119
+ return "mini_ds_ready — call_figma_execute_to_build_screen_using_new_components_and_variables";
120
+ }
121
+ return "mini_ds_failed — report_error_to_user";
122
+ }
123
+ default:
124
+ return undefined;
125
+ }
126
+ }
127
+ reset() {
128
+ this.firstCallMade = false;
129
+ this.toolCallCount = 0;
130
+ }
131
+ }
132
+ /** Singleton for server process lifetime */
133
+ export const bootstrapInjector = new BootstrapInjector();
134
+ //# sourceMappingURL=bootstrap-injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-injector.js","sourceRoot":"","sources":["../../src/core/bootstrap-injector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * v1.9.7: Auto-generated embedded skill summary for Claude Desktop zero-click enforcement.
3
+ *
4
+ * Generated by: scripts/generate-embedded-skills.mjs
5
+ * Source: skills/fmcp-intent-router/SKILL.md, skills/fmcp-screen-orchestrator/SKILL.md, skills/figma-canvas-ops/SKILL.md, skills/fmcp-screen-recipes/SKILL.md, skills/fmcp-project-rules/SKILL.md
6
+ *
7
+ * DO NOT EDIT MANUALLY. Run `npm run generate:embedded-skills` to regenerate.
8
+ * This file is regenerated on prepublishOnly hook before npm publish.
9
+ *
10
+ * Generated: 2026-04-18T08:23:36.324Z
11
+ * Total estimated tokens: 9349
12
+ */
13
+ export declare const EMBEDDED_SKILLS_SUMMARY = "<!-- fmcp-intent-router (2572 tokens) -->\n---\nname: fmcp-intent-router\ndescription: F-MCP ile ilgili herhangi bir kullan\u0131c\u0131 talebinin ilk giri\u015F noktas\u0131. Kullan\u0131c\u0131n\u0131n niyetini analiz eder, hangi hedef SKILL'in \u00E7al\u0131\u015Ft\u0131r\u0131laca\u011F\u0131na karar verir, o SKILL i\u00E7in gereken eksik input'lar\u0131 tek turda toplar, \u00F6zet+onay al\u0131r ve ondan sonra hedef SKILL'i \u00E7al\u0131\u015Ft\u0131r\u0131r. \"figma\", \"ekran olu\u015Ftur\", \"tasar\u0131m yap\", \"component \u00FCret\", \"DS denetle\", \"token sync\", \"kod \u00FCret\", \"design system\" gibi her F-MCP-tetiklemesiyle aktive olur. Claude hi\u00E7bir figma_* yazma tool'u \u00E7al\u0131\u015Ft\u0131rmadan \u00D6NCE bu protokol\u00FC uygulamak zorundad\u0131r.\nmetadata:\n mcp-server: user-figma-mcp-bridge\n version: 1.8.1\n priority: 100\n phase: entry-gate\n personas:\n - designer\n - uidev\n - designops\n---\n\n# F-MCP Intent Router \u2014 Universal Entry Gate\n\n## Neden Var?\n\nF-MCP Bridge'in 20+ SKILL'i var. Her biri farkl\u0131 bir i\u015F yapar (ekran olu\u015Fturma, denetim, k\u00FCt\u00FCphane in\u015Fas\u0131, vb.) ve her biri farkl\u0131 input'lar ister. Claude kullan\u0131c\u0131 \"figma'da ekran yap\" dedi\u011Finde:\n\n1. Hangi SKILL laz\u0131m? (`generate-figma-screen` mi `generate-figma-library` mi?)\n2. Hangi bilgiler eksik? (device? DS? benchmark? i\u00E7erik b\u00F6l\u00FCmleri?)\n3. Kullan\u0131c\u0131 ne onay verdi?\n\nBu SKILL bu \u00FC\u00E7 soruyu **upstream** \u00E7\u00F6zer. Claude intent'i netle\u015Ftirmeden hi\u00E7bir `figma_execute`, `figma_create_frame`, `figma_clone_screen_to_device` \u00E7al\u0131\u015Ft\u0131rmaz. \"H\u0131zl\u0131 ve do\u011Fru\" kural\u0131: yanl\u0131\u015F varsay\u0131m yapmaktansa 1 soru sormak her zaman daha h\u0131zl\u0131d\u0131r.\n\n## Protokol (9 Ad\u0131m \u2014 v1.9.1+)\n\nKullan\u0131c\u0131 F-MCP ile ilgili herhangi bir talep yapt\u0131\u011F\u0131nda Claude bu 9 ad\u0131m\u0131 SIRAYLA uygular. Hi\u00E7bir ad\u0131m atlanmaz.\n\n### \uD83D\uDEA8 Ad\u0131m 0 \u2014 DS GATE + BLANK FILE CHECK (v1.9.7+ MUTLAK \u0130LK KAPI)\n\n**Herhangi bir intent analysis veya figma_* tool \u00E7a\u011Fr\u0131s\u0131ndan \u00D6NCE:**\n\n1. `figma_get_status` \u00E7a\u011F\u0131r \u2014 plugin ba\u011Fl\u0131 m\u0131, response'ta `_bootstrap` varsa direktifleri OKU (v1.9.7)\n2. `.claude/design-systems/active-ds.md` dosyas\u0131n\u0131 oku\n3. `Status:` alan\u0131n\u0131 kontrol et:\n - **`\u2705 Aktif`** \u2192 DS net, Blank File Sub-Check'e ge\u00E7 (madde 5)\n - **`\u274C Hen\u00FCz se\u00E7ilmedi`** VEYA dosya yok \u2192 kullan\u0131c\u0131ya DS sorusu sor (madde 4)\n4. **DS Sorusu (klasik):** \"Aktif bir design system belirlenmemi\u015F. Hangi DS ile ilerlemek istersiniz? (SUI / Material / kendi library)\"\n\n5. **BLANK FILE SUB-CHECK (v1.9.7, ZORUNLU):** `figma_get_design_system_summary` \u00E7a\u011F\u0131r.\n - `components === 0 && componentSets === 0 && variableCollections.length === 0` ise **BO\u015E DOSYA** tespit edildi.\n - `_nextStep: \"BLANK_FILE_DIALOG_REQUIRED\"` response'ta g\u00F6r\u00FCn\u00FCyorsa, **kullan\u0131c\u0131ya 4 se\u00E7enek sun** (AskUserQuestion tek call, 4 option):\n ```\n Q: \"Bu dosyada hen\u00FCz Design System yok. Nas\u0131l ilerleyelim?\"\n (a) Team library import \u2014 \"Hangi library? SUI, Material 3, iOS HIG, veya kendi library'niz?\"\n (b) Mini DS kur otomatik \u2014 figma_create_mini_ds tool'u \u00E7a\u011Fr\u0131l\u0131r (12 color + 8 sizing + 3 text style + Button/Input/Card)\n (c) Referans DS kopyala \u2014 \"Material 3 template / iOS HIG template\"\n (d) DS'siz ilerle \u2014 linter tolerant mode, hardcoded de\u011Ferler kabul (explicit acceptance)\n ```\n - **Se\u00E7im yap\u0131lmadan `figma_execute createFrame` YASAK.** Claude ham createFrame denerse plugin `_DESIGN_SYSTEM_VIOLATIONS_BLOCKING` flag'i d\u00F6nd\u00FCr\u00FCr, retry zorunlu olur.\n - Kullan\u0131c\u0131 \"(b)\" derse Claude `figma_create_mini_ds({ primaryColor, fontFamily, name })` tek tool \u00E7a\u011Fr\u0131s\u0131 yapar, sonra ekran \u00FCretimine ge\u00E7er.\n - Kullan\u0131c\u0131 \"(a)\" derse Claude `figma_get_library_variables(libraryName)` ile listeleme yapar, se\u00E7enek sunar.\n\n6. Se\u00E7im sonras\u0131 `active-ds.md`'yi g\u00FCncelle (`Status: \u2705 Aktif`, `Library Name: <isim>`), sonra Ad\u0131m 1'e ge\u00E7.\n\n**Neden bu kadar kat\u0131:**\n- DS belirsizken `figma_search_assets`, `figma_get_file_data`, `figma_get_library_variables` \u00E7a\u011F\u0131rmak = kullan\u0131c\u0131n\u0131n istemedi\u011Fi library'leri enumere etmek = **token israf\u0131 + UX bozulmas\u0131**\n- Test ge\u00E7mi\u015Finde g\u00F6zlenen hata: benchmark Figma dosyas\u0131n\u0131n 24+ library component'i enumere edildi, sonra \"hangi DS?\" soruldu. **Bu s\u0131ra YASAK.**\n\n**Bu ad\u0131mda \u00E7a\u011Fr\u0131labilen tek Figma tool'u:**\n- \u2705 `figma_get_status()` \u2014 plugin ba\u011Flant\u0131 kontrol\u00FC, DS ba\u011F\u0131ms\u0131z\n- **Ba\u015Fka H\u0130\u00C7B\u0130R figma_* YASAK.** `figma_get_file_data`, `figma_search_assets`, `figma_search_components`, `figma_get_library_variables`, `figma_get_variables`, `figma_get_styles` \u2014 **hepsi YASAK** ta ki Ad\u0131m 0 ge\u00E7ilene kadar.\n\n---\n\n### Ad\u0131m 1 \u2014 Intent Analysis\n\nKullan\u0131c\u0131 talebini oku. Anahtar kelimeleri tara:\n\n| Kullan\u0131c\u0131 ifadesi | Olas\u0131 SKILL aday\u0131 |\n|---|---|\n| \"ekran yap\", \"tasar\u0131m olu\u015Ftur\", \"ui \u00E7iz\", \"UI'\u0131 Figma'ya aktar\", \"landing page\", \"mobil ekran\" | `generate-figma-screen` |\n| \"DS hizala\", \"SUI'ye uygula\", \"design system uygula\", \"token'lara ba\u011Fla\" | `apply-figma-design-system` |\n| \"denet\", \"audit\", \"DS sa\u011Fl\u0131\u011F\u0131\", \"token ba\u011Fl\u0131 m\u0131\", \"ne kadar DS uyumlu\" | `audit-figma-design-system` |\n| \"k\u00FCt\u00FCphane yap\", \"component set \u00FCret\", \"DS k\u00FCt\u00FCphane in\u015Fa\" | `generate-figma-library` |\n| \"Figma'dan kod \u00FCret\", \"implement design\", \"SwiftUI/Compose/React kodu\" | `implement-design` |\n| \"kod \u2194 figma e\u015Fle\u015Ftir\", \"Code Connect\", \"design mapping\" | `code-design-mapper` |\n| \"g\u00F6rsel kar\u015F\u0131la\u015Ft\u0131r\", \"visual diff\", \"QA screenshot\" | `visual-qa-compare` |\n| \"token sync\", \"design tokens export\", \"CSS/Swift/Kotlin token\" | `design-token-pipeline` |\n| \"figjam diyagram\", \"flowchart\", \"mind map\" | `figjam-diagram-builder` |\n| \"ekran \u00F6zeti\", \"analiz et\", \"ne i\u00E7eriyor\" | `figma-screen-analyzer` |\n| \"accessibility\", \"a11y\", \"WCAG\", \"contrast check\" | `figma-a11y-audit` |\n| \"drift\", \"kod/tasar\u0131m sapmas\u0131\", \"out of sync\" | `design-drift-detector` |\n| \"UX copy\", \"microcopy\", \"buton metni\", \"empty state\" | `ux-copy-guidance` |\n| \"bu g\u00F6rselden ilham al\", \"\u015Fu resim gibi\", \"link'teki tasar\u0131mdan\", \"dribbble/behance\", \"benchmark'tan varyasyon\" | `inspiration-intake` \u2192 `generate-figma-screen` |\n\n**Not (v1.8.3+):** `inspiration-intake` bir **\u00F6n-i\u015Fleme** skill'idir. Kullan\u0131c\u0131 bir Figma benchmark linki, internet g\u00F6rsel linki veya sohbete y\u00FCklenmi\u015F g\u00F6rsel ile gelirse \u00F6nce bu skill \u00E7al\u0131\u015Ft\u0131r\u0131l\u0131r (structural_intent JSON \u00FCretir, DE\u011EER \u00E7\u0131karmaz), sonra \u00E7\u0131kt\u0131s\u0131 `generate-figma-screen`'in `reference_benchmark` parametresine beslenir. v1.8.2 build-from-scratch kural\u0131 ile tam uyumludur \u2014 clone de\u011Fil, inspiration.\n\nMode tespiti:\n- Figma URL pattern (`figma.com/file/...?node-id=`) \u2192 `inspiration-intake` (source_type: figma_url)\n- Dribbble/Behance/genel HTTP URL \u2192 `inspiration-intake` (source_type: image_url, WebFetch fallback'li)\n- Kullan\u0131c\u0131 mesaj\u0131nda g\u00F6rsel attachment \u2192 `inspiration-intake` (source_type: image_uploaded)\n\n### Ad\u0131m 2 \u2014 State Files Check\n\nClaude her seferinde \u00FC\u00E7 state dosyas\u0131n\u0131 okur:\n\n```\n1. .claude/design-systems/active-ds.md\n \u2192 Aktif DS belirtilmi\u015F mi? (\u00F6rn \"\u2756 SUI\")\n\n2. .claude/design-systems/last-intent.md\n \u2192 Son tamamlanan intent nedir? (device, ds, skill, inputs)\n\n3. .claude/design-systems/intent-history.md\n \u2192 Son 5 intent nedir? (LRU)\n```\n\nBu dosyalar Claude'un \"\u00F6ncekiyle ayn\u0131 m\u0131?\" sorusu sormas\u0131n\u0131 sa\u011Flar.\n\n### Ad\u0131m 3b \u2014 Approach Karar Mant\u0131\u011F\u0131 (v1.8.2+)\n\nTarget skill `generate-figma-screen` ise, **yakla\u015F\u0131m ayr\u0131m\u0131** yap.\nKullan\u0131c\u0131n\u0131n c\u00FCmlesinde \u015Fu keyword'leri ara ve `approach` input'unu doldur:\n\n| Keyword | Yakla\u015F\u0131m | Tool \u00D6nerisi |\n|---|---|---|\n| \"alternatif\", \"varyasyon\", \"farkl\u0131\", \"yeni\", \"tasarla\", \"redesign\", \"iyile\u015Ftir\" | `build-from-scratch` \u2B50 | `figma_execute` + Step 5, **`figma_clone_screen_to_device` KULLANMA** |\n| \"ayn\u0131 ekran\u0131 X device'a migrate et\", \"boyut de\u011Fi\u015Ftir\", \"iPhone 13\u219217\", \"klonla\" | `clone-to-device` | `figma_clone_screen_to_device` |\n| \"mevcut ekran\u0131 DS'ye hizala\", \"tokenize et\", \"tokens bind et\" | `apply-ds-to-existing` | `apply-figma-design-system` SKILL |\n| Hi\u00E7biri net de\u011Fil | **Kullan\u0131c\u0131ya sor** | \u2014 |\n\n**\u2B50 \u00D6NEML\u0130:** E\u011Fer kullan\u0131c\u0131 \"3 alternatif\" veya \"varyasyon\" derse, `approach = build-from-scratch` **DEFAULT**'tur. `figma_clone_screen_to_device` tool'u **ASLA \u00F6nerilmez**. Clone tool'u kopyalama yaparken benchmark'\u0131n **mevcut yanl\u0131\u015Fl\u0131klar\u0131n\u0131** (hardcoded rectangle, missing token binding, non-responsive layout) kopyalar. Bu kullan\u0131c\u0131n\u0131n istedi\u011Fi **ger\u00E7ek varyasyon yaratmaz**.\n\nE\u011Fer `approach = build-from-scratch` ise, Claude'un ak\u0131\u015F haritas\u0131:\n```\nfigma_search_assets ile SUI bile\u015Fenlerini bul\n \u2193\nfigma_get_library_variables ile DS token key'lerini topla\n \u2193\nfigma_execute ile b\u00F6l\u00FCm b\u00F6l\u00FCm in\u015Fa et:\n - figma.createFrame() + layoutMode + padding (variable binding)\n - importComponentByKeyAsync + createInstance (DS instance'lar)\n - setBoundVariableForPaint (fills token bind)\n - setBoundVariable (padding/itemSpacing/cornerRadius token bind)\n - importStyleByKeyAsync + setTextStyleIdAsync (text style bind)\n - appendChild sonras\u0131 layoutSizingHorizontal/Vertical = FILL\n \u2193\nfigma_validate_screen ile skor kontrol\u00FC (\u226580)\n```\n\n**\u00D6zet + Onay ekran\u0131nda g\u00F6ster:**\n```\n\uD83D\uDCCB Yakla\u015F\u0131m: build-from-scratch \u2B50\n Bu kullan\u0131c\u0131n\u0131n \"alternatif tasar\u0131m\" iste\u011Fine uygun do\u011Fru yol.\n Clone tool kullan\u0131lmayacak. Her alternatif s\u0131f\u0131rdan SUI bile\u015Fenleriyle in\u015Fa edilecek.\n Benchmark (139:xxx) sadece ilham kayna\u011F\u0131 \u2014 kopyalanmayacak.\n```\n\n### Ad\u0131m 3 \u2014 Decide Target Skill\n\nAd\u0131m 1'deki keyword e\u015Fle\u015Fmesi + Ad\u0131m 2'deki state bilgisi \u2192 tek bir SKILL se\u00E7.\n\n**Karar mant\u0131\u011F\u0131:**\n\n```\nIF user request EXACTLY matches one keyword pattern\n \u2192 Select that skill (single match, no question)\n\nELSE IF user request matches 2+ patterns (ambiguous)\n \u2192 Ask user: \"\u015Eunlardan hangisini yapay\u0131m?\"\n \u2192 Use AskUserQuestion with matched skills as options\n\nELSE IF user request is generic (\"figma'da bir \u015Fey yap\")\n \u2192 Ask user: \"Tam olarak ne yapmak istiyorsun?\"\n \u2192 Offer top 5 common skills as options\n\nELSE (no match)\n \u2192 Ask user to clarify intent in natural language\n```\n\n### Ad\u0131m 4 \u2014 Read Target Skill Metadata\n\nSe\u00E7ilen SKILL'in frontmatter'\u0131n\u0131 oku. `required_inputs` blo\u011Funu parse et:\n\n```yaml\nrequired_inputs:\n - name: device\n type: enum\n options: [\"iPhone 17\", \"iPhone 16 Pro Max\", ...]\n question: \"Hangi device boyutunda olsun?\"\n required: true\n default_source: \".claude/design-systems/last-intent.md#device\"\n - name: design_system\n type: from_state\n source: \".claude/design-systems/active-ds.md#Library Name\"\n required: true\n - name: reference_benchmark\n type: node_id_or_none\n question: \"Referans benchmark node var m\u0131?\"\n required: false\n affects: [\"screen_type\", \"sections\"] # verilirse bunlar atlan\u0131r\n - name: screen_type\n type: enum\n ...\n skip_if: \"reference_benchmark != none\"\n```\n\n---\n\n<!-- fmcp-screen-orchestrator (887 tokens) -->\n### Ortak Protokol\n\n1. **Skill Registry** a\u00E7\u0131k \u2014 tahmin yasak, sezgisel Read() yasak\n2. **Intent Routing** \u2014 belirsiz \u2192 Read fmcp-intent-router\n3. **Cheap-First** \u2014 `depth=1`, `verbosity=\"summary\"`, screenshot sadece onay kap\u0131s\u0131nda, \u22645 execute\n4. **Cache-First** \u2014 `.claude/design-systems/<lib>/` cache'i API'den \u00D6NCE oku\n5. **Onay Kap\u0131lar\u0131** \u2014 approach / destructive / evolution / 3. audit fail\n6. **Self-Audit** \u2014 `figma_validate_screen(nodeId, minScore=80)` ZORUNLU\n7. **Skill Evolution** \u2014 iki a\u015Famal\u0131 onay + `# DRAFT \u2014 PENDING APPROVAL` banner\n8. **T\u00FCrk\u00E7e Raporlama** \u2014 metrik blo\u011Fu zorunlu\n\n### Skill Registry\n\n| Skill | Trigger | Common case? |\n|---|---|---|\n| `fmcp-intent-router` | Belirsiz intent | Sadece belirsizlikte |\n| `inspiration-intake` | image/figma_benchmark | Sadece bu modlarda |\n| `generate-figma-screen` | Net screen creation | HER ZAMAN (ana motor) |\n| `figma-canvas-ops` | Her figma_execute \u00F6ncesi | HER ZAMAN (pre-flight) |\n| `fmcp-screen-recipes` | Fast Path match | Sadece Fast Path'te |\n| `apply-figma-design-system` | Mevcut ekran\u0131 DS'ye hizala | Sadece remediation |\n\n### Ad\u0131m 0 \u2014 DS GATE (MUTLAK \u0130LK KAPI)\n\n```\n1. Read(\".claude/design-systems/active-ds.md\")\n2. \u2705 Aktif \u2192 Library Name not al, devam\n \u274C Se\u00E7ilmedi veya dosya yok \u2192 DUR, kullan\u0131c\u0131ya \"Hangi DS?\" sor, hi\u00E7bir figma_* \u00E7a\u011F\u0131rma\n```\n\nDS belirsizken `figma_get_file_data`, `figma_search_assets` \u00E7a\u011F\u0131rmak YASAK. \u0130stisnalar: `figma_get_status()`, filesystem read, Claude vision.\n\n### Ad\u0131m 0.5 \u2014 Fast Path Check\n\n5 ko\u015Fulun HEPS\u0130 TRUE \u2192 `fmcp-screen-recipes` Read, recipe uygula:\n1. Tek ekran (multi-screen de\u011Fil)\n2. Standart tip (login/payment/profile/list/detail/form/onboarding/dashboard/settings)\n3. DS aktif\n4. Platform belli (explicit keyword VEYA \u00F6nceki intent'ten saved). Yoksa DUR, kullan\u0131c\u0131ya sor. Default varsay\u0131m YASAK.\n5. Animation/prototype YOK\n\nBiri bile FALSE \u2192 Karar Ak\u0131\u015F\u0131'na ge\u00E7. Recipe k\u0131r\u0131l\u0131rsa da fallback.\n\n### Karar Ak\u0131\u015F\u0131\n\n```\n1. Intent net mi? EVET \u2192 sub-skill / HAYIR \u2192 Read fmcp-intent-router\n2. image/figma_benchmark \u2192 Read inspiration-intake \u2192 structural_intent JSON\n3. figma_execute yazacak m\u0131? EVET \u2192 Read figma-canvas-ops\n4. Ana motor \u2192 Read generate-figma-screen\n5. build-from-scratch vs clone-to-device\n```\n\n### DS Fallback Chain\n\n1. **DS component instance** \u2014 en \u00E7ok tercih\n2. **DS primitive variant** \u2014 yak\u0131n variant + setProperties\n3. **Token-bound primitive** \u2014 createFrame + t\u00FCm fill/padding/radius variable'a ba\u011Fl\u0131 \u2192 me\u015Fru, ihlal DE\u011E\u0130L\n4. **Hardcoded shape** \u2192 GER\u00C7EK \u0130HLAL, DUR, kullan\u0131c\u0131ya bildir\n\n### Resmi Figma MCP Yasa\u011F\u0131\n\n`Figma:*` prefix'li tool'lar (mcp.figma.com) ASLA \u00E7a\u011Fr\u0131lmaz. Sadece `figma_*` (figma-mcp-bridge) kullan. `figma_search_assets` bo\u015F \u2192 Rule 24 fallback (manuel instance scan), `Figma:search_design_system`'e d\u00FC\u015FME.\n\n### Filesystem MCP\n\nSkill Read i\u00E7in: `mcp__fmcp-filesystem__read_text_file(path=\"<absolute_path>/skills/<skill>/SKILL.md\")`. Claude Desktop'ta prompt'ta absolute path belirtilmeli.\n\n### Self-Audit Gate + Verification\n\n```\nfigma_validate_screen(nodeId=<wrapper_id>, minScore=80)\n```\n- `<80` \u2192 SEVERE violation'lar\u0131 oku, d\u00FCzelt, yeniden validate\n- 3 deneme fail \u2192 kullan\u0131c\u0131dan rebuild onay\u0131 al\n\nTeslim \u00F6ncesi kontrol: validate \u226580, ham shape yok, t\u00FCm de\u011Ferler token'a ba\u011Fl\u0131, auto-layout eksiksiz, T\u00FCrk\u00E7e rapor + metrikler.\n\n### Rapor Format\u0131\n\n```markdown\n## \uD83C\uDFA8 Ekran \u00DCretimi \u2014 <ekran_ad\u0131>\n**Mod:** <intake_mode> | **DS:** <active-ds> | **Yakla\u015F\u0131m:** <approach>\n### Sonu\u00E7\n<Figma node link>\n\uD83D\uDCCA Metrikler: skill'ler, API \u00E7a\u011Fr\u0131, cache hit/miss, execute say\u0131s\u0131, validate score\n```\n\n---\n\n---\n\n<!-- figma-canvas-ops (2369 tokens) -->\n---\nname: figma-canvas-ops\ndescription: F-MCP Bridge ile Figma tuvalinde g\u00FCvenli yazma/d\u00FCzenleme i\u00E7in zorunlu \u00F6nko\u015Ful k\u0131lavuzu. figma_execute \u00E7a\u011Fr\u0131s\u0131 \u00F6ncesi bu skill y\u00FCklenmelidir.\nmetadata:\n mcp-server: user-figma-mcp-bridge\n personas:\n - designer\n - designops\n---\n\n# Figma Canvas Ops \u2014 figma_execute G\u00FCvenli Kullan\u0131m K\u0131lavuzu\n\n## Ara\u00E7 E\u015Fleme (topluluk \u2192 F-MCP)\n\n| Topluluk | F-MCP Bridge | Not |\n|---|---|---|\n| `use_figma` | `figma_execute` | JS \u00E7al\u0131\u015Ft\u0131rma |\n| `get_metadata` | `figma_get_file_data` | Yap\u0131/metadata |\n| `get_screenshot` | `figma_capture_screenshot` | G\u00F6rsel do\u011Frulama |\n| `search_design_system` | `figma_search_components` + `figma_get_design_system_summary` | \u0130ki ara\u00E7 birlikte |\n\n## Prerequisites\n\n- F-MCP Bridge plugin ba\u011Fl\u0131 olmal\u0131 (`figma_get_status()`)\n- Aktif DS context: `.claude/design-systems/active-ds.md` \u2192 `Status: \u2705`\n\n## 0. Design System Context (ZORUNLU)\n\n### 0a \u2014 Active DS check\n```\n1. Read .claude/design-systems/active-ds.md\n2. \u2705 Aktif \u2192 Library Name not al, 0b'ye ge\u00E7\n \u274C Se\u00E7ilmedi \u2192 0c'ye ge\u00E7\n \"DS bypass mode\" \u2192 DS'siz devam\n```\n\n### 0b \u2014 DS asset cache haz\u0131rl\u0131\u011F\u0131\n```\n1. .claude/design-systems/<library-id>/components.md var m\u0131?\n2. .claude/design-systems/<library-id>/tokens.md var m\u0131?\n3. Yoksa: figma_get_library_variables + figma_search_assets ile ke\u015Ffet, cache'e yaz\n```\n\n### 0c \u2014 Kullan\u0131c\u0131ya DS se\u00E7imi sor\nactive-ds.md `\u274C` ise: \"Hangi DS? (SUI / Material / HIG / Kendi / Hi\u00E7biri)\". Yan\u0131t sonras\u0131 active-ds.md g\u00FCncelle, 0b'ye ge\u00E7. Sonraki turlarda TEKRAR SORMA.\n\n## 1. Kritik Kurallar\n\n1. **`return` ile veri d\u00F6n.** `figma.closePlugin()` \u00E7a\u011F\u0131rma.\n\n2. **D\u00FCz JS, top-level `await`.** Kod otomatik async sar\u0131l\u0131r. `(async()=>{})()` sarma. **Async API zorunlu** \u2014 dynamic-page mode'da sync API'ler throws:\n\n | \u274C YASAK (sync) | \u2705 ZORUNLU (async) |\n |---|---|\n | `instance.mainComponent` | `await instance.getMainComponentAsync()` |\n | `figma.getNodeById(id)` | `await figma.getNodeByIdAsync(id)` |\n | `figma.variables.importVariableByKey(key)` | `await figma.variables.importVariableByKeyAsync(key)` |\n | `figma.importComponentByKey(key)` | `await figma.importComponentByKeyAsync(key)` |\n | `figma.importStyleByKey(key)` | `await figma.importStyleByKeyAsync(key)` |\n | `node.effectStyleId = x` | `await node.setEffectStyleIdAsync(x)` |\n | `node.textStyleId = x` | `await node.setTextStyleIdAsync(x)` |\n | `figma.listAvailableFonts()` | `await figma.listAvailableFontsAsync()` |\n | `figma.loadFont(...)` | `await figma.loadFontAsync(...)` |\n | `figma.variables.getVariableCollectionById(id)` | `await figma.variables.getVariableCollectionByIdAsync(id)` |\n\n3. **`figma.notify()` \u00E7al\u0131\u015Fmaz** \u2014 kullanma.\n\n4. **`console.log()` d\u00F6nmez** \u2014 `return` kullan.\n\n5. **K\u00FC\u00E7\u00FCk ad\u0131mlarla \u00E7al\u0131\u015F.** Timeout: varsay\u0131lan 15000ms, max 30000ms.\n\n ### 5a. CHUNKING MANDATE (v2.0)\n\n Her `figma_execute` **max 15 atomic operation**. Atomic op'lar: node/instance olu\u015Fturma, variable/style/component import, font load, bind operasyonu, getNodeByIdAsync, getMainComponentAsync.\n\n - 1 execute = 1 mega-goal (discovery, frame+structure, 3-4 component placement)\n - 25+ op \u2192 2-3 execute'a b\u00F6l\n - Execute aras\u0131 state: nodeId'leri `return` et, sonraki execute `getNodeByIdAsync` ile al\n - Her execute sonras\u0131 1 sat\u0131r T\u00FCrk\u00E7e micro-report\n\n6. **Renkler 0\u20131 aral\u0131\u011F\u0131nda** (0\u2013255 de\u011Fil). Hardcoded renk YASAK \u2014 DS'den oku.\n\n7. **Fills/strokes read-only array** \u2014 klonla, de\u011Fi\u015Ftir, ata:\n ```js\n const fills = [...node.fills];\n fills[0] = { ...fills[0], color: DS_COLOR };\n node.fills = fills;\n ```\n\n8. **Font y\u00FCkleme zorunlu.** S\u0131ra: (a) DS cache'ten font oku \u2192 (b) Yoksa kullan\u0131c\u0131ya sor \u2192 (c) \"Sen se\u00E7\" \u2192 Inter.\n\n **8a-1) Font weight check (ZORUNLU):** `loadFontAsync` \u00F6ncesi `listAvailableFontsAsync` ile kontrol et. Fallback helper:\n ```js\n const allFonts = await figma.listAvailableFontsAsync();\n const styles = allFonts.filter(f => f.fontName.family === \"SHBGrotesk\").map(f => f.fontName.style);\n function pickStyle(desired, available) {\n if (available.indexOf(desired) >= 0) return desired;\n var fb = { \"Medium\":[\"Semi Bold\",\"Regular\"], \"ExtraBold\":[\"Bold\"], \"Black\":[\"Bold\"], \"Thin\":[\"Light\",\"Regular\"] };\n var alts = fb[desired] || [];\n for (var i = 0; i < alts.length; i++) { if (available.indexOf(alts[i]) >= 0) return alts[i]; }\n return available.find(s => s.indexOf(\"Italic\") < 0) || available[0];\n }\n await figma.loadFontAsync({ family: \"SHBGrotesk\", style: pickStyle(\"Medium\", styles) });\n ```\n **FigJam:** `createShapeWithText()` varsay\u0131lan \"Inter Medium\". Metin d\u00FCzenlemeden \u00F6nce `await figma.loadFontAsync(shape.text.fontName)`.\n\n9. **Sayfa konteksti her \u00E7a\u011Fr\u0131da s\u0131f\u0131rlan\u0131r.** Farkl\u0131 sayfa: `await figma.setCurrentPageAsync(page)`.\n\n10. **T\u00FCm tasar\u0131m de\u011Ferleri DS variable'a BA\u011ELANMALI (ZORUNLU).**\n\n Renk, spacing, padding, radius \u2014 H\u0130\u00C7B\u0130R de\u011Fer hardcoded yaz\u0131lmaz. Token yoksa DURDUR, kullan\u0131c\u0131ya sor.\n\n **Ak\u0131\u015F:**\n - **Variable import:** `const v = await figma.variables.importVariableByKeyAsync(\"KEY\")`\n - **Renk bind:** `node.fills = [figma.variables.setBoundVariableForPaint(fills[0], \"color\", v)]`\n - **Spacing bind:** `node.setBoundVariable(\"paddingLeft\", v)`\n - **Text style:** `await textNode.setTextStyleIdAsync(style.id)`\n - **Text renk:** `textNode.fills = [figma.variables.setBoundVariableForPaint(textFills[0], \"color\", textColorVar)]`\n\n Hardcoded `node.fills = [{ type: \"SOLID\", color: {...} }]` YASAK.\n\n10a. **Inline Bind Verification (v1.9.4, ZORUNLU).** Her execute sonunda olu\u015Fturulan node'lar\u0131 tara. Bind eksikse `throw` at\u0131l\u0131r \u2014 execute ba\u015Far\u0131s\u0131z say\u0131l\u0131r, Claude retry eder. \u015Eablon:\n\n ```js\n // Execute'un sonunda, createdNodes listesini taray\u0131p bind kontrol\u00FC yap:\n function assertBound(node) {\n // Fill bind\n if (Array.isArray(node.fills)) {\n for (var i = 0; i < node.fills.length; i++) {\n var f = node.fills[i];\n if (f && f.visible !== false && f.type === \"SOLID\") {\n var fbv = node.boundVariables && node.boundVariables.fills;\n var bound = fbv && (Array.isArray(fbv) ? fbv[i] : true);\n if (!bound) throw new Error(\"UNBOUND_FILL: \" + node.name + \" \u2014 setBoundVariableForPaint cagrisi eksik\");\n }\n }\n }\n // Padding/itemSpacing/radius bind (auto-layout frame)\n if (node.type === \"FRAME\" || node.type === \"COMPONENT\") {\n var padProps = [\"paddingTop\",\"paddingBottom\",\"paddingLeft\",\"paddingRight\"];\n for (var j = 0; j < padProps.length; j++) {\n var p = padProps[j];\n if (typeof node[p] === \"number\" && node[p] > 0 && !(node.boundVariables && node.boundVariables[p])) {\n throw new Error(\"UNBOUND_PADDING: \" + node.name + \".\" + p + \"=\" + node[p] + \" \u2014 setBoundVariable cagrisi eksik\");\n }\n }\n if (typeof node.itemSpacing === \"number\" && node.itemSpacing > 0 && !(node.boundVariables && node.boundVariables.itemSpacing)) {\n throw new Error(\"UNBOUND_ITEMSPACING: \" + node.name + \" \u2014 setBoundVariable('itemSpacing', v) cagrisi eksik\");\n }\n var radProps = [\"cornerRadius\",\"topLeftRadius\",\"topRightRadius\",\"bottomLeftRadius\",\"bottomRightRadius\"];\n for (var k = 0; k < radProps.length; k++) {\n var r = radProps[k];\n if (typeof node[r] === \"number\" && node[r] > 0 && !(node.boundVariables && node.boundVariables[r])) {\n throw new Error(\"UNBOUND_RADIUS: \" + node.name + \".\" + r + \"=\" + node[r]);\n }\n }\n }\n // Text style\n if (node.type === \"TEXT\" && !(node.textStyleId && typeof node.textStyleId === \"string\" && node.textStyleId !== \"\")) {\n throw new Error(\"UNBOUND_TEXTSTYLE: '\" + (node.characters||\"\").slice(0,30) + \"' \u2014 setTextStyleIdAsync(style.id) cagrisi eksik\");\n }\n }\n\n // T\u00FCm olu\u015Fturulan node'lar\u0131 do\u011Frula:\n for (var n = 0; n < createdNodes.length; n++) assertBound(createdNodes[n]);\n ```\n\n Bu kontrol atlan\u0131rsa `figma_scan_ds_compliance` final gate'te sonu\u00E7 zaten BLOCKING olur \u2014 ama inline check erkendedir ve context'i az yer. **v1.9.4 \u00F6nerisi:** Her mega-step sonunda bu assertion blo\u011Funu execute'un sonuna koy.\n\n11. **appendChild s\u0131ralamas\u0131 kritik.** \u00D6NCE `parent.appendChild(child)`, SONRA `child.layoutSizingHorizontal = \"FILL\"` / `layoutPositioning = \"ABSOLUTE\"`:\n ```js\n parent.appendChild(child); // \u00D6NCE\n child.layoutSizingHorizontal = \"FILL\"; // SONRA\n ```\n Hata: \"Can only set layoutPositioning = ABSOLUTE if parent has layoutMode !== NONE\" \u2192 child append edilmemi\u015F.\n\n12. **Yeni node'lar\u0131 (0,0)'dan uza\u011Fa konumland\u0131r.** Bo\u015F alan bul.\n\n13. **Hata durumunda DUR.** Hata oku, d\u00FCzelt, tekrar \u00E7al\u0131\u015Ft\u0131r. Atomik \u2014 hata olursa de\u011Fi\u015Fiklik uygulanmaz.\n\n14. **T\u00FCm node ID'lerini RETURN ET:** `return { createdNodeIds: [...] }`\n\n15. **Variable scope'lar\u0131:** Arka plan: `[\"FRAME_FILL\"]`, Metin: `[\"TEXT_FILL\"]`, Bo\u015Fluk: `[\"GAP\"]`\n\n16. **Her Promise'i `await` et.**\n\n17. **v1.9.5 Concise Query Rule \u2014 tek sat\u0131r boyut/metadata sorgular\u0131.**\n\n Boyut, renk, layout sorgulamak i\u00E7in **20+ sat\u0131r JS YAZMA**. Tek sat\u0131r yeter:\n\n ```js\n // \u0130Y\u0130 \u2014 tek sat\u0131r, minimal context\n return await figma.getNodeByIdAsync(id).then(n => ({ w: n.width, h: n.height, children: n.children?.length }));\n\n // \u0130Y\u0130 \u2014 toplu (birden fazla node)\n return Promise.all(ids.map(async id => {\n const n = await figma.getNodeByIdAsync(id);\n return { id, name: n?.name, size: n ? [n.width, n.height] : null };\n }));\n\n---\n\n<!-- fmcp-screen-recipes (2092 tokens) -->\n---\nname: fmcp-screen-recipes\ndescription: Fast path cookbook \u2014 standart ekran tipleri (login/payment/profile/list/detail/form/onboarding/dashboard/settings) i\u00E7in 5 mega-ad\u0131ml\u0131 recipe. Max 15 op/execute, cache-first discovery, her ad\u0131mda T\u00FCrk\u00E7e micro-report.\nmetadata:\n mcp-server: user-figma-mcp-bridge\n version: 3.0.0\n priority: 96\n phase: fast-path\n personas:\n - designer\n - uidev\n token_budget: condensed-first\nrequired_inputs:\n - name: screen_type\n type: \"enum: login | payment | profile | list | detail | form | onboarding | dashboard | settings\"\n - name: platform\n type: \"enum: mobile | tablet | desktop | web\"\n - name: device_preset\n type: string\n - name: variants\n type: \"array: [light] | [light, dark]\"\n - name: active_ds\n type: string\noutputs:\n - name: light_frame_id\n type: string\n - name: dark_frame_id\n type: \"string | null\"\n - name: validate_scores\n type: \"{ light: number, dark: number | null }\"\n---\n\n# FMCP Screen Recipes \u2014 Fast Path Cookbook\n\n## Ne Zaman Kullan\u0131l\u0131r\n\n**Fast Path DEVREYE G\u0130RER** (hepsi TRUE olmal\u0131):\n- \u2705 Tek ekran \u00FCretimi\n- \u2705 Standart ekran tipi: 9 recipe'ten biri match ediyor\n- \u2705 DS tan\u0131ml\u0131: `active-ds.md` Status: \u2705 Aktif\n- \u2705 Platform belli\n- \u2705 Custom animation / prototype YOK\n\n**Devreye G\u0130RMEZ:** Multi-screen flow, custom layout, animation, explicit generate-figma-screen talebi, DS GATE ge\u00E7ilmemi\u015Fse.\n\n---\n\n## 5 Mega-Ad\u0131ml\u0131 Ak\u0131\u015F\n\nMax **15 op/execute**. Her mega-ad\u0131m sonras\u0131 tek sat\u0131r T\u00FCrk\u00E7e micro-report.\n\n```\nM1: Pre-Flight Discovery + Token + Text Style (1 execute, ~15 op)\nM2: Frame + Structure + Modes (1 execute, ~12-14 op)\nM3: Component Placement (toplu, 3-4/execute) (2-3 execute, ~12-15 op each)\n \u21B3 Her M3 execute sonras\u0131: figma_scan_ds_compliance(threshold=85) inline gate\nM4: Dark Variant (1 execute, ~4 op)\nM5: Validate + Final Report (ZORUNLU: figma_scan_ds_compliance(detailed) + figma_validate_screen)\n```\n\n**Toplam execute:** ~6-8 + 2-3 scan call. **Hedef s\u00FCre:** ~10 dk. **v1.9.4:** Scan call'lar\u0131 h\u0131zl\u0131d\u0131r (~150ms), execute b\u00FCt\u00E7esini yemezler.\n\n### 3 MUTLAK KURAL\n\n**KURAL 1 \u2014 Fill Bind Zorunlu (frame + text dahil):**\n```js\nconst paint = { type: 'SOLID', color: { r: 1, g: 1, b: 1 } };\nconst bound = figma.variables.setBoundVariableForPaint(paint, 'color', dsColorVar);\nnode.fills = [bound];\n```\nFill panel'de variable icon \uD83C\uDFA8 G\u00D6R\u00DCNMELI. Hardcoded hex YASAK. Frame fill + text fill + primitive dahil T\u00DCM node'lar.\n\n**KURAL 2 \u2014 Variant Se\u00E7im: DEFAULT Koru:**\n- `setProperties` ile SADECE recipe'de explicit belirtilen property'leri set et\n- Di\u011Fer T\u00DCM property'leri DEFAULT b\u0131rak\n- `Product` \u2192 main (default), Boolean kontroller \u2192 recipe'de explicit yoksa DEFAULT\n\n**KURAL 3 \u2014 Token Bind, Alias Resolve ETME:**\n`setBoundVariable(property, importedVariable)` ile bind et. Figma runtime alias chain'i otomatik \u00E7\u00F6zer. `valuesByMode` okuma, alias traversal YASAK (timeout riski).\n\n### Mega-Ad\u0131m Mapping\n\nA\u015Fa\u011F\u0131daki eski ad\u0131mlar REFERANS ama\u00E7l\u0131d\u0131r. AYRI AYRI execute ETME \u2014 mega-ad\u0131m tablosunu takip et:\n- **M1:** Ad\u0131m 1 (validation) + 1.5 (discovery) + 1.6 (text style) \u2192 TEK execute\n- **M2:** Ad\u0131m 2 (frame) + 4b (mode) + 5.5 (content body) \u2192 TEK execute\n- **M3:** Ad\u0131m 6 (discovery) + 7 (placement) \u2192 2-3 execute\n- **M4:** Ad\u0131m 8 (dark) \u2192 TEK execute\n- **M5:** Ad\u0131m 9 (validate) \u2192 1-2 validate call\n\n---\n\n### Ad\u0131m 1 \u2014 Pre-Flight Check\n\nHi\u00E7bir figma_execute \u00E7a\u011F\u0131rma. Do\u011Frula: active-ds.md \u2705, screen_type ge\u00E7erli, platform + device_preset ge\u00E7erli, variants \u22651.\n\n**Micro-report:** `\u2705 Pre-flight: screen_type=<X>, platform=<Y>, device=<Z>, variants=<V>`\n\n### Ad\u0131m 1.5 \u2014 Unified Pre-Flight Discovery\n\n**Cache-First (v3.0+):** \u00D6nce `.claude/design-systems/sui/tokens.md` oku. Cache varsa ve <7 g\u00FCn \u2192 token discovery ATLA, cache'ten kullan. Yoksa a\u015Fa\u011F\u0131daki execute'lar\u0131 \u00E7al\u0131\u015Ft\u0131r, sonra cache'i g\u00FCncelle.\n\nToken name matching: SUI nested path format\u0131 (`\"Spacing/spacing-100\"`). `endsWith` match kullan:\n```js\nvars.find(v => v.name.endsWith(\"/\" + suffix) || v.name === suffix)\n```\n\n#### Execute 1 \u2014 Collection & Mode Discovery (7 op)\n\n```js\nconst colls = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();\nfunction findColl(keywords) {\n return colls.find(c => {\n const n = c.name.toLowerCase().trim();\n return keywords.some(kw => n.includes(kw));\n });\n}\nconst sizeColl = findColl([\"semantic size\", \"semantic sizes\", \"size\"]);\nconst colorsColl = findColl([\"semantic color\", \"s theme\"]);\nconst result = { availableColls: colls.map(c => ({name: c.name, key: c.key})), spacingTokenKeys: {}, collectionInfo: { colors: null, size: null }, surfaceKey: null };\n\nif (sizeColl) {\n const sizeVars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(sizeColl.key);\n const suffixes = [\"spacing-none\",\"spacing-050\",\"spacing-075\",\"spacing-100\",\"spacing-125\",\"spacing-150\",\"spacing-200\"];\n for (const s of suffixes) {\n const f = sizeVars.find(v => v.name.endsWith(\"/\"+s) || v.name === s);\n if (f) result.spacingTokenKeys[s] = f.key;\n }\n if (sizeVars.length > 0) {\n const first = await figma.variables.importVariableByKeyAsync(sizeVars[0].key);\n const coll = await figma.variables.getVariableCollectionByIdAsync(first.variableCollectionId);\n result.collectionInfo.size = { collId: coll.id, modes: coll.modes.map(m => ({name: m.name, modeId: m.modeId})) };\n }\n}\nif (colorsColl) {\n const colorsVars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(colorsColl.key);\n const bgVar = colorsVars.find(v => v.name.toLowerCase().includes(\"background\") && v.name.toLowerCase().includes(\"level-0\"));\n if (bgVar) result.surfaceKey = bgVar.key;\n if (colorsVars.length > 0) {\n const first = await figma.variables.importVariableByKeyAsync(colorsVars[0].key);\n const coll = await figma.variables.getVariableCollectionByIdAsync(first.variableCollectionId);\n result.collectionInfo.colors = { collId: coll.id, modes: coll.modes.map(m => ({name: m.name, modeId: m.modeId})) };\n }\n}\nreturn result;\n```\n\n#### Execute 2 \u2014 Critical Token Import (7 op)\n\n```js\nconst tokenKeyMap = {};\nconst spacingKeys = { /* Execute 1'den gelen spacingTokenKeys */ };\nfor (const [suffix, key] of Object.entries(spacingKeys)) {\n try {\n const imported = await figma.variables.importVariableByKeyAsync(key);\n tokenKeyMap[suffix] = imported.id;\n } catch(e) {}\n}\nreturn { tokenKeyMap };\n```\n\n**Micro-report:** `\u2705 Pre-Flight Discovery: <N> collection, <M> token imported, surface=<found/missing>`\n\n### Ad\u0131m 1.6 \u2014 Text Style Resolution\n\nDosyadaki mevcut text style'lar\u0131 tara, role mapping \u00FCret. `importStyleByKeyAsync` \u00C7A\u011EIRMA \u2014 direkt `setTextStyleIdAsync(roleMap[role].id)` kullan.\n\n```js\nconst allTexts = figma.currentPage.findAll(n => n.type === \"TEXT\");\nconst uniqueStyleIds = new Set();\nfor (const t of allTexts) { if (t.textStyleId && typeof t.textStyleId === 'string') uniqueStyleIds.add(t.textStyleId); }\n\nconst styleMap = {};\nfor (const id of uniqueStyleIds) {\n try { const style = await figma.getStyleByIdAsync(id); if (style) styleMap[style.id] = { id: style.id, name: style.name, fontSize: style.fontSize || null }; } catch(e) {}\n}\n\nconst roleKeywords = {\n display: [\"display\",\"hero\",\"amount\",\"title-xl\"], title: [\"section-title\",\"title\",\"heading\"],\n subtitle: [\"subtitle\",\"body-semibold\",\"body-bold\"], body: [\"body-medium\",\"body-regular\",\"body\"],\n caption: [\"small\",\"caption\",\"footnote\"], button: [\"button\"]\n};\nfunction findStyle(kws) { for (const kw of kws) { const m = Object.values(styleMap).find(s => (s.name||\"\").toLowerCase().includes(kw.toLowerCase())); if (m) return m; } return null; }\nconst roleMap = {};\nfor (const [role, kws] of Object.entries(roleKeywords)) { const m = findStyle(kws); if (m) roleMap[role] = { id: m.id, name: m.name, fontSize: m.fontSize }; }\nif (!roleMap.display) {\n const sorted = Object.values(styleMap).filter(s => s.fontSize).sort((a,b) => b.fontSize - a.fontSize);\n if (sorted.length > 0) roleMap.display = { id: sorted[0].id, name: sorted[0].name, fontSize: sorted[0].fontSize };\n}\nreturn { totalStyles: Object.keys(styleMap).length, styleMap, roleMap };\n```\n\n**Micro-report:** `\u2705 Text Style: <N> style, <M> role e\u015Fle\u015Fti`\n\n---\n\n### Ad\u0131m 2 \u2014 Wrapper Frame + Background (Edge-to-Edge)\n\nAna frame: device preset boyutu, auto-layout VERTICAL, padding=0, gap=0, background DS variable'a ba\u011Fl\u0131.\n\n**Edge-to-Edge yap\u0131:**\n\n---\n\n<!-- fmcp-project-rules (1370 tokens) -->\n---\nname: fmcp-project-rules\ndescription: F-MCP Bridge kullan\u0131m kurallar\u0131 \u2014 Design Token Kural\u0131, Ba\u011Fl\u0131 Token Kural\u0131, k\u00FCt\u00FCphane y\u00F6netimi, otomatik yan\u0131t kurallar\u0131. T\u00FCm F-MCP skill'leri i\u00E7in ge\u00E7erli temel kurallar. Her Figma i\u015Fleminde bu kurallar otomatik olarak ge\u00E7erlidir.\nmetadata:\n mcp-server: user-figma-mcp-bridge\n personas:\n - designer\n - designops\n - uidev\n - po\n---\n\n# F-MCP Temel Kurallar\n\nBu skill, t\u00FCm F-MCP skill'leri ve komutlar\u0131 i\u00E7in ge\u00E7erli olan temel kurallar\u0131 tan\u0131mlar. Her Figma i\u015Fleminde bu kurallar otomatik olarak uygulan\u0131r.\n\n## Kullan\u0131c\u0131 \u0130stekleri \u2014 Otomatik Yan\u0131t\n\n### \"F-MCP'yi g\u00FCncelle\" / \"update\" / \"g\u00FCncelle\"\nTerminal komutu verme. `bash scripts/update.sh` \u00E7al\u0131\u015Ft\u0131r, sonucu bildir:\n> G\u00FCncelleme tamamland\u0131 (vX.Y.Z). Claude'u yeniden ba\u015Flat ve Figma'da plugin'i kapat-a\u00E7.\n\n### \"F-MCP'yi kur\" / \"setup\" / \"kur\" / \"bunu kur\" / GitHub linki verildi\nKullan\u0131c\u0131 GitHub linki (github.com/atezer/FMCP) verip \"kur\" derse veya herhangi bir \u015Fekilde kurulum isterse:\n\n1. Repo zaten clone edilmi\u015Fse: `bash scripts/setup.sh` \u00E7al\u0131\u015Ft\u0131r\n2. Repo clone edilmemi\u015Fse: `git clone https://github.com/atezer/FMCP.git && cd FMCP && bash scripts/setup.sh`\n3. Kullan\u0131c\u0131ya sadece sonucu bildir.\n\nKullan\u0131c\u0131ya ASLA terminal komutu s\u00F6yleme, teknik ad\u0131m a\u00E7\u0131klama. Her \u015Feyi sen yap.\n\n### Dil\nKullan\u0131c\u0131 T\u00FCrk\u00E7e konu\u015Fuyor. T\u00FCm dosyalarda T\u00FCrk\u00E7e karakterler (\u015F, \u00E7, \u011F, \u00F6, \u00FC, \u0131, \u0130) do\u011Fru kullan\u0131lmal\u0131.\n\n---\n\n## Design System K\u00FCt\u00FCphaneleri\n\nKullan\u0131c\u0131 lokal olarak design system k\u00FCt\u00FCphaneleri kaydedebilir. Kay\u0131tl\u0131 k\u00FCt\u00FCphaneler `.claude/libraries/` dizininde bulunur.\n\n### Kullan\u0131m kurallar\u0131\n\n1. **Skill \u00E7al\u0131\u015Ft\u0131rmadan \u00F6nce** `.claude/libraries/` dizinini kontrol et. Kay\u0131tl\u0131 k\u00FCt\u00FCphane varsa oku.\n2. **Varsay\u0131lan k\u00FCt\u00FCphane:** Kullan\u0131c\u0131 \"hangi k\u00FCt\u00FCphane?\" demi\u015Fse veya context'ten anla\u015F\u0131lam\u0131yorsa, kay\u0131tl\u0131 k\u00FCt\u00FCphanelerden ilkini kullan.\n3. **Figma file key'leri** k\u00FCt\u00FCphane dosyas\u0131ndaki tablolardan al \u2014 URL'den parse etme, do\u011Frudan `File Key` alan\u0131n\u0131 kullan.\n4. **Token okuma** her zaman k\u00FCt\u00FCphanenin WEB/ana dosyas\u0131ndan yap\u0131l\u0131r.\n5. **Platform se\u00E7imi:** Web ekran\u0131 \u2192 WEB dosyas\u0131, Mobil ekran \u2192 Mobil dosyas\u0131 (yoksa WEB fallback).\n\n---\n\n## Design Token Kural\u0131 (T\u00DCM skill'ler i\u00E7in ge\u00E7erli \u2014 ZORUNLU)\n\nHi\u00E7bir skill g\u00F6m\u00FCl\u00FC/hardcoded design token de\u011Feri i\u00E7eremez ve kullanamaz. Font ailesi, renk kodu, font boyutu, spacing, radius, g\u00F6lge \u2014 hi\u00E7bir tasar\u0131m de\u011Feri skill i\u00E7ine yaz\u0131lmaz.\n\n**Her tasar\u0131m de\u011Feri \u00E7al\u0131\u015Fma an\u0131nda tasar\u0131m sisteminden okunur:**\n\n1. **\u00D6nce kay\u0131tl\u0131 k\u00FCt\u00FCphaneyi oku:** `.claude/libraries/` dizinindeki k\u00FCt\u00FCphane dosyas\u0131n\u0131 kontrol et. Font ailesi, variable collection'lar ve style listesi orada.\n2. **Canl\u0131 de\u011Ferleri Figma'dan al:**\n - **K\u00FCt\u00FCphane variable'lar\u0131 (renkler, spacing)** \u2192 `figma_get_library_variables()` veya `figma_execute` ile `figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync()` + `getVariablesInLibraryCollectionAsync()` \u2014 DS dosyas\u0131na ba\u011Flanmak GEREKMEZ, hedef dosyadan \u00E7al\u0131\u015F\u0131r\n - **Lokal variable'lar** \u2192 `figma_get_variables()` \u2014 sadece dosya i\u00E7i de\u011Ferler\n - **Lokal stiller** \u2192 `figma_get_styles()` \u2014 sadece dosya i\u00E7i stiller\n - **K\u00FCt\u00FCphane text style'lar\u0131** \u2192 cache'den key al, `figma.importStyleByKeyAsync(key)` ile import et. Cache yoksa REST API: `figma_rest_api GET /v1/files/{fileKey}/styles`\n - Font \u2192 k\u00FCt\u00FCphane text style'lar\u0131ndan veya k\u00FCt\u00FCphanenin `Font Ailesi` alan\u0131ndan\n - G\u00F6lgeler \u2192 `figma_get_styles()` effect style'lar\u0131ndan veya k\u00FCt\u00FCphane cache'inden\n3. **Bulunamazsa kullan\u0131c\u0131ya sor.**\n4. **Kullan\u0131c\u0131 \"sen se\u00E7\" derse:** \u00D6nce DS k\u00FCt\u00FCphanesi ba\u011Fl\u0131ysa DS fontunu kullan (text style'lardan \u00E7\u0131kar). DS fontu bulunamad\u0131ysa `Inter`, renkler i\u00E7in Figma varsay\u0131lanlar\u0131 kullan.\n\n**\u00D6NEML\u0130:** `figma_get_styles()` ve `figma_get_variables()` sadece dosya \u0130\u00C7\u0130 (local) de\u011Ferleri d\u00F6nd\u00FCr\u00FCr. Team library'den gelen token'lar i\u00E7in `figma_get_library_variables` veya `figma.teamLibrary` API'si kullan\u0131lmal\u0131d\u0131r.\n\n**Skill'lerdeki kod \u00F6rnekleri:** \u00D6rneklerde ge\u00E7en de\u011Ferler (renk hex, font ad\u0131, piksel boyutu) yaln\u0131zca FORMAT g\u00F6sterimidir. \u00C7al\u0131\u015Fma an\u0131nda bu de\u011Ferler her zaman tasar\u0131m sisteminden okunmal\u0131d\u0131r.\n\n---\n\n## Ba\u011Fl\u0131 Token Kural\u0131 (ZORUNLU \u2014 t\u00FCm ekran/bile\u015Fen olu\u015Fturma i\u015Flemlerinde)\n\nFigma'da olu\u015Fturulan hi\u00E7bir node'da **ba\u011Flanmam\u0131\u015F (unbound) tasar\u0131m de\u011Feri** bulunmamal\u0131d\u0131r. Her renk, spacing, padding, radius ve metin stili DS variable'\u0131na veya text style'\u0131na **ba\u011Fl\u0131 (bound)** olmal\u0131d\u0131r.\n\n- **Renk (fill/stroke):** `figma.variables.importVariableByKeyAsync(key)` ile import et, `setBoundVariableForPaint()` ile ba\u011Fla\n- **Spacing/padding/radius/gap:** `setBoundVariable(\"paddingLeft\", variable)` ile ba\u011Fla\n- **Metin stili:** `setTextStyleIdAsync(styleId)` ile DS text style'\u0131n\u0131 uygula\n- **Metin rengi:** Text node fill'ini `setBoundVariableForPaint()` ile ba\u011Fla\n\n**Hardcoded de\u011Fer kabul edilmez.** `node.fills = [{ type: \"SOLID\", color: {r,g,b} }]` veya `node.fontSize = 16` gibi do\u011Frudan de\u011Fer atamalar\u0131 YASAKTIR. T\u00FCm de\u011Ferler DS'ten import edilip ba\u011Flanmal\u0131d\u0131r.\n\nDetayl\u0131 API kullan\u0131m\u0131: `figma-canvas-ops` skill'inin **madde 10** b\u00F6l\u00FCm\u00FCne bak.\n\n---\n\n## Mevcut k\u00FCt\u00FCphaneler\n\nKay\u0131tl\u0131 k\u00FCt\u00FCphaneleri g\u00F6rmek i\u00E7in `.claude/libraries/` dizinini kontrol et. Her `.md` dosyas\u0131 bir k\u00FCt\u00FCphanedir. K\u00FCt\u00FCphane eklemek i\u00E7in `/add-library` komutunu kullan.\n\n## Evolution Triggers\n\n- Yeni DS kural kategorisi eklendi\u011Finde bu skill g\u00FCncellenmelidir.\n- Yeni platform deste\u011Fi (Flutter, React Native vb.) eklendi\u011Finde platform se\u00E7imi kurallar\u0131 geni\u015Fletilmelidir.\n- Kullan\u0131c\u0131 geri bildirimine g\u00F6re otomatik yan\u0131t kurallar\u0131 g\u00FCncellenmelidir.";
14
+ export declare const EMBEDDED_SKILLS_TOKEN_ESTIMATE = 9349;
15
+ export declare const EMBEDDED_SKILLS_VERSION = "1.9.7";
16
+ export declare const EMBEDDED_SKILLS_GENERATED_AT = "2026-04-18T08:23:36.324Z";
17
+ //# sourceMappingURL=embedded-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded-skills.d.ts","sourceRoot":"","sources":["../../src/core/embedded-skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,uBAAuB,q62CAgyByC,CAAC;AAE9E,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAC/C,eAAO,MAAM,4BAA4B,6BAA6B,CAAC"}