@sxl-studio/bridge 1.5.1 → 1.7.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.
- package/README.md +35 -2
- package/dist/agent-recipes.d.ts +268 -0
- package/dist/agent-recipes.js +637 -0
- package/dist/agent-recipes.js.map +1 -1
- package/dist/command-queue.js +16 -0
- package/dist/command-queue.js.map +1 -1
- package/dist/http-api.d.ts +1 -0
- package/dist/http-api.js +7 -2
- package/dist/http-api.js.map +1 -1
- package/dist/mcp-factory.js +11 -1
- package/dist/mcp-factory.js.map +1 -1
- package/dist/sxl-mcp-instructions.js +142 -2
- package/dist/sxl-mcp-instructions.js.map +1 -1
- package/dist/tools/audit.d.ts +49 -0
- package/dist/tools/audit.js +83 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/catalogue-bootstrap.js +34 -0
- package/dist/tools/catalogue-bootstrap.js.map +1 -1
- package/dist/tools/compositions-orchestration.d.ts +91 -0
- package/dist/tools/compositions-orchestration.js +101 -0
- package/dist/tools/compositions-orchestration.js.map +1 -0
- package/dist/tools/mockup.d.ts +323 -0
- package/dist/tools/mockup.js +206 -0
- package/dist/tools/mockup.js.map +1 -0
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +52 -2
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/styles-orchestration.d.ts +544 -0
- package/dist/tools/styles-orchestration.js +175 -0
- package/dist/tools/styles-orchestration.js.map +1 -0
- package/dist/tools/tokens.d.ts +60 -60
- package/dist/tools/variables-orchestration.d.ts +20 -0
- package/dist/tools/variables-orchestration.js +116 -0
- package/dist/tools/variables-orchestration.js.map +1 -0
- package/dist/workspace-blob-http.d.ts +9 -0
- package/dist/workspace-blob-http.js +154 -0
- package/dist/workspace-blob-http.js.map +1 -0
- package/dist/workspace-blob-store.d.ts +12 -0
- package/dist/workspace-blob-store.js +87 -0
- package/dist/workspace-blob-store.js.map +1 -0
- package/package.json +3 -2
package/dist/agent-recipes.js
CHANGED
|
@@ -96,6 +96,130 @@ export const RECIPE_INDEX = {
|
|
|
96
96
|
"render this spec as a figma flow",
|
|
97
97
|
],
|
|
98
98
|
},
|
|
99
|
+
{
|
|
100
|
+
recipeId: "variable-usage",
|
|
101
|
+
userPhrases: [
|
|
102
|
+
"сколько раз используется accent.medium",
|
|
103
|
+
"where is this variable used",
|
|
104
|
+
"посчитай где используется переменная",
|
|
105
|
+
"render a page with all usages of accent.medium",
|
|
106
|
+
"найди все объекты с переменной",
|
|
107
|
+
"show me everywhere this token appears",
|
|
108
|
+
"выведи на страницу все места где встречается переменная",
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
recipeId: "audit-coverage",
|
|
113
|
+
userPhrases: [
|
|
114
|
+
"проверь везде ли подкреплены переменные",
|
|
115
|
+
"найди объекты без переменных",
|
|
116
|
+
"audit raw values without variables",
|
|
117
|
+
"review the file for missing bindings",
|
|
118
|
+
"где hex заливки вместо токенов",
|
|
119
|
+
"найди объекты с дефолтными цветами",
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
recipeId: "find-unused",
|
|
124
|
+
userPhrases: [
|
|
125
|
+
"какие переменные у меня не используются",
|
|
126
|
+
"find unused variables",
|
|
127
|
+
"which styles are dead",
|
|
128
|
+
"почисть неиспользуемые токены",
|
|
129
|
+
"найди мёртвые стили",
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
recipeId: "bulk-variables",
|
|
134
|
+
userPhrases: [
|
|
135
|
+
"создай набор переменных по этому списку",
|
|
136
|
+
"import these variables in bulk",
|
|
137
|
+
"bulk create variables from spec",
|
|
138
|
+
"обнови переменные пакетно",
|
|
139
|
+
"перепривяжи алиасы переменных",
|
|
140
|
+
"rebind aliases from old token to new",
|
|
141
|
+
"найди дубликаты переменных и слей их",
|
|
142
|
+
"dedupe variables across collections",
|
|
143
|
+
"приведи коллекцию в алфавитный порядок",
|
|
144
|
+
"reorder variables alphabetically",
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
recipeId: "auto-bind-from-audit",
|
|
149
|
+
userPhrases: [
|
|
150
|
+
"примени предложенные переменные к аудиту",
|
|
151
|
+
"apply variable coverage suggestions",
|
|
152
|
+
"автопривяжи переменные где есть подсказки",
|
|
153
|
+
"fix the audit by binding suggested variables",
|
|
154
|
+
"convert audit suggestions into bindings",
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
recipeId: "bulk-styles",
|
|
159
|
+
userPhrases: [
|
|
160
|
+
"создай набор стилей по этому списку",
|
|
161
|
+
"import these paint/text/effect styles in bulk",
|
|
162
|
+
"bulk create paint styles from spec",
|
|
163
|
+
"обнови стили пакетно",
|
|
164
|
+
"найди дубликаты стилей и слей их",
|
|
165
|
+
"dedupe styles across the file",
|
|
166
|
+
"перепривяжи стили со старого на новый",
|
|
167
|
+
"rebind style consumers from one style to another",
|
|
168
|
+
"примени предложенные стили к аудиту",
|
|
169
|
+
"apply style coverage suggestions",
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
recipeId: "style-drift",
|
|
174
|
+
userPhrases: [
|
|
175
|
+
"проверь дрейф стилей и переменных",
|
|
176
|
+
"audit style drift vs variables",
|
|
177
|
+
"стили рассинхронизированы с токенами",
|
|
178
|
+
"find paint styles that drifted from variables",
|
|
179
|
+
"сверь PaintStyle со списком ожидаемых цветов",
|
|
180
|
+
"verify styles against expected colors",
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
recipeId: "mockup-builder",
|
|
185
|
+
userPhrases: [
|
|
186
|
+
"собери макет страницы из компонентов",
|
|
187
|
+
"build a mockup from existing components",
|
|
188
|
+
"сделай дашборд из карточек",
|
|
189
|
+
"render a screen using design system components",
|
|
190
|
+
"lay out cards in auto-layout",
|
|
191
|
+
"сложи макет из WCard и WButton",
|
|
192
|
+
"render a list of N cards from this dataset",
|
|
193
|
+
"построй продуктовую страницу по описанию",
|
|
194
|
+
"assemble a settings screen from existing components",
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
recipeId: "bulk-compositions",
|
|
199
|
+
userPhrases: [
|
|
200
|
+
"сгенерируй все компоненты дизайн-системы",
|
|
201
|
+
"regenerate every WAccordion / WButton from JSON",
|
|
202
|
+
"пересобери компоненты по композициям",
|
|
203
|
+
"apply all SXL compositions in this workspace",
|
|
204
|
+
"обнови компоненты после правок в JSON",
|
|
205
|
+
"rebuild every composition that drifted",
|
|
206
|
+
"перегенерируй все компоненты после очистки файла",
|
|
207
|
+
"fresh-bake the design system from compositions",
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
recipeId: "composition-drift",
|
|
212
|
+
userPhrases: [
|
|
213
|
+
"проверь рассинхрон композиций и компонентов",
|
|
214
|
+
"audit composition drift",
|
|
215
|
+
"какие компоненты не соответствуют JSON",
|
|
216
|
+
"find compositions that drifted from Figma",
|
|
217
|
+
"сверь tokens/components с реальными ComponentSet",
|
|
218
|
+
"verify SXL compositions still match the Figma design system",
|
|
219
|
+
"какие компоненты потерялись",
|
|
220
|
+
"show compositions whose tracked component was deleted",
|
|
221
|
+
],
|
|
222
|
+
},
|
|
99
223
|
],
|
|
100
224
|
decideBetween: [
|
|
101
225
|
{
|
|
@@ -118,6 +242,76 @@ export const RECIPE_INDEX = {
|
|
|
118
242
|
use_compose_with_variables_when: "goal is to generate a reusable Figma component with variable bindings from a design URL",
|
|
119
243
|
use_doc_composition_when: "goal is to render a documentation frame from an existing composition file",
|
|
120
244
|
},
|
|
245
|
+
{
|
|
246
|
+
between: ["variable-usage", "audit-coverage"],
|
|
247
|
+
use_variable_usage_when: "user names a specific variable and wants to know where / how often / 'покажи все места'",
|
|
248
|
+
use_audit_coverage_when: "user wants to know which nodes are NOT bound to variables (e.g. raw hex / dimensions)",
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
between: ["audit-coverage", "find-unused"],
|
|
252
|
+
use_audit_coverage_when: "the goal is finding nodes that lack a variable / style binding (where to ADD bindings)",
|
|
253
|
+
use_find_unused_when: "the goal is finding variables / styles that nothing references (what to DELETE)",
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
between: ["audit-coverage", "auto-bind-from-audit"],
|
|
257
|
+
use_audit_coverage_when: "user wants the LIST of missing bindings (no writes)",
|
|
258
|
+
use_auto_bind_from_audit_when: "user wants to APPLY the suggested variables (canvas write — apply_coverage_suggestions)",
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
between: ["bulk-variables", "doc-tokens"],
|
|
262
|
+
use_bulk_variables_when: "user wants to create / merge / refactor Figma Variables in bulk (one spec → many writes)",
|
|
263
|
+
use_doc_tokens_when: "user wants to render existing token values into a Figma doc frame",
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
between: ["bulk-styles", "bulk-variables"],
|
|
267
|
+
use_bulk_styles_when: "the targets are Figma local STYLES (PaintStyle / TextStyle / EffectStyle) — fillStyleId / textStyleId / effectStyleId fields",
|
|
268
|
+
use_bulk_variables_when: "the targets are Figma VARIABLES (boundVariables, valuesByMode)",
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
between: ["bulk-styles", "audit-coverage"],
|
|
272
|
+
use_bulk_styles_when: "user wants to ADD / MERGE / REFACTOR styles, or apply find_style_coverage_misses suggestions",
|
|
273
|
+
use_audit_coverage_when: "user only wants the LIST of nodes missing styleId / variable bindings (no writes)",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
between: ["style-drift", "audit-coverage"],
|
|
277
|
+
use_style_drift_when: "user wants to verify EXISTING styles match the source of truth (variables / token snapshot)",
|
|
278
|
+
use_audit_coverage_when: "user wants to find nodes that have NO style binding at all",
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
between: ["style-drift", "find-unused"],
|
|
282
|
+
use_style_drift_when: "the goal is to detect rendered values that drifted from the source of truth",
|
|
283
|
+
use_find_unused_when: "the goal is to delete styles that nothing references",
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
between: ["mockup-builder", "doc-component"],
|
|
287
|
+
use_mockup_builder_when: "user wants to ASSEMBLE a screen / dashboard / list from many existing components in auto-layout",
|
|
288
|
+
use_doc_component_when: "user wants to DOCUMENT a single component (title + variants matrix + props table)",
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
between: ["mockup-builder", "compose-with-variables"],
|
|
292
|
+
use_mockup_builder_when: "the goal is to compose existing components into a layout (consumer)",
|
|
293
|
+
use_compose_with_variables_when: "the goal is to generate / refactor the COMPONENT itself from a design URL (producer)",
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
between: ["mockup-builder", "doc-flow"],
|
|
297
|
+
use_mockup_builder_when: "user wants a SINGLE auto-layout screen built from components (not a series of pages)",
|
|
298
|
+
use_doc_flow_when: "user wants a STORY of multiple pages / screens stacked side-by-side with captions",
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
between: ["bulk-compositions", "compose-with-variables"],
|
|
302
|
+
use_bulk_compositions_when: "the composition JSON files already exist in the plugin workspace (`tokens/components/W*.json`) and you want to (re)build many components in one call",
|
|
303
|
+
use_compose_with_variables_when: "the composition JSON does NOT exist yet — you start from a Figma URL, export composition JSON, and generate one component",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
between: ["bulk-compositions", "composition-drift"],
|
|
307
|
+
use_bulk_compositions_when: "the user wants to WRITE (generate / apply) compositions",
|
|
308
|
+
use_composition_drift_when: "the user only wants to KNOW which compositions are out of sync (read-only)",
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
between: ["composition-drift", "style-drift"],
|
|
312
|
+
use_composition_drift_when: "the unit of comparison is a composition JSON ↔ Figma ComponentSet",
|
|
313
|
+
use_style_drift_when: "the unit of comparison is a local PaintStyle ↔ Variable / token snapshot",
|
|
314
|
+
},
|
|
121
315
|
],
|
|
122
316
|
forbidden: [
|
|
123
317
|
"Calling use_figma with a hand-written figma.* script when an SXL Bridge tool covers the task.",
|
|
@@ -419,4 +613,447 @@ export const RECIPE_VARIABLE_PALETTE = {
|
|
|
419
613
|
],
|
|
420
614
|
doneCriteria: "One card per target variable next to the template; each swatch is bound to its variable; no use_figma script was used.",
|
|
421
615
|
};
|
|
616
|
+
export const RECIPE_VARIABLE_USAGE = {
|
|
617
|
+
id: "variable-usage",
|
|
618
|
+
title: "Find usages of a Figma variable (count + visualize)",
|
|
619
|
+
version: 1,
|
|
620
|
+
userPhrases: [
|
|
621
|
+
"сколько раз используется accent.medium",
|
|
622
|
+
"where is this variable used",
|
|
623
|
+
"посчитай где используется переменная",
|
|
624
|
+
"render a page with all usages of accent.medium",
|
|
625
|
+
"найди все объекты с переменной",
|
|
626
|
+
"выведи на страницу все места где встречается переменная",
|
|
627
|
+
],
|
|
628
|
+
decideBetween: [
|
|
629
|
+
{
|
|
630
|
+
between: ["variable-usage", "audit-coverage"],
|
|
631
|
+
hint: "If user wants to find missing bindings (no variable assigned) → audit-coverage. If user names a variable and asks 'where is it used' → variable-usage.",
|
|
632
|
+
},
|
|
633
|
+
],
|
|
634
|
+
context: "analyze_variable_usage returns a token-friendly summary (counts only). For the full node list, use find_variable_usages with cursor pagination. To visualize the result on the canvas, call render_variable_usage_page (creates a fresh page with cloned references). All three resolve transitive aliases — a variable that aliases the target counts as a usage and is included in target.aliasChain.",
|
|
635
|
+
preferredTools: [
|
|
636
|
+
"get_variables",
|
|
637
|
+
"analyze_variable_usage",
|
|
638
|
+
"find_variable_usages",
|
|
639
|
+
"render_variable_usage_page",
|
|
640
|
+
],
|
|
641
|
+
forbidden: [
|
|
642
|
+
"Writing a use_figma script that walks node.boundVariables manually — analyze_variable_usage already does it (with alias resolution).",
|
|
643
|
+
"Calling find_variable_usages without limit/cursor for huge files — pagination keeps the agent fast and cheap.",
|
|
644
|
+
"Cloning nodes by hand into a new page — use render_variable_usage_page (chunked + auto-layout).",
|
|
645
|
+
],
|
|
646
|
+
steps: [
|
|
647
|
+
"Identify the variable (variableId is best). If only a name, get_variables narrows it down.",
|
|
648
|
+
"Call analyze_variable_usage { variable, scope: 'page'|'file' } first — small response, decides next step.",
|
|
649
|
+
"If user wants details: find_variable_usages { variable, scope, limit }, optionally paginate via the returned cursor.",
|
|
650
|
+
"If user wants visualization: render_variable_usage_page { variable, scope: 'file', maxClones }. Confirm writesAllowed first via get_plugin_status.",
|
|
651
|
+
],
|
|
652
|
+
doneCriteria: "Agent returned a count + breakdown (analyze) or a paginated record list (find) or created a 'Usage: <variable>' page (render). Transitive aliases included in target.aliasChain.",
|
|
653
|
+
};
|
|
654
|
+
export const RECIPE_AUDIT_COVERAGE = {
|
|
655
|
+
id: "audit-coverage",
|
|
656
|
+
title: "Audit nodes that lack a variable / style binding",
|
|
657
|
+
version: 1,
|
|
658
|
+
userPhrases: [
|
|
659
|
+
"проверь везде ли подкреплены переменные",
|
|
660
|
+
"найди объекты без переменных",
|
|
661
|
+
"audit raw values without variables",
|
|
662
|
+
"review the file for missing bindings",
|
|
663
|
+
"где hex заливки вместо токенов",
|
|
664
|
+
],
|
|
665
|
+
decideBetween: [
|
|
666
|
+
{
|
|
667
|
+
between: ["audit-coverage", "find-unused"],
|
|
668
|
+
hint: "audit-coverage finds where to ADD bindings (raw values). find-unused finds variables/styles to DELETE.",
|
|
669
|
+
},
|
|
670
|
+
],
|
|
671
|
+
context: "audit_variable_coverage returns SUMMARY only (counts + topOffenders). When `suggest=true` (default) the plugin matches every raw value against existing local variables; the suggestion in topOffenders / details lets the agent propose batch_bind_variables payloads. Style coverage (audit_style_coverage) reports nodes where neither a styleId nor a variable is bound.",
|
|
672
|
+
preferredTools: [
|
|
673
|
+
"audit_variable_coverage",
|
|
674
|
+
"find_variable_coverage_misses",
|
|
675
|
+
"audit_style_coverage",
|
|
676
|
+
"find_style_coverage_misses",
|
|
677
|
+
"batch_bind_variables",
|
|
678
|
+
],
|
|
679
|
+
forbidden: [
|
|
680
|
+
"Walking the document manually with use_figma — audit_* tools cover the case (chunked, alias-aware).",
|
|
681
|
+
"Applying suggested bindings without user confirmation — coverage suggestions can be wrong on intentional raw values.",
|
|
682
|
+
"Running on scope='file' first when 'page' is enough — start narrow, widen on demand.",
|
|
683
|
+
],
|
|
684
|
+
steps: [
|
|
685
|
+
"Start narrow: audit_variable_coverage { scope: 'page' } — confirm magnitude.",
|
|
686
|
+
"If acceptable, widen: scope: 'file'.",
|
|
687
|
+
"For details / fix-up: find_variable_coverage_misses { limit, cursor } — assemble a batch_bind_variables payload from suggestion entries.",
|
|
688
|
+
"For style coverage do the same with audit_style_coverage / find_style_coverage_misses.",
|
|
689
|
+
],
|
|
690
|
+
doneCriteria: "Agent returned a summary (and optionally a batch_bind_variables proposal) without using use_figma. Coverage gaps are quantified per property and per page.",
|
|
691
|
+
};
|
|
692
|
+
export const RECIPE_BULK_VARIABLES = {
|
|
693
|
+
id: "bulk-variables",
|
|
694
|
+
title: "Bulk create / dedupe / rebind / reorder Figma Variables",
|
|
695
|
+
version: 1,
|
|
696
|
+
userPhrases: [
|
|
697
|
+
"создай набор переменных по этому списку",
|
|
698
|
+
"import these variables in bulk",
|
|
699
|
+
"bulk create variables from spec",
|
|
700
|
+
"обнови переменные пакетно",
|
|
701
|
+
"перепривяжи алиасы переменных",
|
|
702
|
+
"rebind aliases from old token to new",
|
|
703
|
+
"найди дубликаты переменных и слей их",
|
|
704
|
+
"dedupe variables across collections",
|
|
705
|
+
"приведи коллекцию в алфавитный порядок",
|
|
706
|
+
"reorder variables alphabetically",
|
|
707
|
+
],
|
|
708
|
+
decideBetween: [
|
|
709
|
+
{
|
|
710
|
+
between: ["bulk-variables", "doc-tokens"],
|
|
711
|
+
hint: "If the user wants to render existing token values as documentation, switch to doc-tokens.",
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
between: ["bulk-variables", "auto-bind-from-audit"],
|
|
715
|
+
hint: "auto-bind-from-audit applies suggestions from audit_variable_coverage; bulk-variables operates on the variables themselves (CRUD + alias refactors).",
|
|
716
|
+
},
|
|
717
|
+
],
|
|
718
|
+
context: "Phase B 'thick' commands cover four recurring refactors: (1) declarative bulk import / update via import_variable_spec, (2) duplicate detection + merge via dedupe_variables, (3) alias rewrites across modes via rebind_variable_aliases, (4) read-only ordering analysis via analyze_variable_order. All write commands accept a dry-run mode that returns the exact plan without touching Figma — agents should ALWAYS preview first and surface the plan to the user before committing.",
|
|
719
|
+
preferredTools: [
|
|
720
|
+
"get_variables",
|
|
721
|
+
"import_variable_spec",
|
|
722
|
+
"dedupe_variables",
|
|
723
|
+
"rebind_variable_aliases",
|
|
724
|
+
"analyze_variable_order",
|
|
725
|
+
"batch_bind_variables",
|
|
726
|
+
],
|
|
727
|
+
forbidden: [
|
|
728
|
+
"Calling create_variable / set_variable_mode_value in a loop for 5+ items — use import_variable_spec.",
|
|
729
|
+
"Hand-writing a rebinding loop with rename_variable + set_variable_mode_value — use rebind_variable_aliases.",
|
|
730
|
+
"Treating analyze_variable_order as a write command — Figma Plugin API does not expose stable variable reordering, so this is diff-only.",
|
|
731
|
+
"Skipping dryRun on dedupe / rebind / import — always preview before committing.",
|
|
732
|
+
"Using use_figma scripts to traverse local variables — get_variables + Phase B tools cover the case.",
|
|
733
|
+
],
|
|
734
|
+
steps: [
|
|
735
|
+
"Read the user's intent: bulk create vs dedupe vs rebind vs reorder. Each maps to one Phase B tool.",
|
|
736
|
+
"For BULK CREATE / UPDATE: pass spec.collections[] to import_variable_spec with dryRun: true first. The response lists added / updated / skipped variables and unresolved aliases. Re-call without dryRun to commit.",
|
|
737
|
+
"For DEDUPE: dedupe_variables { strategy: 'byName' | 'byDefaultModeValue' } — default is dry-run. Confirm the proposed survivor with the user, then re-call with apply: true.",
|
|
738
|
+
"For ALIAS REBIND: rebind_variable_aliases { mappings: [{ fromVariableId, toVariableId }], dryRun: true } first. The response counts how many valuesByMode entries would change. Re-call with dryRun: false to commit.",
|
|
739
|
+
"For ORDER: analyze_variable_order { collectionId, strategy } — read-only analysis. Return the moves[] to the user; manual reorder in the Variables panel is required.",
|
|
740
|
+
],
|
|
741
|
+
doneCriteria: "Agent produced a single Phase B call (or two: dryRun preview + commit) that the plugin executed; the user has the diff before any write. No use_figma / batch loops were used.",
|
|
742
|
+
};
|
|
743
|
+
export const RECIPE_AUTO_BIND_FROM_AUDIT = {
|
|
744
|
+
id: "auto-bind-from-audit",
|
|
745
|
+
title: "Auto-apply audit_variable_coverage suggestions",
|
|
746
|
+
version: 1,
|
|
747
|
+
userPhrases: [
|
|
748
|
+
"примени предложенные переменные к аудиту",
|
|
749
|
+
"apply variable coverage suggestions",
|
|
750
|
+
"автопривяжи переменные где есть подсказки",
|
|
751
|
+
"fix the audit by binding suggested variables",
|
|
752
|
+
"convert audit suggestions into bindings",
|
|
753
|
+
],
|
|
754
|
+
decideBetween: [
|
|
755
|
+
{
|
|
756
|
+
between: ["auto-bind-from-audit", "audit-coverage"],
|
|
757
|
+
hint: "audit-coverage produces the diagnosis (no writes); auto-bind-from-audit applies the prescribed variable. Always run audit first, confirm, then auto-bind.",
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
context: "find_variable_coverage_misses returns suggestions per node + property: { nodeId, property, suggestion: { variableId, variableName } }. apply_coverage_suggestions translates that array into setBoundVariableForPaint / setBoundVariableForEffect / setBoundVariable writes. Default mode is dry-run — agent receives a preview the user can sign off on. Commit happens only when dryRun: false.",
|
|
761
|
+
preferredTools: [
|
|
762
|
+
"audit_variable_coverage",
|
|
763
|
+
"find_variable_coverage_misses",
|
|
764
|
+
"apply_coverage_suggestions",
|
|
765
|
+
"batch_bind_variables",
|
|
766
|
+
],
|
|
767
|
+
forbidden: [
|
|
768
|
+
"Applying suggestions blindly without showing them to the user — coverage suggestions can be wrong on intentional raw values.",
|
|
769
|
+
"Calling bind_variable in a loop for each suggestion — apply_coverage_suggestions handles paths like fills[0].color / effects[2].color in one round-trip.",
|
|
770
|
+
"Skipping the dry-run preview — apply_coverage_suggestions is destructive (it writes bindings on the canvas).",
|
|
771
|
+
],
|
|
772
|
+
steps: [
|
|
773
|
+
"Run find_variable_coverage_misses { scope: 'page' | 'file', limit, withSuggestion: true }. Filter entries that have a non-null suggestion.",
|
|
774
|
+
"Build the suggestions[] array: { nodeId, property, variableId } per entry.",
|
|
775
|
+
"Call apply_coverage_suggestions with dryRun: true (default). Surface the preview[] to the user.",
|
|
776
|
+
"On confirmation, re-call apply_coverage_suggestions with dryRun: false to commit. Canvas write — Dev Mode is blocked.",
|
|
777
|
+
],
|
|
778
|
+
doneCriteria: "Bindings prescribed by the audit are applied to the canvas; the response reports applied / failed counts. No use_figma scripts were used.",
|
|
779
|
+
};
|
|
780
|
+
export const RECIPE_BULK_STYLES = {
|
|
781
|
+
id: "bulk-styles",
|
|
782
|
+
title: "Bulk create / dedupe / rebind LOCAL Figma styles + apply coverage suggestions (Phase C)",
|
|
783
|
+
version: 1,
|
|
784
|
+
userPhrases: [
|
|
785
|
+
"создай набор стилей по этому списку",
|
|
786
|
+
"import these paint / text / effect styles in bulk",
|
|
787
|
+
"bulk create paint styles from spec",
|
|
788
|
+
"обнови стили пакетно",
|
|
789
|
+
"найди дубликаты стилей и слей их",
|
|
790
|
+
"dedupe styles across the file",
|
|
791
|
+
"перепривяжи стили со старого на новый",
|
|
792
|
+
"rebind style consumers from one style to another",
|
|
793
|
+
"примени предложенные стили к аудиту",
|
|
794
|
+
"apply style coverage suggestions",
|
|
795
|
+
"конвертируй raw paints в стили",
|
|
796
|
+
],
|
|
797
|
+
decideBetween: [
|
|
798
|
+
{
|
|
799
|
+
between: ["bulk-styles", "bulk-variables"],
|
|
800
|
+
hint: "bulk-styles wraps Figma local STYLES (fillStyleId / textStyleId / effectStyleId). For Figma VARIABLES (boundVariables / valuesByMode) use bulk-variables instead.",
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
between: ["bulk-styles", "audit-coverage"],
|
|
804
|
+
hint: "audit-coverage only LISTS missing bindings. bulk-styles applies them (apply_style_coverage_suggestions) and refactors styles in bulk.",
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
between: ["bulk-styles", "style-drift"],
|
|
808
|
+
hint: "style-drift verifies that styles match the source of truth (read-only). bulk-styles modifies styles or their consumers.",
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
context: "Phase C 'thick' commands cover four recurring style refactors: (1) declarative bulk import / update via import_style_spec (PaintStyle + TextStyle + EffectStyle), (2) duplicate detection + merge via dedupe_styles (byName | bySignature), (3) bulk styleId rewriting on consumer nodes via rebind_style_consumers, (4) converting find_style_coverage_misses into setStyleId* writes via apply_style_coverage_suggestions. All write commands accept dry-run / preview mode that returns the plan WITHOUT touching Figma — agent should ALWAYS preview first and surface the diff to the user before committing.",
|
|
812
|
+
preferredTools: [
|
|
813
|
+
"get_local_styles",
|
|
814
|
+
"import_style_spec",
|
|
815
|
+
"dedupe_styles",
|
|
816
|
+
"rebind_style_consumers",
|
|
817
|
+
"find_style_coverage_misses",
|
|
818
|
+
"apply_style_coverage_suggestions",
|
|
819
|
+
],
|
|
820
|
+
forbidden: [
|
|
821
|
+
"Calling create_paint_style / create_text_style / create_effect_style in a loop for 5+ items — use import_style_spec.",
|
|
822
|
+
"Hand-writing a styleId rewriting loop with set_fill_style / set_stroke_style — use rebind_style_consumers.",
|
|
823
|
+
"Skipping dryRun on dedupe_styles / rebind_style_consumers / apply_style_coverage_suggestions — always preview before committing.",
|
|
824
|
+
"Using use_figma scripts to traverse local styles — get_local_styles + Phase C tools cover the case.",
|
|
825
|
+
"Applying coverage suggestions blindly — coverage suggestions can be wrong on intentional raw values.",
|
|
826
|
+
],
|
|
827
|
+
steps: [
|
|
828
|
+
"Read the user's intent: bulk create vs dedupe vs rebind consumers vs auto-bind from audit. Each maps to one Phase C tool.",
|
|
829
|
+
"For BULK CREATE / UPDATE: build spec.{paintStyles, textStyles, effectStyles}[] and call import_style_spec with dryRun: true first. SOLID paints accept `color: '#rrggbb[aa]'` shortcut. Re-call without dryRun to commit.",
|
|
830
|
+
"For DEDUPE: dedupe_styles { strategy: 'byName' | 'bySignature', styleType?: 'PAINT' | 'TEXT' | 'EFFECT' | 'ALL' } — default is dry-run. Confirm the proposed survivor (style with most consumers wins), then re-call with apply: true.",
|
|
831
|
+
"For STYLE REBIND: rebind_style_consumers { mappings: [{ fromStyleId, toStyleId }], dryRun: true } first. The response counts (node, field) pairs that would change. Re-call with dryRun: false to commit.",
|
|
832
|
+
"For AUTO-BIND FROM AUDIT: find_style_coverage_misses → assemble suggestions[{ nodeId, property, styleId }] → apply_style_coverage_suggestions { suggestions, dryRun: true }. Style assignments are PER-NODE (PaintStyle covers the whole fills[] array), so duplicates by (nodeId, field) land in skipped[]. Surface preview, then re-call with dryRun: false.",
|
|
833
|
+
],
|
|
834
|
+
doneCriteria: "Agent produced a Phase C call (or two: dryRun preview + commit) that the plugin executed; the user approved the diff before any write. No use_figma / set_*_style loops were used.",
|
|
835
|
+
};
|
|
836
|
+
export const RECIPE_STYLE_DRIFT = {
|
|
837
|
+
id: "style-drift",
|
|
838
|
+
title: "Audit drift between local Paint styles and the source of truth (Phase C)",
|
|
839
|
+
version: 1,
|
|
840
|
+
userPhrases: [
|
|
841
|
+
"проверь дрейф стилей и переменных",
|
|
842
|
+
"audit style drift vs variables",
|
|
843
|
+
"стили рассинхронизированы с токенами",
|
|
844
|
+
"find paint styles that drifted from variables",
|
|
845
|
+
"сверь PaintStyle со списком ожидаемых цветов",
|
|
846
|
+
"verify styles against expected colors",
|
|
847
|
+
],
|
|
848
|
+
decideBetween: [
|
|
849
|
+
{
|
|
850
|
+
between: ["style-drift", "audit-coverage"],
|
|
851
|
+
hint: "style-drift verifies EXISTING style values vs source of truth. audit-coverage finds nodes WITHOUT a style binding.",
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
between: ["style-drift", "bulk-styles"],
|
|
855
|
+
hint: "style-drift is READ-ONLY (Dev Mode safe). When drift is found and the user wants to fix it, switch to bulk-styles → import_style_spec to overwrite the drifted style values.",
|
|
856
|
+
},
|
|
857
|
+
],
|
|
858
|
+
context: "audit_style_drift compares local PaintStyles to the source of truth in two modes: byName-vs-variables (auto-pairs styles with like-named local Variables) or explicit ({ styleId, expectedColor } expectations from a token snapshot). Returns findings[] (drift > tolerance) and skipped[] (styles that couldn't be compared — non-SOLID, non-COLOR variable, etc.). NO canvas writes — fully Dev-Mode-compatible.",
|
|
859
|
+
preferredTools: ["audit_style_drift", "get_variables", "import_style_spec"],
|
|
860
|
+
forbidden: [
|
|
861
|
+
"Walking PaintStyles + Variables manually with use_figma — audit_style_drift covers it (alias-aware).",
|
|
862
|
+
"Setting tolerance > 0 silently — when fuzzy matching is enabled, surface the value to the user.",
|
|
863
|
+
"Treating findings[] as canonical: skipped[] entries (no matching variable, non-SOLID paint, etc.) often need a follow-up question.",
|
|
864
|
+
],
|
|
865
|
+
steps: [
|
|
866
|
+
"Decide the comparison source: token-driven workflow → byName-vs-variables; token snapshot from the transformer → explicit.",
|
|
867
|
+
"Call audit_style_drift { request: { mode: 'byName-vs-variables' } } (or explicit + expectations[]) with optional tolerance.",
|
|
868
|
+
"Surface findings[] grouped by source. For each, show actualColor → expectedColor + delta. Surface skipped[] separately.",
|
|
869
|
+
"If user wants to fix drift: build an import_style_spec.paintStyles[] payload that overrides the drifted values, dryRun first, then commit.",
|
|
870
|
+
],
|
|
871
|
+
doneCriteria: "Agent produced a deterministic drift report. No canvas writes happened during the audit. If the user requested a fix, a follow-up import_style_spec was issued with explicit dryRun preview.",
|
|
872
|
+
};
|
|
873
|
+
export const RECIPE_FIND_UNUSED = {
|
|
874
|
+
id: "find-unused",
|
|
875
|
+
title: "Find unused local variables and styles",
|
|
876
|
+
version: 1,
|
|
877
|
+
userPhrases: [
|
|
878
|
+
"какие переменные у меня не используются",
|
|
879
|
+
"find unused variables",
|
|
880
|
+
"which styles are dead",
|
|
881
|
+
"почисть неиспользуемые токены",
|
|
882
|
+
"найди мёртвые стили",
|
|
883
|
+
],
|
|
884
|
+
context: "find_unused_variables walks the file once, building two reference sets: bindings on every node + alias targets in any variable mode. unused = local variables \\ referenced. find_unused_styles does the equivalent for paint/text/effect styles. Both are read-only.",
|
|
885
|
+
preferredTools: [
|
|
886
|
+
"find_unused_variables",
|
|
887
|
+
"find_unused_styles",
|
|
888
|
+
"batch_delete_variables",
|
|
889
|
+
],
|
|
890
|
+
forbidden: [
|
|
891
|
+
"Deleting variables / styles without explicit user confirmation — false positives are possible (e.g. variables used only in published libraries).",
|
|
892
|
+
"Running unused detection without explaining the scan boundary — it covers the current document only.",
|
|
893
|
+
],
|
|
894
|
+
steps: [
|
|
895
|
+
"Run find_unused_variables / find_unused_styles — return the lists.",
|
|
896
|
+
"Confirm with the user which entries to remove (group by collection / styleType for clarity).",
|
|
897
|
+
"If approved: batch_delete_variables for variables; styles need manual removal (no batch tool yet).",
|
|
898
|
+
],
|
|
899
|
+
doneCriteria: "Agent returned a deterministic list of unused variables / styles. Deletions only happened after explicit confirmation.",
|
|
900
|
+
};
|
|
901
|
+
export const RECIPE_MOCKUP_BUILDER = {
|
|
902
|
+
id: "mockup-builder",
|
|
903
|
+
title: "Assemble a mockup screen from existing design-system components (Phase D)",
|
|
904
|
+
version: 1,
|
|
905
|
+
userPhrases: [
|
|
906
|
+
"собери макет страницы из компонентов",
|
|
907
|
+
"build a mockup from existing components",
|
|
908
|
+
"сделай дашборд из карточек",
|
|
909
|
+
"render a screen using design system components",
|
|
910
|
+
"lay out cards in auto-layout",
|
|
911
|
+
"сложи макет из WCard и WButton",
|
|
912
|
+
"render a list of N cards from this dataset",
|
|
913
|
+
"построй продуктовую страницу по описанию",
|
|
914
|
+
"assemble a settings screen from existing components",
|
|
915
|
+
],
|
|
916
|
+
decideBetween: [
|
|
917
|
+
{
|
|
918
|
+
between: ["mockup-builder", "doc-component"],
|
|
919
|
+
hint: "mockup-builder ASSEMBLES a screen from many components; doc-component DOCUMENTS a single component (variants + props).",
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
between: ["mockup-builder", "compose-with-variables"],
|
|
923
|
+
hint: "mockup-builder is the consumer (lays out instances); compose-with-variables is the producer (creates / refactors the component itself).",
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
between: ["mockup-builder", "doc-flow"],
|
|
927
|
+
hint: "mockup-builder = single auto-layout screen; doc-flow = multiple pages stacked side-by-side as a story.",
|
|
928
|
+
},
|
|
929
|
+
],
|
|
930
|
+
context: "Phase D: thick orchestration over `figma.createInstance / setProperties / setBoundVariableForPaint / loadFontAsync`. Pipeline: (1) `find_components` to discover ids / keys + componentPropertyDefinitions; (2) `build_mockup` to assemble an auto-layout container from a declarative item tree (`instance | section | spacer | text`) with property / text / fill-binding overrides; (3) `apply_mockup_dataset` when the same template needs to be cloned per-row from a structured list.",
|
|
931
|
+
preferredTools: [
|
|
932
|
+
"find_components",
|
|
933
|
+
"build_mockup",
|
|
934
|
+
"apply_mockup_dataset",
|
|
935
|
+
"get_variables",
|
|
936
|
+
],
|
|
937
|
+
forbidden: [
|
|
938
|
+
"Calling use_figma to write a hand-rolled `figma.createInstance(...) / setProperties(...)` loop when build_mockup covers the assembly.",
|
|
939
|
+
"Guessing component names instead of running find_components first — the user's file may have arbitrary local names.",
|
|
940
|
+
"Skipping dryRun for build_mockup / apply_mockup_dataset — always preview the resolved plan before writing to canvas.",
|
|
941
|
+
"Hand-coding fill colours when a Figma Variable is available — use fillBindings { variableId } so the mockup picks up theme switches automatically.",
|
|
942
|
+
"Loading fonts manually — build_mockup loads fonts on demand with a safe Inter Regular fallback.",
|
|
943
|
+
"Assuming property names like `size#123:0` — pass the human key (`size`); the plugin maps to the internal `name#defId` suffix via `componentProperties`.",
|
|
944
|
+
],
|
|
945
|
+
steps: [
|
|
946
|
+
"Run find_components { query | prefix?, includeProperties: true, kind?: 'COMPONENT' | 'COMPONENT_SET', limit?: 50 } to enumerate available components. Cache the (id, name, propertyDefinitions, defaultVariantId) list.",
|
|
947
|
+
"If the user wants library components, set includeRemoteInstances: true so library components instantiated in this file are included; otherwise stay local-only.",
|
|
948
|
+
"Decide the layout: VERTICAL stack of sections, HORIZONTAL row of cards, or WRAP grid. Pick itemSpacing / padding to match the user's intent (e.g. 16px gutters).",
|
|
949
|
+
"Build the items[] tree. Use `instance` for components (one of componentId | componentKey | componentName), `section` for nested auto-layout frames, `spacer` for explicit gaps, `text` for bare TEXT layers (TEXT styles can be applied via textStyleId).",
|
|
950
|
+
"For property / text / fill overrides on instances: pass `properties` (human keys), `textOverrides[]` (layerName + value), `fillBindings[]` (variableId; optional layerName when only one child should receive the fill).",
|
|
951
|
+
"Call build_mockup { ..., dryRun: true } first. The plugin returns a resolved plan with per-item ok/error. If any errors → fix the spec, do not commit.",
|
|
952
|
+
"Re-call build_mockup without dryRun to write to canvas. Capture rootNodeId for downstream tools (e.g. document the mockup, run audit_variable_coverage on it).",
|
|
953
|
+
"If the user wants N cards from a dataset, leave one template instance inside the mockup (kind: 'instance'), then call apply_mockup_dataset { templateNodeId, rows[], dryRun: true } → preview → commit. removeTemplate: true deletes the placeholder after cloning.",
|
|
954
|
+
],
|
|
955
|
+
doneCriteria: "Agent produced one (or a sequence of) Phase D calls (find_components → build_mockup [dryRun → commit] → optional apply_mockup_dataset) that the plugin executed without use_figma. The user approved each diff before commit. The mockup uses real components by id/key (not duplicated geometry) and binds Figma Variables instead of raw hex when a variable is available.",
|
|
956
|
+
};
|
|
957
|
+
export const RECIPE_BULK_COMPOSITIONS = {
|
|
958
|
+
id: "bulk-compositions",
|
|
959
|
+
title: "Bulk generate / apply many composition files in one call (Phase E)",
|
|
960
|
+
version: 1,
|
|
961
|
+
userPhrases: [
|
|
962
|
+
"сгенерируй все компоненты дизайн-системы",
|
|
963
|
+
"regenerate every WAccordion / WButton / WInput from JSON",
|
|
964
|
+
"пересобери компоненты по композициям",
|
|
965
|
+
"apply all SXL compositions in this workspace",
|
|
966
|
+
"обнови компоненты после правок в JSON",
|
|
967
|
+
"rebuild every composition that drifted",
|
|
968
|
+
"перегенерируй все компоненты после очистки файла",
|
|
969
|
+
"fresh-bake the design system from compositions",
|
|
970
|
+
],
|
|
971
|
+
decideBetween: [
|
|
972
|
+
{
|
|
973
|
+
between: ["bulk-compositions", "compose-with-variables"],
|
|
974
|
+
use_bulk_compositions_when: "the composition JSON files already exist in the plugin workspace (`tokens/components/W*.json`) and you want to (re)build many components in one call",
|
|
975
|
+
use_compose_with_variables_when: "the composition JSON does NOT exist yet — you start from a Figma URL, export composition JSON, and generate one component",
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
between: ["bulk-compositions", "composition-drift"],
|
|
979
|
+
use_bulk_compositions_when: "the user wants to WRITE (generate / apply) compositions",
|
|
980
|
+
use_composition_drift_when: "the user only wants to KNOW which compositions are out of sync (read-only)",
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
between: ["bulk-compositions", "doc-component"],
|
|
984
|
+
use_bulk_compositions_when: "the goal is to (re)build the actual COMPONENT in Figma from composition JSON",
|
|
985
|
+
use_doc_component_when: "the goal is to render a documentation FRAME for an existing component",
|
|
986
|
+
},
|
|
987
|
+
],
|
|
988
|
+
context: "Phase E thick orchestration around `handleGenerateComposition` / `handleApplyComposition`. Discovers every `$type:composition` file in the plugin workspace (same source as `list_compositions`), filters by `fileIds | names | prefix`, then runs the per-file pipeline with per-item error isolation (`continueOnError: true` by default). `operation: 'auto'` mirrors the manual UX (apply if a tracked component already exists, otherwise generate); `'generate'` forces a fresh ComponentSet rebuild; `'apply'` forces apply onto an existing component. `dryRun: true` returns the resolved plan WITHOUT touching the canvas — Dev Mode safe.",
|
|
989
|
+
preferredTools: [
|
|
990
|
+
"list_compositions",
|
|
991
|
+
"audit_composition_drift",
|
|
992
|
+
"bulk_generate_compositions",
|
|
993
|
+
],
|
|
994
|
+
forbidden: [
|
|
995
|
+
"Calling generate_composition / apply_composition in a hand-written loop for 3+ files — use bulk_generate_compositions to keep per-item error isolation, progress events, and idempotency.",
|
|
996
|
+
"Using bulk_generate_compositions with `operation: 'apply'` against compositions that have no diff-id tracking entry — the handler will fall back to `generate` per item; if the user explicitly asked for apply-only, run audit_composition_drift first to confirm tracking exists.",
|
|
997
|
+
"Skipping dryRun when the user expects a preview — agent must surface the resolved plan (file count, expected variant counts, errors) before committing canvas writes.",
|
|
998
|
+
"Operating on every composition without filters when the user only mentioned a single component family — pass `prefix: 'WAccordion'` / `names: [...]` to keep the run small and idempotent.",
|
|
999
|
+
"Interpreting `success: true, variantsCreated: 0` as a failure — that's normal idempotent behaviour for `apply` when nothing changed.",
|
|
1000
|
+
],
|
|
1001
|
+
steps: [
|
|
1002
|
+
"Discover what's in the workspace: read `sxl://compositions/index` (or call list_compositions) to get the full set of composition files + names.",
|
|
1003
|
+
"(Optional) Run audit_composition_drift first when the user is unsure which components actually drifted. Use the report to build the `fileIds` filter for the next step.",
|
|
1004
|
+
"Pick filter scope: `fileIds: [...]` for surgical re-builds, `prefix: 'W'` for a whole DS family, `names: ['WButton', 'WInput']` for a curated list. Omit all filters only when the user explicitly asked to rebuild everything.",
|
|
1005
|
+
"Pick operation: `auto` (default — manual UX), `generate` (force rebuild — use after structural changes / corrupted tracking), `apply` (force apply onto existing — use only when tracking is healthy).",
|
|
1006
|
+
"Call bulk_generate_compositions { ..., dryRun: true } first. The plugin returns the resolved plan with per-item composition name + parse status. If any errors → fix the JSON / config, do not commit.",
|
|
1007
|
+
"Re-call without dryRun to commit. Capture summary { total, processed, created, updated, failed, elapsedMs } and surface it to the user.",
|
|
1008
|
+
"On per-item failures, the run continues by default. Group `items[].errors` by composition for the user; if `continueOnError: false` was set, only `items` up to the first failure are present.",
|
|
1009
|
+
],
|
|
1010
|
+
doneCriteria: "Agent produced one or two bulk_generate_compositions calls (dryRun → commit) that touched only the requested compositions. Per-item errors were surfaced; failures did not silently rebuild the wrong components. No hand-written generate/apply loops were issued.",
|
|
1011
|
+
};
|
|
1012
|
+
export const RECIPE_COMPOSITION_DRIFT = {
|
|
1013
|
+
id: "composition-drift",
|
|
1014
|
+
title: "Audit drift between composition JSON files and Figma components (Phase E)",
|
|
1015
|
+
version: 1,
|
|
1016
|
+
userPhrases: [
|
|
1017
|
+
"проверь рассинхрон композиций и компонентов",
|
|
1018
|
+
"audit composition drift",
|
|
1019
|
+
"какие компоненты не соответствуют JSON",
|
|
1020
|
+
"find compositions that drifted from Figma",
|
|
1021
|
+
"сверь tokens/components с реальными ComponentSet",
|
|
1022
|
+
"verify SXL compositions still match the Figma design system",
|
|
1023
|
+
"какие компоненты потерялись",
|
|
1024
|
+
"show compositions whose tracked component was deleted",
|
|
1025
|
+
],
|
|
1026
|
+
decideBetween: [
|
|
1027
|
+
{
|
|
1028
|
+
between: ["composition-drift", "bulk-compositions"],
|
|
1029
|
+
use_composition_drift_when: "user wants the LIST of out-of-sync compositions (read-only — Dev Mode safe)",
|
|
1030
|
+
use_bulk_compositions_when: "user wants to FIX the drift (write — bulk_generate_compositions { fileIds: drifted, operation: 'generate' })",
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
between: ["composition-drift", "style-drift"],
|
|
1034
|
+
use_composition_drift_when: "the unit of comparison is a composition JSON ↔ Figma ComponentSet",
|
|
1035
|
+
use_style_drift_when: "the unit of comparison is a local PaintStyle ↔ Variable / token snapshot",
|
|
1036
|
+
},
|
|
1037
|
+
{
|
|
1038
|
+
between: ["composition-drift", "find-unused"],
|
|
1039
|
+
use_composition_drift_when: "the goal is to verify EXISTING compositions still match the Figma scene",
|
|
1040
|
+
use_find_unused_when: "the goal is to clean up dangling local variables / styles (different unit)",
|
|
1041
|
+
},
|
|
1042
|
+
],
|
|
1043
|
+
context: "audit_composition_drift compares every `$type:composition` file in the plugin workspace against the Figma component it tracked in `diff-id.compositions`. Per-composition status: `linked` (tracking entry valid + Figma node matches), `unlinked` (no tracking — never generated), `drift` (Figma node renamed / variant count mismatch / wrong type), `missing` (tracking points to a deleted node). Findings include human-readable `reason`. Fully Dev-Mode-compatible — never touches the canvas.",
|
|
1044
|
+
preferredTools: ["audit_composition_drift", "list_compositions", "bulk_generate_compositions"],
|
|
1045
|
+
forbidden: [
|
|
1046
|
+
"Walking diff-id.json + Figma scene tree manually with use_figma — audit_composition_drift covers it.",
|
|
1047
|
+
"Treating `unlinked` as drift — it just means the composition was never generated. Surface it as a separate bucket.",
|
|
1048
|
+
"Auto-fixing without confirmation — drift can mean the designer intentionally renamed the Figma component; ask before running bulk_generate_compositions.",
|
|
1049
|
+
],
|
|
1050
|
+
steps: [
|
|
1051
|
+
"Run audit_composition_drift with appropriate filters: `prefix: 'W'` for the whole DS, `names: [...]` for a curated list, no filters for the full workspace.",
|
|
1052
|
+
"Group findings by status (linked / unlinked / drift / missing) and surface counts to the user.",
|
|
1053
|
+
"For each `drift` / `missing` finding, surface: composition name, fileId, status, reason, expected vs actual variant count, tracked componentSetId.",
|
|
1054
|
+
"If user wants to fix drift: call bulk_generate_compositions { fileIds: [drift+missing fileIds], operation: 'generate', dryRun: true } first → preview → commit.",
|
|
1055
|
+
"For `unlinked` findings: ask whether to generate them as new components (bulk_generate_compositions { operation: 'auto' }) or leave them.",
|
|
1056
|
+
],
|
|
1057
|
+
doneCriteria: "Agent returned a deterministic drift report with per-composition status. No canvas writes happened during the audit. If the user approved a fix, a follow-up bulk_generate_compositions was issued with explicit dryRun preview.",
|
|
1058
|
+
};
|
|
422
1059
|
//# sourceMappingURL=agent-recipes.js.map
|