@noemuch/bridge-ds 2.0.0 → 2.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noemuch/bridge-ds",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "AI-powered design generation in Figma — 100% design system compliant. Connects Claude Code to Figma via MCP for spec-first, token-bound, component-native design.",
5
5
  "main": "lib/cli.js",
6
6
  "bin": {
@@ -109,14 +109,26 @@ Never generate a full design in a single script. Split into small, sequential st
109
109
 
110
110
  **CRITICAL — Pre-script element audit (BLOCKING, Rule 18):**
111
111
 
112
- Before writing EACH script, list every visual element it will create and verify against registries:
112
+ Before writing EACH script, list every visual element it will create and cross-reference against the spec's "DS Components Used" table AND the registries:
113
+
113
114
  ```
114
- Elements in this step:
115
- - Avatar components.json key: xxx ✓
116
- - Divider → components.json key: xxx ✓
117
- - Label text raw text (layout frame label, no DS component)
115
+ PRE-SCRIPT AUDIT Step {n}:
116
+ Spec requires: Registry match: Script will use:
117
+ ─────────────────────────────────────────────────────────────────────
118
+ AssetLogo (logo) logos.json key: abc123 → importComponentByKeyAsync
119
+ Tag v2 (label) → components.json key: def456 → importComponentSetByKeyAsync ✓
120
+ CardBase (container) → components.json key: ghi789 → importComponentByKeyAsync ✓
121
+ Section title → NO DS component → raw text (justified) ✓
122
+ Layout wrapper → NO DS component → raw frame (structural) ✓
118
123
  ```
119
- If an element exists in `components.json`, it MUST be imported via `importComponentByKeyAsync`. NEVER recreate as raw frame/text/shape. NEVER hardcode hex colors — always bind variables.
124
+
125
+ **BLOCKING RULES:**
126
+ - If a spec-listed DS component is planned as a raw element → **STOP. Rewrite the script.**
127
+ - If an element exists in ANY registry (components, icons, logos, illustrations) → **MUST import it**. No exceptions.
128
+ - If you're about to use `figma.createEllipse()`, `figma.createRectangle()`, or `figma.createFrame()` for something that looks like a DS component → **STOP and check registries first.**
129
+ - Only create raw elements for pure structural layout frames or when NO DS component exists (document WHY in the audit).
130
+
131
+ NEVER recreate as raw frame/text/shape. NEVER hardcode hex colors — always bind variables.
120
132
 
121
133
  **Standard steps for a screen:**
122
134
 
@@ -159,10 +159,10 @@ text.fontSize = 32;
159
159
 
160
160
  // CORRECT (key from registries/text-styles.json)
161
161
  var style = await figma.importStyleByKeyAsync("YOUR_TEXT_STYLE_KEY");
162
- text.textStyleId = style.id;
162
+ await text.setTextStyleIdAsync(style.id); // MUST use async version — see Rule 20
163
163
  ```
164
164
 
165
- **Load text style keys from `registries/text-styles.json`.**
165
+ **Load text style keys from `registries/text-styles.json`.** Always use `setTextStyleIdAsync()`, not `textStyleId =`.
166
166
 
167
167
  ---
168
168
 
@@ -356,28 +356,38 @@ The `return` before the IIFE is mandatory — without it, the Promise is lost.
356
356
 
357
357
  ## Rule 18: DS component reuse — NEVER recreate existing components
358
358
 
359
- **This is the most critical rule. Violations require script rewrite.**
359
+ **This is the most critical rule. Violations require FULL script rewrite.**
360
360
 
361
361
  Before creating ANY visual element, check the registries:
362
- 1. `registries/components.json` → Buttons, Tags, Inputs, Avatars, Dividers, etc.
362
+ 1. `registries/components.json` → Buttons, Tags, Inputs, Avatars, Dividers, Cards, etc.
363
363
  2. `registries/icons.json` → Icons (if exists)
364
- 3. `registries/logos.json` → Logos (if exists)
364
+ 3. `registries/logos.json` → Logos, brand assets (if exists)
365
365
  4. `registries/illustrations.json` → Illustrations (if exists)
366
366
 
367
367
  **NEVER:**
368
- - Create a raw frame/ellipse for an Avatar → import the DS component
369
- - Create a raw rectangle for a Divider → import the DS component
370
- - Create a raw frame with text for a Tag/Badge → import the DS component
368
+ - `figma.createEllipse()` for a logo → import from logos.json via `importComponentByKeyAsync`
369
+ - `figma.createFrame()` for a Tag/Badge → import from components.json via `importComponentSetByKeyAsync`
370
+ - `figma.createFrame()` for a Card → import the DS Card component
371
+ - `figma.createRectangle()` for a Divider → import the DS Divider component
371
372
  - Hardcode hex colors → always bind variables
372
373
 
373
- **Pre-script checklist (mandatory):**
374
+ **Why this matters:** Using raw elements cascades into multiple failures:
375
+ - No `INSTANCE_SWAP` props possible (can't swap a logo on an ellipse)
376
+ - No inherited component properties (size, variant, state)
377
+ - Wrong proportions (raw frames don't match DS component sizing)
378
+ - Breaks the design system contract — the whole point of Bridge
379
+
380
+ **Pre-script audit (MANDATORY — must appear before every script):**
374
381
  ```
375
- Elements in this step:
376
- - Avatar components.json key: xxx ✓
377
- - Divider → components.json key: xxx ✓
378
- - Label raw text (no DS component for this)
382
+ PRE-SCRIPT AUDIT Step {n}:
383
+ Spec requires: Registry match: Script will use:
384
+ ─────────────────────────────────────────────────────────────────────
385
+ {element} {registry}.json key: {key} → import{method}
386
+ {element} → NO DS component → raw {type} (reason) ✓
379
387
  ```
380
388
 
389
+ **If ANY spec-listed DS component is planned as a raw element → STOP and fix before writing the script.**
390
+
381
391
  ---
382
392
 
383
393
  ## Rule 19: Canvas positioning — never stack components
@@ -400,6 +410,22 @@ mainComponent.y = 400;
400
410
 
401
411
  ---
402
412
 
413
+ ## Rule 20: setTextStyleIdAsync (not textStyleId) in dynamic-page context
414
+
415
+ When running scripts via `figma_execute` (which uses `documentAccess: "dynamic-page"`), text style assignment MUST use the async API:
416
+
417
+ ```js
418
+ // WRONG — crashes in dynamic-page context
419
+ text.textStyleId = style.id;
420
+
421
+ // CORRECT
422
+ await text.setTextStyleIdAsync(style.id);
423
+ ```
424
+
425
+ Same applies to `setFillStyleIdAsync`, `setStrokeStyleIdAsync`, `setEffectStyleIdAsync`.
426
+
427
+ ---
428
+
403
429
  ## Standard Script Boilerplate
404
430
 
405
431
  ```js