canicode 0.8.9 → 0.9.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/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { GetFileResponse, Node } from '@figma/rest-api-spec';
3
3
 
4
- var version = "0.8.9";
4
+ var version = "0.9.1";
5
5
 
6
6
  declare const SeveritySchema: z.ZodEnum<{
7
7
  blocking: "blocking";
@@ -14,15 +14,15 @@ declare const SEVERITY_WEIGHT: Record<Severity, number>;
14
14
  declare const SEVERITY_LABELS: Record<Severity, string>;
15
15
 
16
16
  declare const CategorySchema: z.ZodEnum<{
17
- layout: "layout";
18
- token: "token";
19
- component: "component";
20
- naming: "naming";
21
- "ai-readability": "ai-readability";
22
- "handoff-risk": "handoff-risk";
17
+ "pixel-critical": "pixel-critical";
18
+ "responsive-critical": "responsive-critical";
19
+ "code-quality": "code-quality";
20
+ "token-management": "token-management";
21
+ semantic: "semantic";
22
+ interaction: "interaction";
23
23
  }>;
24
24
  type Category = z.infer<typeof CategorySchema>;
25
- declare const CATEGORIES: ("layout" | "token" | "component" | "naming" | "ai-readability" | "handoff-risk")[];
25
+ declare const CATEGORIES: ("pixel-critical" | "responsive-critical" | "code-quality" | "token-management" | "semantic" | "interaction")[];
26
26
  declare const CATEGORY_LABELS: Record<Category, string>;
27
27
 
28
28
  /**
@@ -55,12 +55,14 @@ declare const AnalysisNodeTypeSchema: z.ZodEnum<{
55
55
  LINK_UNFURL: "LINK_UNFURL";
56
56
  TABLE: "TABLE";
57
57
  TABLE_CELL: "TABLE_CELL";
58
+ SLOT: "SLOT";
58
59
  }>;
59
60
  type AnalysisNodeType = z.infer<typeof AnalysisNodeTypeSchema>;
60
61
  declare const LayoutModeSchema: z.ZodEnum<{
61
62
  NONE: "NONE";
62
63
  HORIZONTAL: "HORIZONTAL";
63
64
  VERTICAL: "VERTICAL";
65
+ GRID: "GRID";
64
66
  }>;
65
67
  type LayoutMode = z.infer<typeof LayoutModeSchema>;
66
68
  declare const LayoutAlignSchema: z.ZodEnum<{
@@ -76,6 +78,42 @@ declare const LayoutPositioningSchema: z.ZodEnum<{
76
78
  ABSOLUTE: "ABSOLUTE";
77
79
  }>;
78
80
  type LayoutPositioning = z.infer<typeof LayoutPositioningSchema>;
81
+ declare const LayoutConstraintSchema: z.ZodObject<{
82
+ horizontal: z.ZodEnum<{
83
+ CENTER: "CENTER";
84
+ LEFT: "LEFT";
85
+ RIGHT: "RIGHT";
86
+ LEFT_RIGHT: "LEFT_RIGHT";
87
+ SCALE: "SCALE";
88
+ }>;
89
+ vertical: z.ZodEnum<{
90
+ CENTER: "CENTER";
91
+ SCALE: "SCALE";
92
+ TOP: "TOP";
93
+ BOTTOM: "BOTTOM";
94
+ TOP_BOTTOM: "TOP_BOTTOM";
95
+ }>;
96
+ }, z.core.$strip>;
97
+ type LayoutConstraint = z.infer<typeof LayoutConstraintSchema>;
98
+ declare const LayoutWrapSchema: z.ZodEnum<{
99
+ NO_WRAP: "NO_WRAP";
100
+ WRAP: "WRAP";
101
+ }>;
102
+ type LayoutWrap = z.infer<typeof LayoutWrapSchema>;
103
+ declare const OverflowDirectionSchema: z.ZodEnum<{
104
+ NONE: "NONE";
105
+ HORIZONTAL_SCROLLING: "HORIZONTAL_SCROLLING";
106
+ VERTICAL_SCROLLING: "VERTICAL_SCROLLING";
107
+ HORIZONTAL_AND_VERTICAL_SCROLLING: "HORIZONTAL_AND_VERTICAL_SCROLLING";
108
+ }>;
109
+ type OverflowDirection = z.infer<typeof OverflowDirectionSchema>;
110
+ declare const GridChildAlignSchema: z.ZodEnum<{
111
+ MIN: "MIN";
112
+ CENTER: "CENTER";
113
+ MAX: "MAX";
114
+ AUTO: "AUTO";
115
+ }>;
116
+ type GridChildAlign = z.infer<typeof GridChildAlignSchema>;
79
117
  /**
80
118
  * Lightweight FigmaNode type for analysis
81
119
  * Contains only properties needed by rules
@@ -109,12 +147,14 @@ declare const BaseAnalysisNodeSchema: z.ZodObject<{
109
147
  LINK_UNFURL: "LINK_UNFURL";
110
148
  TABLE: "TABLE";
111
149
  TABLE_CELL: "TABLE_CELL";
150
+ SLOT: "SLOT";
112
151
  }>;
113
152
  visible: z.ZodDefault<z.ZodBoolean>;
114
153
  layoutMode: z.ZodOptional<z.ZodEnum<{
115
154
  NONE: "NONE";
116
155
  HORIZONTAL: "HORIZONTAL";
117
156
  VERTICAL: "VERTICAL";
157
+ GRID: "GRID";
118
158
  }>>;
119
159
  layoutAlign: z.ZodOptional<z.ZodEnum<{
120
160
  MIN: "MIN";
@@ -144,6 +184,65 @@ declare const BaseAnalysisNodeSchema: z.ZodObject<{
144
184
  paddingRight: z.ZodOptional<z.ZodNumber>;
145
185
  paddingTop: z.ZodOptional<z.ZodNumber>;
146
186
  paddingBottom: z.ZodOptional<z.ZodNumber>;
187
+ minWidth: z.ZodOptional<z.ZodNumber>;
188
+ maxWidth: z.ZodOptional<z.ZodNumber>;
189
+ minHeight: z.ZodOptional<z.ZodNumber>;
190
+ maxHeight: z.ZodOptional<z.ZodNumber>;
191
+ layoutGrow: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<1>]>>;
192
+ constraints: z.ZodOptional<z.ZodObject<{
193
+ horizontal: z.ZodEnum<{
194
+ CENTER: "CENTER";
195
+ LEFT: "LEFT";
196
+ RIGHT: "RIGHT";
197
+ LEFT_RIGHT: "LEFT_RIGHT";
198
+ SCALE: "SCALE";
199
+ }>;
200
+ vertical: z.ZodEnum<{
201
+ CENTER: "CENTER";
202
+ SCALE: "SCALE";
203
+ TOP: "TOP";
204
+ BOTTOM: "BOTTOM";
205
+ TOP_BOTTOM: "TOP_BOTTOM";
206
+ }>;
207
+ }, z.core.$strip>>;
208
+ layoutWrap: z.ZodOptional<z.ZodEnum<{
209
+ NO_WRAP: "NO_WRAP";
210
+ WRAP: "WRAP";
211
+ }>>;
212
+ counterAxisSpacing: z.ZodOptional<z.ZodNumber>;
213
+ counterAxisAlignContent: z.ZodOptional<z.ZodEnum<{
214
+ AUTO: "AUTO";
215
+ SPACE_BETWEEN: "SPACE_BETWEEN";
216
+ }>>;
217
+ gridRowCount: z.ZodOptional<z.ZodNumber>;
218
+ gridColumnCount: z.ZodOptional<z.ZodNumber>;
219
+ gridRowGap: z.ZodOptional<z.ZodNumber>;
220
+ gridColumnGap: z.ZodOptional<z.ZodNumber>;
221
+ gridColumnsSizing: z.ZodOptional<z.ZodString>;
222
+ gridRowsSizing: z.ZodOptional<z.ZodString>;
223
+ gridChildHorizontalAlign: z.ZodOptional<z.ZodEnum<{
224
+ MIN: "MIN";
225
+ CENTER: "CENTER";
226
+ MAX: "MAX";
227
+ AUTO: "AUTO";
228
+ }>>;
229
+ gridChildVerticalAlign: z.ZodOptional<z.ZodEnum<{
230
+ MIN: "MIN";
231
+ CENTER: "CENTER";
232
+ MAX: "MAX";
233
+ AUTO: "AUTO";
234
+ }>>;
235
+ gridRowSpan: z.ZodOptional<z.ZodNumber>;
236
+ gridColumnSpan: z.ZodOptional<z.ZodNumber>;
237
+ gridRowAnchorIndex: z.ZodOptional<z.ZodNumber>;
238
+ gridColumnAnchorIndex: z.ZodOptional<z.ZodNumber>;
239
+ clipsContent: z.ZodOptional<z.ZodBoolean>;
240
+ overflowDirection: z.ZodOptional<z.ZodEnum<{
241
+ NONE: "NONE";
242
+ HORIZONTAL_SCROLLING: "HORIZONTAL_SCROLLING";
243
+ VERTICAL_SCROLLING: "VERTICAL_SCROLLING";
244
+ HORIZONTAL_AND_VERTICAL_SCROLLING: "HORIZONTAL_AND_VERTICAL_SCROLLING";
245
+ }>>;
147
246
  absoluteBoundingBox: z.ZodOptional<z.ZodNullable<z.ZodObject<{
148
247
  x: z.ZodNumber;
149
248
  y: z.ZodNumber;
@@ -156,11 +255,19 @@ declare const BaseAnalysisNodeSchema: z.ZodObject<{
156
255
  styles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
157
256
  fills: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
158
257
  strokes: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
258
+ strokeWeight: z.ZodOptional<z.ZodNumber>;
259
+ individualStrokeWeights: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
159
260
  effects: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
160
261
  cornerRadius: z.ZodOptional<z.ZodNumber>;
262
+ opacity: z.ZodOptional<z.ZodNumber>;
161
263
  boundVariables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
162
264
  characters: z.ZodOptional<z.ZodString>;
163
265
  style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
266
+ textTruncation: z.ZodOptional<z.ZodEnum<{
267
+ DISABLED: "DISABLED";
268
+ ENDING: "ENDING";
269
+ }>>;
270
+ maxLines: z.ZodOptional<z.ZodNumber>;
164
271
  devStatus: z.ZodOptional<z.ZodObject<{
165
272
  type: z.ZodEnum<{
166
273
  NONE: "NONE";
@@ -169,6 +276,7 @@ declare const BaseAnalysisNodeSchema: z.ZodObject<{
169
276
  }>;
170
277
  description: z.ZodOptional<z.ZodString>;
171
278
  }, z.core.$strip>>;
279
+ interactions: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
172
280
  isAsset: z.ZodOptional<z.ZodBoolean>;
173
281
  }, z.core.$strip>;
174
282
  type AnalysisNode = z.infer<typeof BaseAnalysisNodeSchema> & {
@@ -183,12 +291,15 @@ declare const AnalysisFileSchema: z.ZodObject<{
183
291
  name: z.ZodString;
184
292
  lastModified: z.ZodString;
185
293
  version: z.ZodString;
294
+ sourceUrl: z.ZodOptional<z.ZodString>;
186
295
  document: z.ZodType<AnalysisNode, unknown, z.core.$ZodTypeInternals<AnalysisNode, unknown>>;
187
296
  components: z.ZodRecord<z.ZodString, z.ZodObject<{
188
297
  key: z.ZodString;
189
298
  name: z.ZodString;
190
299
  description: z.ZodString;
191
300
  }, z.core.$strip>>;
301
+ componentDefinitions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<AnalysisNode, unknown, z.core.$ZodTypeInternals<AnalysisNode, unknown>>>>;
302
+ interactionDestinations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<AnalysisNode, unknown, z.core.$ZodTypeInternals<AnalysisNode, unknown>>>>;
192
303
  styles: z.ZodRecord<z.ZodString, z.ZodObject<{
193
304
  key: z.ZodString;
194
305
  name: z.ZodString;
@@ -204,12 +315,12 @@ declare const RuleDefinitionSchema: z.ZodObject<{
204
315
  id: z.ZodString;
205
316
  name: z.ZodString;
206
317
  category: z.ZodEnum<{
207
- layout: "layout";
208
- token: "token";
209
- component: "component";
210
- naming: "naming";
211
- "ai-readability": "ai-readability";
212
- "handoff-risk": "handoff-risk";
318
+ "pixel-critical": "pixel-critical";
319
+ "responsive-critical": "responsive-critical";
320
+ "code-quality": "code-quality";
321
+ "token-management": "token-management";
322
+ semantic: "semantic";
323
+ interaction: "interaction";
213
324
  }>;
214
325
  why: z.ZodString;
215
326
  impact: z.ZodString;
@@ -239,18 +350,32 @@ interface RuleContext {
239
350
  file: AnalysisFile;
240
351
  parent?: AnalysisNode | undefined;
241
352
  depth: number;
353
+ /** Depth relative to the nearest COMPONENT/INSTANCE ancestor. Resets at component boundaries. */
354
+ componentDepth: number;
242
355
  maxDepth: number;
243
356
  path: string[];
357
+ /** Ancestor node types from root to parent (excludes current node). */
358
+ ancestorTypes: string[];
244
359
  siblings?: AnalysisNode[] | undefined;
360
+ /** Per-analysis shared state. Created fresh for each analysis run, eliminating module-level mutable state. */
361
+ analysisState: Map<string, unknown>;
245
362
  }
363
+ /**
364
+ * Get or initialize per-analysis state for a rule.
365
+ * Each key gets its own lazily-initialized state that persists for the duration of one analysis run.
366
+ */
367
+ declare function getAnalysisState<T>(context: RuleContext, key: string, init: () => T): T;
246
368
  /**
247
369
  * Rule violation result from check function
248
370
  */
249
371
  interface RuleViolation {
250
372
  ruleId: string;
373
+ subType?: string;
251
374
  nodeId: string;
252
375
  nodePath: string;
253
376
  message: string;
377
+ suggestion: string;
378
+ guide?: string;
254
379
  }
255
380
  /**
256
381
  * Rule check function signature
@@ -266,7 +391,7 @@ interface Rule {
266
391
  /**
267
392
  * Rule ID type for type safety
268
393
  */
269
- type RuleId = "no-auto-layout" | "absolute-position-in-auto-layout" | "fixed-width-in-responsive-context" | "missing-responsive-behavior" | "group-usage" | "fixed-size-in-auto-layout" | "missing-min-width" | "missing-max-width" | "deep-nesting" | "overflow-hidden-abuse" | "inconsistent-sibling-layout-direction" | "raw-color" | "raw-font" | "inconsistent-spacing" | "magic-number-spacing" | "raw-shadow" | "raw-opacity" | "multiple-fill-colors" | "missing-component" | "detached-instance" | "nested-instance-override" | "variant-not-used" | "component-property-unused" | "single-use-component" | "missing-component-description" | "default-name" | "non-semantic-name" | "inconsistent-naming-convention" | "numeric-suffix-name" | "too-long-name" | "ambiguous-structure" | "z-index-dependent-layout" | "missing-layout-hint" | "invisible-layer" | "empty-frame" | "hardcode-risk" | "text-truncation-unhandled" | "image-no-placeholder" | "prototype-link-in-design" | "no-dev-status";
394
+ type RuleId = "no-auto-layout" | "absolute-position-in-auto-layout" | "non-layout-container" | "fixed-size-in-auto-layout" | "missing-size-constraint" | "missing-component" | "detached-instance" | "variant-structure-mismatch" | "deep-nesting" | "raw-value" | "irregular-spacing" | "missing-interaction-state" | "missing-prototype" | "non-standard-naming" | "non-semantic-name" | "inconsistent-naming-convention";
270
395
  /**
271
396
  * Categories that support depthWeight
272
397
  */
@@ -293,12 +418,12 @@ type Issue = z.infer<typeof IssueSchema>;
293
418
 
294
419
  declare const CategoryScoreSchema: z.ZodObject<{
295
420
  category: z.ZodEnum<{
296
- layout: "layout";
297
- token: "token";
298
- component: "component";
299
- naming: "naming";
300
- "ai-readability": "ai-readability";
301
- "handoff-risk": "handoff-risk";
421
+ "pixel-critical": "pixel-critical";
422
+ "responsive-critical": "responsive-critical";
423
+ "code-quality": "code-quality";
424
+ "token-management": "token-management";
425
+ semantic: "semantic";
426
+ interaction: "interaction";
302
427
  }>;
303
428
  score: z.ZodNumber;
304
429
  maxScore: z.ZodNumber;
@@ -327,12 +452,12 @@ declare const ReportSchema: z.ZodObject<{
327
452
  totalScore: z.ZodNumber;
328
453
  categoryScores: z.ZodArray<z.ZodObject<{
329
454
  category: z.ZodEnum<{
330
- layout: "layout";
331
- token: "token";
332
- component: "component";
333
- naming: "naming";
334
- "ai-readability": "ai-readability";
335
- "handoff-risk": "handoff-risk";
455
+ "pixel-critical": "pixel-critical";
456
+ "responsive-critical": "responsive-critical";
457
+ "code-quality": "code-quality";
458
+ "token-management": "token-management";
459
+ semantic: "semantic";
460
+ interaction: "interaction";
336
461
  }>;
337
462
  score: z.ZodNumber;
338
463
  maxScore: z.ZodNumber;
@@ -365,6 +490,19 @@ declare const ReportSchema: z.ZodObject<{
365
490
  }, z.core.$strip>;
366
491
  type Report = z.infer<typeof ReportSchema>;
367
492
 
493
+ /** Zod schema for CLI visual-compare options (raw CLI input). */
494
+ declare const VisualCompareCliOptionsSchema: z.ZodObject<{
495
+ figmaUrl: z.ZodOptional<z.ZodString>;
496
+ figmaScreenshot: z.ZodOptional<z.ZodString>;
497
+ token: z.ZodOptional<z.ZodString>;
498
+ output: z.ZodOptional<z.ZodString>;
499
+ width: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>>;
500
+ height: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>>;
501
+ figmaScale: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>>;
502
+ expandRoot: z.ZodOptional<z.ZodBoolean>;
503
+ }, z.core.$strip>;
504
+ type VisualCompareCliOptions = z.infer<typeof VisualCompareCliOptionsSchema>;
505
+
368
506
  /**
369
507
  * Analysis issue with calculated score and metadata
370
508
  */
@@ -376,12 +514,22 @@ interface AnalysisIssue {
376
514
  maxDepth: number;
377
515
  calculatedScore: number;
378
516
  }
517
+ /**
518
+ * Information about a rule that threw during analysis
519
+ */
520
+ interface RuleFailure {
521
+ ruleId: string;
522
+ nodeName: string;
523
+ nodeId: string;
524
+ error: string;
525
+ }
379
526
  /**
380
527
  * Analysis result from the rule engine
381
528
  */
382
529
  interface AnalysisResult {
383
530
  file: AnalysisFile;
384
531
  issues: AnalysisIssue[];
532
+ failedRules: RuleFailure[];
385
533
  maxDepth: number;
386
534
  nodeCount: number;
387
535
  analyzedAt: string;
@@ -478,10 +626,14 @@ declare function gradeToClassName(grade: Grade): string;
478
626
  * Calculate scores from analysis result using density + diversity scoring
479
627
  *
480
628
  * Density Score = 100 - (weighted issue count / node count) * 100
481
- * Diversity Score = (1 - unique rules / total category rules) * 100
629
+ * Diversity Score = (1 - weighted triggered rule scores / total category scores) * 100
482
630
  * Final Score = density * 0.7 + diversity * 0.3
631
+ *
632
+ * @param result Analysis result with issues
633
+ * @param configs Optional preset-adjusted config map used to produce the issues.
634
+ * If not provided, diversity totals are reconstructed from issue.config values.
483
635
  */
484
- declare function calculateScores(result: AnalysisResult): ScoreReport;
636
+ declare function calculateScores(result: AnalysisResult, configs?: Record<RuleId, RuleConfig>): ScoreReport;
485
637
  /**
486
638
  * Format score report as a summary string
487
639
  */
@@ -498,7 +650,258 @@ declare function getSeverityLabel(severity: Severity): string;
498
650
  * Build a JSON-serializable analysis result summary.
499
651
  * Shared by CLI (--json) and MCP server (analyze tool response).
500
652
  */
501
- declare function buildResultJson(fileName: string, result: AnalysisResult, scores: ScoreReport): Record<string, unknown>;
653
+ declare function buildResultJson(fileName: string, result: AnalysisResult, scores: ScoreReport, options?: {
654
+ fileKey?: string;
655
+ }): Record<string, unknown>;
656
+
657
+ /**
658
+ * Extract a DOM-like design tree from AnalysisFile.
659
+ * Converts Figma node tree to a concise text format with inline CSS styles.
660
+ * AI reads this 1:1 to generate HTML+CSS — no information loss, 50-100x smaller.
661
+ */
662
+
663
+ /** Options for design tree generation. */
664
+ interface DesignTreeOptions {
665
+ /** Directory containing <nodeId>.svg files for VECTOR nodes */
666
+ vectorDir?: string;
667
+ /** Directory containing downloaded PNGs and mapping.json for IMAGE fill nodes */
668
+ imageDir?: string;
669
+ }
670
+ /**
671
+ * Generate a design tree string from an AnalysisFile.
672
+ */
673
+ interface DesignTreeResult {
674
+ /** The design tree text */
675
+ tree: string;
676
+ /** Estimated token count (~4 chars per token for mixed code/text) */
677
+ estimatedTokens: number;
678
+ /** Raw byte size */
679
+ bytes: number;
680
+ }
681
+ /**
682
+ * Generate a design tree string from an AnalysisFile.
683
+ */
684
+ declare function generateDesignTree(file: AnalysisFile, options?: DesignTreeOptions): string;
685
+ /**
686
+ * Generate a design tree with token/size statistics.
687
+ * Use this when you need to measure token consumption for AI context budget.
688
+ */
689
+ declare function generateDesignTreeWithStats(file: AnalysisFile, options?: DesignTreeOptions): DesignTreeResult;
690
+
691
+ /**
692
+ * Strip specific information types from design-tree text for ablation experiments.
693
+ * Post-processes the generated text — does NOT modify design-tree.ts.
694
+ *
695
+ * Flow: generateDesignTree() → stripDesignTree() → send to LLM
696
+ */
697
+ /** All strip types available (including utility strips not used in experiments). */
698
+ type DesignTreeStripType = "layout-direction-spacing" | "size-constraints" | "position-stacking" | "color-values" | "typography" | "shadows-effects" | "component-references" | "component-descriptions" | "node-names-hierarchy" | "overflow-text-behavior" | "hover-interaction-states" | "variable-references" | "style-references";
699
+ /**
700
+ * Experiment-relevant strip types only.
701
+ * Excludes trivially obvious types (color, typography, shadows, overflow, hover)
702
+ * and no-op types (position-stacking, component-descriptions).
703
+ */
704
+ type DesignTreeInfoType = "layout-direction-spacing" | "size-constraints" | "component-references" | "node-names-hierarchy" | "variable-references" | "style-references";
705
+ /** All strip types (used for exhaustive testing). */
706
+ declare const ALL_STRIP_TYPES: readonly DesignTreeStripType[];
707
+ /**
708
+ * Strip experiment types used in calibration ablation (six types).
709
+ * Keep in sync with `StripTypeEnum` / `STRIP_TYPE_RULES` in the agents layer.
710
+ * `size-constraints` pairs with responsive rules `missing-size-constraint`, `fixed-size-in-auto-layout`.
711
+ */
712
+ declare const DESIGN_TREE_INFO_TYPES: readonly DesignTreeInfoType[];
713
+ /**
714
+ * Strip a specific information type from a design-tree text.
715
+ * Returns a new string with the target information removed.
716
+ */
717
+ declare function stripDesignTree(tree: string, type: DesignTreeStripType): string;
718
+
719
+ declare const DifficultySchema: z.ZodEnum<{
720
+ easy: "easy";
721
+ moderate: "moderate";
722
+ hard: "hard";
723
+ failed: "failed";
724
+ }>;
725
+ type Difficulty = z.infer<typeof DifficultySchema>;
726
+ declare const RuleRelatedStruggleSchema: z.ZodObject<{
727
+ ruleId: z.ZodString;
728
+ description: z.ZodString;
729
+ actualImpact: z.ZodEnum<{
730
+ easy: "easy";
731
+ moderate: "moderate";
732
+ hard: "hard";
733
+ failed: "failed";
734
+ }>;
735
+ }, z.core.$strip>;
736
+ type RuleRelatedStruggle = z.infer<typeof RuleRelatedStruggleSchema>;
737
+ declare const UncoveredStruggleSchema: z.ZodObject<{
738
+ description: z.ZodString;
739
+ suggestedCategory: z.ZodString;
740
+ estimatedImpact: z.ZodEnum<{
741
+ easy: "easy";
742
+ moderate: "moderate";
743
+ hard: "hard";
744
+ failed: "failed";
745
+ }>;
746
+ }, z.core.$strip>;
747
+ type UncoveredStruggle = z.infer<typeof UncoveredStruggleSchema>;
748
+ declare const ConversionRecordSchema: z.ZodObject<{
749
+ nodeId: z.ZodString;
750
+ nodePath: z.ZodString;
751
+ generatedCode: z.ZodString;
752
+ difficulty: z.ZodEnum<{
753
+ easy: "easy";
754
+ moderate: "moderate";
755
+ hard: "hard";
756
+ failed: "failed";
757
+ }>;
758
+ notes: z.ZodString;
759
+ ruleRelatedStruggles: z.ZodArray<z.ZodObject<{
760
+ ruleId: z.ZodString;
761
+ description: z.ZodString;
762
+ actualImpact: z.ZodEnum<{
763
+ easy: "easy";
764
+ moderate: "moderate";
765
+ hard: "hard";
766
+ failed: "failed";
767
+ }>;
768
+ }, z.core.$strip>>;
769
+ uncoveredStruggles: z.ZodArray<z.ZodObject<{
770
+ description: z.ZodString;
771
+ suggestedCategory: z.ZodString;
772
+ estimatedImpact: z.ZodEnum<{
773
+ easy: "easy";
774
+ moderate: "moderate";
775
+ hard: "hard";
776
+ failed: "failed";
777
+ }>;
778
+ }, z.core.$strip>>;
779
+ durationMs: z.ZodNumber;
780
+ }, z.core.$strip>;
781
+ type ConversionRecord = z.infer<typeof ConversionRecordSchema>;
782
+ declare const StripTypeEnum: z.ZodEnum<{
783
+ "layout-direction-spacing": "layout-direction-spacing";
784
+ "size-constraints": "size-constraints";
785
+ "component-references": "component-references";
786
+ "node-names-hierarchy": "node-names-hierarchy";
787
+ "variable-references": "variable-references";
788
+ "style-references": "style-references";
789
+ }>;
790
+ declare const StripDeltaResultSchema: z.ZodObject<{
791
+ stripType: z.ZodEnum<{
792
+ "layout-direction-spacing": "layout-direction-spacing";
793
+ "size-constraints": "size-constraints";
794
+ "component-references": "component-references";
795
+ "node-names-hierarchy": "node-names-hierarchy";
796
+ "variable-references": "variable-references";
797
+ "style-references": "style-references";
798
+ }>;
799
+ baselineSimilarity: z.ZodNumber;
800
+ strippedSimilarity: z.ZodNumber;
801
+ delta: z.ZodNumber;
802
+ deltaDifficulty: z.ZodEnum<{
803
+ easy: "easy";
804
+ moderate: "moderate";
805
+ hard: "hard";
806
+ failed: "failed";
807
+ }>;
808
+ baselineResponsiveSimilarity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
809
+ strippedResponsiveSimilarity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
810
+ responsiveDelta: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
811
+ responsiveViewport: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
812
+ baselineInputTokens: z.ZodOptional<z.ZodNumber>;
813
+ strippedInputTokens: z.ZodOptional<z.ZodNumber>;
814
+ tokenDelta: z.ZodOptional<z.ZodNumber>;
815
+ baselineHtmlBytes: z.ZodOptional<z.ZodNumber>;
816
+ strippedHtmlBytes: z.ZodOptional<z.ZodNumber>;
817
+ htmlBytesDelta: z.ZodOptional<z.ZodNumber>;
818
+ baselineCssClassCount: z.ZodOptional<z.ZodNumber>;
819
+ strippedCssClassCount: z.ZodOptional<z.ZodNumber>;
820
+ baselineCssVariableCount: z.ZodOptional<z.ZodNumber>;
821
+ strippedCssVariableCount: z.ZodOptional<z.ZodNumber>;
822
+ }, z.core.$strip>;
823
+ declare const StripDeltasArraySchema: z.ZodArray<z.ZodObject<{
824
+ stripType: z.ZodEnum<{
825
+ "layout-direction-spacing": "layout-direction-spacing";
826
+ "size-constraints": "size-constraints";
827
+ "component-references": "component-references";
828
+ "node-names-hierarchy": "node-names-hierarchy";
829
+ "variable-references": "variable-references";
830
+ "style-references": "style-references";
831
+ }>;
832
+ baselineSimilarity: z.ZodNumber;
833
+ strippedSimilarity: z.ZodNumber;
834
+ delta: z.ZodNumber;
835
+ deltaDifficulty: z.ZodEnum<{
836
+ easy: "easy";
837
+ moderate: "moderate";
838
+ hard: "hard";
839
+ failed: "failed";
840
+ }>;
841
+ baselineResponsiveSimilarity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
842
+ strippedResponsiveSimilarity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
843
+ responsiveDelta: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
844
+ responsiveViewport: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
845
+ baselineInputTokens: z.ZodOptional<z.ZodNumber>;
846
+ strippedInputTokens: z.ZodOptional<z.ZodNumber>;
847
+ tokenDelta: z.ZodOptional<z.ZodNumber>;
848
+ baselineHtmlBytes: z.ZodOptional<z.ZodNumber>;
849
+ strippedHtmlBytes: z.ZodOptional<z.ZodNumber>;
850
+ htmlBytesDelta: z.ZodOptional<z.ZodNumber>;
851
+ baselineCssClassCount: z.ZodOptional<z.ZodNumber>;
852
+ strippedCssClassCount: z.ZodOptional<z.ZodNumber>;
853
+ baselineCssVariableCount: z.ZodOptional<z.ZodNumber>;
854
+ strippedCssVariableCount: z.ZodOptional<z.ZodNumber>;
855
+ }, z.core.$strip>>;
856
+ type StripDeltaResult = z.infer<typeof StripDeltaResultSchema>;
857
+ declare const RuleImpactAssessmentSchema: z.ZodArray<z.ZodObject<{
858
+ ruleId: z.ZodString;
859
+ issueCount: z.ZodNumber;
860
+ actualImpact: z.ZodString;
861
+ description: z.ZodString;
862
+ }, z.core.$strip>>;
863
+ declare const UncoveredStrugglesInputSchema: z.ZodArray<z.ZodObject<{
864
+ description: z.ZodString;
865
+ suggestedCategory: z.ZodString;
866
+ estimatedImpact: z.ZodString;
867
+ }, z.core.$strip>>;
868
+
869
+ /**
870
+ * Delta-based difficulty mapping for ablation experiments.
871
+ * Converts pixel similarity delta (baseline - stripped) to a difficulty level.
872
+ *
873
+ * Used by calibration pipeline to objectively measure rule impact
874
+ * instead of relying on Converter self-assessment.
875
+ */
876
+
877
+ /**
878
+ * Map a strip experiment's similarity delta to a difficulty level.
879
+ *
880
+ * Delta = baseline similarity - stripped similarity (percentage points).
881
+ * Higher delta means removing that information caused more pixel degradation.
882
+ *
883
+ * Thresholds from issue #191:
884
+ * - ≤ 5%p → easy (removing info barely matters)
885
+ * - 6-15%p → moderate (noticeable degradation)
886
+ * - 16-30%p → hard (significant degradation)
887
+ * - > 30%p → failed (critical information)
888
+ */
889
+ declare function stripDeltaToDifficulty(delta: number): Difficulty;
890
+ /**
891
+ * Map a token count delta percentage to a difficulty level.
892
+ *
893
+ * tokenDelta = baselineInputTokens - strippedInputTokens.
894
+ * tokenDeltaPercent = tokenDelta / baselineInputTokens * 100.
895
+ * Higher percentage means removing that info significantly reduces token cost,
896
+ * i.e. the info contributed a lot of tokens — its absence matters for token management.
897
+ *
898
+ * Thresholds:
899
+ * - ≤ 5% → easy (minimal token impact)
900
+ * - 6-20% → moderate (noticeable token savings)
901
+ * - 21-40% → hard (significant token impact)
902
+ * - > 40% → failed (critical for token budget)
903
+ */
904
+ declare function tokenDeltaToDifficulty(baselineTokens: number, strippedTokens: number): Difficulty;
502
905
 
503
906
  /**
504
907
  * Registry for all rules
@@ -548,8 +951,26 @@ declare const ruleRegistry: RuleRegistry;
548
951
  declare function defineRule(rule: Rule): Rule;
549
952
 
550
953
  /**
551
- * Central configuration for all rules
552
- * Edit scores/severity here without touching rule logic
954
+ * Maps each rule ID to its category.
955
+ * Categories are based on ablation experiment data (PR #149, #150):
956
+ * - pixel-critical: ΔV ≥ 5% — layout info removal directly degrades pixel accuracy
957
+ * - responsive-critical: ΔV ≥ 15% at expanded viewport — size info critical for responsive
958
+ * - code-quality: ΔV ≈ 0% but CSS classes -8~15 — affects code structure, not pixels
959
+ * - token-management: raw values without design tokens — wrong input = wrong output
960
+ * - semantic: ΔV < 2%, negligible code difference — naming and semantic issues
961
+ */
962
+ declare const RULE_ID_CATEGORY: Record<RuleId, Category>;
963
+ /**
964
+ * Central configuration for all rules.
965
+ * Scores based on ablation experiment + AI implementation interview (#200):
966
+ * - pixel-critical: -10 ~ -7 (layout strip caused ΔV +5.4%)
967
+ * - responsive-critical: -8 ~ -6 (size-constraints ΔV +15.9% at responsive viewports)
968
+ * - code-quality: -7 ~ -3 (CSS classes -8~15, no pixel impact)
969
+ * - token-management: -5 ~ -4 (wrong input = wrong output, irregular spacing actively causes errors)
970
+ * - interaction: -1 (uncalibrated — no metric to validate, kept minimal #210)
971
+ * - semantic: -4 ~ -1 (non-semantic-name upgraded per interview — causes actual implementation errors)
972
+ *
973
+ * Category weights removed (#196) — overall score is simple average of categories.
553
974
  */
554
975
  declare const RULE_CONFIGS: Record<RuleId, RuleConfig>;
555
976
  /**
@@ -567,55 +988,24 @@ declare function getRuleOption<T>(ruleId: RuleId, optionKey: string, defaultValu
567
988
 
568
989
  declare const noAutoLayout: Rule;
569
990
  declare const absolutePositionInAutoLayout: Rule;
570
- declare const fixedWidthInResponsiveContext: Rule;
571
- declare const missingResponsiveBehavior: Rule;
572
- declare const groupUsage: Rule;
573
991
  declare const fixedSizeInAutoLayout: Rule;
574
- declare const missingMinWidth: Rule;
575
- declare const missingMaxWidth: Rule;
992
+ declare const missingSizeConstraint: Rule;
993
+ declare const nonLayoutContainer: Rule;
576
994
  declare const deepNesting: Rule;
577
- declare const overflowHiddenAbuse: Rule;
578
- declare const inconsistentSiblingLayoutDirection: Rule;
579
995
 
580
- declare const rawColor: Rule;
581
- declare const rawFont: Rule;
582
- declare const inconsistentSpacing: Rule;
583
- declare const magicNumberSpacing: Rule;
584
- declare const rawShadow: Rule;
585
- declare const rawOpacity: Rule;
586
- declare const multipleFillColors: Rule;
996
+ declare const rawValue: Rule;
997
+ declare const irregularSpacing: Rule;
587
998
 
588
999
  declare const missingComponent: Rule;
589
1000
  declare const detachedInstance: Rule;
590
- declare const nestedInstanceOverride: Rule;
591
- declare const variantNotUsed: Rule;
592
- declare const componentPropertyUnused: Rule;
593
- declare const singleUseComponent: Rule;
594
- declare const missingComponentDescription: Rule;
595
- /**
596
- * Reset deduplication state between analysis runs.
597
- * Call this at the start of each analysis if the process is long-running
598
- * (e.g. MCP server mode).
599
- */
600
- declare function resetMissingComponentDescriptionState(): void;
1001
+ declare const variantStructureMismatch: Rule;
601
1002
 
602
- declare const defaultName: Rule;
603
1003
  declare const nonSemanticName: Rule;
604
1004
  declare const inconsistentNamingConvention: Rule;
605
- declare const numericSuffixName: Rule;
606
- declare const tooLongName: Rule;
607
-
608
- declare const ambiguousStructure: Rule;
609
- declare const zIndexDependentLayout: Rule;
610
- declare const missingLayoutHint: Rule;
611
- declare const invisibleLayer: Rule;
612
- declare const emptyFrame: Rule;
1005
+ declare const nonStandardNaming: Rule;
613
1006
 
614
- declare const hardcodeRisk: Rule;
615
- declare const textTruncationUnhandled: Rule;
616
- declare const imageNoPlaceholder: Rule;
617
- declare const prototypeLinkInDesign: Rule;
618
- declare const noDevStatus: Rule;
1007
+ declare const missingInteractionState: Rule;
1008
+ declare const missingPrototype: Rule;
619
1009
 
620
1010
  declare const FigmaUrlInfoSchema: z.ZodObject<{
621
1011
  fileKey: z.ZodString;
@@ -627,6 +1017,13 @@ declare function parseFigmaUrl(url: string): FigmaUrlInfo;
627
1017
  declare class FigmaUrlParseError extends Error {
628
1018
  constructor(message: string);
629
1019
  }
1020
+ /**
1021
+ * Extract the commentable node ID from a potentially nested instance path.
1022
+ * Instance-internal IDs like "I3010:7457;1442:7704" use semicolons to
1023
+ * separate path segments. The Figma Comments API only accepts simple IDs
1024
+ * (e.g. "3010:7457"), so we take the first segment and strip the "I" prefix.
1025
+ */
1026
+ declare function toCommentableNodeId(nodeId: string): string;
630
1027
  declare function buildFigmaDeepLink(fileKey: string, nodeId: string): string;
631
1028
 
632
1029
  interface GetFileNodesResponse {
@@ -655,6 +1052,11 @@ declare class FigmaClient {
655
1052
  format?: "png" | "svg" | "jpg";
656
1053
  scale?: number;
657
1054
  }): Promise<Record<string, string | null>>;
1055
+ /**
1056
+ * Get original image fill URLs by imageRef.
1057
+ * Returns a mapping of imageRef → download URL for all image fills in the file.
1058
+ */
1059
+ getImageFills(fileKey: string): Promise<Record<string, string>>;
658
1060
  /**
659
1061
  * Download an image URL and return as base64
660
1062
  */
@@ -676,6 +1078,11 @@ declare function transformFigmaResponse(fileKey: string, response: GetFileRespon
676
1078
  * Returns the first node's subtree as the document.
677
1079
  */
678
1080
  declare function transformFileNodesResponse(fileKey: string, response: GetFileNodesResponse): AnalysisFile;
1081
+ /**
1082
+ * Transform component master nodes from a /v1/files/{key}/nodes response.
1083
+ * Each requested node ID is transformed into an AnalysisNode if present.
1084
+ */
1085
+ declare function transformComponentMasterNodes(response: GetFileNodesResponse, requestedIds: string[]): Record<string, AnalysisNode>;
679
1086
 
680
1087
  /**
681
1088
  * Load Figma data from a JSON file
@@ -692,25 +1099,32 @@ declare class FigmaFileLoadError extends Error {
692
1099
  }
693
1100
 
694
1101
  /**
695
- * Parse MCP get_metadata XML output into an AnalysisFile.
696
- *
697
- * The XML represents a subtree of the Figma file. We wrap it in a
698
- * DOCUMENT node and fill in minimal file metadata.
1102
+ * Recursively collect all unique componentId values from INSTANCE nodes.
699
1103
  */
700
- declare function parseMcpMetadataXml(xml: string, fileKey: string, fileName?: string): AnalysisFile;
1104
+ declare function collectComponentIds(node: AnalysisNode): Set<string>;
701
1105
  /**
702
- * Enrich an AnalysisFile (from get_metadata) with style data extracted
703
- * from get_design_context code output.
1106
+ * Recursively collect all unique interaction destination IDs from nodes.
1107
+ * These are the node IDs that interactions (e.g., ON_HOVER → CHANGE_TO) point to.
1108
+ */
1109
+ declare function collectInteractionDestinationIds(node: AnalysisNode): Set<string>;
1110
+ /**
1111
+ * Resolve component master node trees via multi-pass fetching.
1112
+ *
1113
+ * Pass 1: collect component IDs from the document tree, fetch their masters.
1114
+ * Pass 2+: collect component IDs from fetched masters that were not in previous passes.
1115
+ * Repeats up to maxPasses (default 2).
704
1116
  *
705
- * The design context code is React+Tailwind generated for a specific node.
706
- * We parse Tailwind classes to extract layout, color, spacing, and effect
707
- * properties, then merge them into matching AnalysisNodes in the tree.
1117
+ * Batches API calls at BATCH_SIZE IDs per request.
1118
+ * Skips IDs that return null (e.g. external library components).
1119
+ */
1120
+ declare function resolveComponentDefinitions(client: FigmaClient, fileKey: string, document: AnalysisNode, maxPasses?: number): Promise<Record<string, AnalysisNode>>;
1121
+ /**
1122
+ * Resolve interaction destination nodes (e.g., hover variants).
708
1123
  *
709
- * @param file - AnalysisFile from parseMcpMetadataXml
710
- * @param designContextCode - Code string from get_design_context
711
- * @param targetNodeId - The node ID that get_design_context was called for (optional)
1124
+ * Collects all destinationId values from interactions in the document,
1125
+ * excludes those already in componentDefinitions, and fetches them.
712
1126
  */
713
- declare function enrichWithDesignContext(file: AnalysisFile, designContextCode: string, targetNodeId?: string): void;
1127
+ declare function resolveInteractionDestinations(client: FigmaClient, fileKey: string, document: AnalysisNode, existingDefinitions?: Record<string, AnalysisNode>): Promise<Record<string, AnalysisNode>>;
714
1128
 
715
1129
  declare const SamplingStrategySchema: z.ZodEnum<{
716
1130
  all: "all";
@@ -719,13 +1133,13 @@ declare const SamplingStrategySchema: z.ZodEnum<{
719
1133
  }>;
720
1134
  type SamplingStrategy = z.infer<typeof SamplingStrategySchema>;
721
1135
  declare const CalibrationStatusSchema: z.ZodEnum<{
1136
+ failed: "failed";
722
1137
  pending: "pending";
723
1138
  analyzing: "analyzing";
724
1139
  converting: "converting";
725
1140
  evaluating: "evaluating";
726
1141
  tuning: "tuning";
727
1142
  completed: "completed";
728
- failed: "failed";
729
1143
  }>;
730
1144
  type CalibrationStatus = z.infer<typeof CalibrationStatusSchema>;
731
1145
  declare const CalibrationConfigSchema: z.ZodObject<{
@@ -739,8 +1153,10 @@ declare const CalibrationConfigSchema: z.ZodObject<{
739
1153
  random: "random";
740
1154
  }>>;
741
1155
  outputPath: z.ZodDefault<z.ZodString>;
1156
+ runDir: z.ZodOptional<z.ZodString>;
742
1157
  }, z.core.$strip>;
743
1158
  type CalibrationConfig = z.infer<typeof CalibrationConfigSchema>;
1159
+ type CalibrationConfigInput = z.input<typeof CalibrationConfigSchema>;
744
1160
  interface CalibrationRun {
745
1161
  config: CalibrationConfig;
746
1162
  status: CalibrationStatus;
@@ -773,90 +1189,6 @@ interface NodeIssueDetail {
773
1189
  message: string;
774
1190
  }
775
1191
 
776
- declare const DifficultySchema: z.ZodEnum<{
777
- failed: "failed";
778
- easy: "easy";
779
- moderate: "moderate";
780
- hard: "hard";
781
- }>;
782
- type Difficulty = z.infer<typeof DifficultySchema>;
783
- declare const RuleRelatedStruggleSchema: z.ZodObject<{
784
- ruleId: z.ZodString;
785
- description: z.ZodString;
786
- actualImpact: z.ZodEnum<{
787
- failed: "failed";
788
- easy: "easy";
789
- moderate: "moderate";
790
- hard: "hard";
791
- }>;
792
- }, z.core.$strip>;
793
- type RuleRelatedStruggle = z.infer<typeof RuleRelatedStruggleSchema>;
794
- declare const UncoveredStruggleSchema: z.ZodObject<{
795
- description: z.ZodString;
796
- suggestedCategory: z.ZodString;
797
- estimatedImpact: z.ZodEnum<{
798
- failed: "failed";
799
- easy: "easy";
800
- moderate: "moderate";
801
- hard: "hard";
802
- }>;
803
- }, z.core.$strip>;
804
- type UncoveredStruggle = z.infer<typeof UncoveredStruggleSchema>;
805
- declare const ConversionRecordSchema: z.ZodObject<{
806
- nodeId: z.ZodString;
807
- nodePath: z.ZodString;
808
- generatedCode: z.ZodString;
809
- difficulty: z.ZodEnum<{
810
- failed: "failed";
811
- easy: "easy";
812
- moderate: "moderate";
813
- hard: "hard";
814
- }>;
815
- notes: z.ZodString;
816
- ruleRelatedStruggles: z.ZodArray<z.ZodObject<{
817
- ruleId: z.ZodString;
818
- description: z.ZodString;
819
- actualImpact: z.ZodEnum<{
820
- failed: "failed";
821
- easy: "easy";
822
- moderate: "moderate";
823
- hard: "hard";
824
- }>;
825
- }, z.core.$strip>>;
826
- uncoveredStruggles: z.ZodArray<z.ZodObject<{
827
- description: z.ZodString;
828
- suggestedCategory: z.ZodString;
829
- estimatedImpact: z.ZodEnum<{
830
- failed: "failed";
831
- easy: "easy";
832
- moderate: "moderate";
833
- hard: "hard";
834
- }>;
835
- }, z.core.$strip>>;
836
- durationMs: z.ZodNumber;
837
- }, z.core.$strip>;
838
- type ConversionRecord = z.infer<typeof ConversionRecordSchema>;
839
- interface ConversionExecutorResult {
840
- generatedCode: string;
841
- difficulty: Difficulty;
842
- notes: string;
843
- ruleRelatedStruggles: RuleRelatedStruggle[];
844
- uncoveredStruggles: UncoveredStruggle[];
845
- }
846
- type ConversionExecutor = (nodeId: string, fileKey: string, flaggedRuleIds: string[]) => Promise<ConversionExecutorResult>;
847
- interface ConversionAgentInput {
848
- fileKey: string;
849
- nodes: Array<{
850
- nodeId: string;
851
- nodePath: string;
852
- flaggedRuleIds: string[];
853
- }>;
854
- }
855
- interface ConversionAgentOutput {
856
- records: ConversionRecord[];
857
- skippedNodeIds: string[];
858
- }
859
-
860
1192
  declare const MismatchTypeSchema: z.ZodEnum<{
861
1193
  overscored: "overscored";
862
1194
  underscored: "underscored";
@@ -882,14 +1214,26 @@ declare const MismatchCaseSchema: z.ZodObject<{
882
1214
  suggestion: "suggestion";
883
1215
  }>>;
884
1216
  actualDifficulty: z.ZodEnum<{
885
- failed: "failed";
886
1217
  easy: "easy";
887
1218
  moderate: "moderate";
888
1219
  hard: "hard";
1220
+ failed: "failed";
889
1221
  }>;
890
1222
  reasoning: z.ZodString;
1223
+ category: z.ZodOptional<z.ZodString>;
1224
+ description: z.ZodOptional<z.ZodString>;
891
1225
  }, z.core.$strip>;
892
1226
  type MismatchCase = z.infer<typeof MismatchCaseSchema>;
1227
+ interface StripDeltaForEval {
1228
+ /** Pixel similarity delta (baseline - stripped) at design viewport */
1229
+ pixelDelta: number;
1230
+ /** Responsive pixel similarity delta at expanded viewport (null if not measured) */
1231
+ responsiveDelta: number | null;
1232
+ /** Baseline design-tree input token count */
1233
+ baselineInputTokens: number | null;
1234
+ /** Stripped design-tree input token count */
1235
+ strippedInputTokens: number | null;
1236
+ }
893
1237
  interface EvaluationAgentInput {
894
1238
  nodeIssueSummaries: Array<{
895
1239
  nodeId: string;
@@ -915,12 +1259,53 @@ interface EvaluationAgentInput {
915
1259
  score: number;
916
1260
  severity: string;
917
1261
  }>;
1262
+ /**
1263
+ * Responsive viewport comparison delta (similarity - responsiveSimilarity).
1264
+ * Positive = design breaks at expanded viewport. Used to evaluate responsive-critical rules.
1265
+ * null/undefined = no responsive comparison available.
1266
+ */
1267
+ responsiveDelta?: number | null | undefined;
1268
+ /**
1269
+ * Strip ablation results keyed by strip type.
1270
+ * Contains pixel delta, token counts, responsive delta, and HTML metrics per strip.
1271
+ * Used to objectively override AI self-assessment with category-appropriate metrics.
1272
+ * undefined = no strip ablation data available.
1273
+ */
1274
+ stripDeltas?: Record<string, StripDeltaForEval> | undefined;
1275
+ /**
1276
+ * Whether the conversion was whole-design (single root record covering the entire page).
1277
+ * When true, evaluation merges all nodeIssueSummaries' flaggedRuleIds into the single record
1278
+ * so rules flagged on child nodes aren't silently dropped.
1279
+ */
1280
+ wholeDesign?: boolean | undefined;
918
1281
  }
919
1282
  interface EvaluationAgentOutput {
920
1283
  mismatches: MismatchCase[];
921
1284
  validatedRules: string[];
922
1285
  }
923
1286
 
1287
+ declare const CrossRunEvidenceGroupSchema: z.ZodObject<{
1288
+ overscoredCount: z.ZodNumber;
1289
+ underscoredCount: z.ZodNumber;
1290
+ overscoredDifficulties: z.ZodArray<z.ZodString>;
1291
+ underscoredDifficulties: z.ZodArray<z.ZodString>;
1292
+ allPro: z.ZodOptional<z.ZodArray<z.ZodString>>;
1293
+ allCon: z.ZodOptional<z.ZodArray<z.ZodString>>;
1294
+ lastConfidence: z.ZodOptional<z.ZodEnum<{
1295
+ high: "high";
1296
+ medium: "medium";
1297
+ low: "low";
1298
+ }>>;
1299
+ lastDecision: z.ZodOptional<z.ZodEnum<{
1300
+ APPROVE: "APPROVE";
1301
+ REJECT: "REJECT";
1302
+ REVISE: "REVISE";
1303
+ HOLD: "HOLD";
1304
+ }>>;
1305
+ }, z.core.$strip>;
1306
+ type CrossRunEvidenceGroup = z.infer<typeof CrossRunEvidenceGroupSchema>;
1307
+ type CrossRunEvidence = Record<string, CrossRunEvidenceGroup>;
1308
+
924
1309
  declare const ConfidenceSchema: z.ZodEnum<{
925
1310
  high: "high";
926
1311
  medium: "medium";
@@ -950,6 +1335,7 @@ declare const ScoreAdjustmentSchema: z.ZodObject<{
950
1335
  low: "low";
951
1336
  }>;
952
1337
  supportingCases: z.ZodNumber;
1338
+ proposedDisable: z.ZodOptional<z.ZodBoolean>;
953
1339
  }, z.core.$strip>;
954
1340
  type ScoreAdjustment = z.infer<typeof ScoreAdjustmentSchema>;
955
1341
  declare const NewRuleProposalSchema: z.ZodObject<{
@@ -977,17 +1363,63 @@ interface TuningAgentInput {
977
1363
  currentSeverity?: string | undefined;
978
1364
  actualDifficulty: string;
979
1365
  reasoning: string;
1366
+ category?: string | undefined;
1367
+ description?: string | undefined;
980
1368
  }>;
981
1369
  ruleScores: Record<string, {
982
1370
  score: number;
983
1371
  severity: string;
984
1372
  }>;
1373
+ priorEvidence?: CrossRunEvidence;
985
1374
  }
986
1375
  interface TuningAgentOutput {
987
1376
  adjustments: ScoreAdjustment[];
988
1377
  newRuleProposals: NewRuleProposal[];
989
1378
  }
990
1379
 
1380
+ declare const GapEntrySchema: z.ZodObject<{
1381
+ category: z.ZodString;
1382
+ description: z.ZodString;
1383
+ pixelImpact: z.ZodOptional<z.ZodString>;
1384
+ coveredByRule: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1385
+ coveredByExistingRule: z.ZodOptional<z.ZodBoolean>;
1386
+ existingRule: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1387
+ causedByInterpretation: z.ZodOptional<z.ZodBoolean>;
1388
+ actionable: z.ZodOptional<z.ZodBoolean>;
1389
+ suggestedRuleCategory: z.ZodOptional<z.ZodString>;
1390
+ area: z.ZodOptional<z.ZodString>;
1391
+ }, z.core.$strip>;
1392
+ type GapEntry = z.infer<typeof GapEntrySchema>;
1393
+ declare const GapAnalyzerOutputSchema: z.ZodObject<{
1394
+ fixture: z.ZodOptional<z.ZodString>;
1395
+ similarity: z.ZodOptional<z.ZodNumber>;
1396
+ timestamp: z.ZodOptional<z.ZodString>;
1397
+ gaps: z.ZodArray<z.ZodObject<{
1398
+ category: z.ZodString;
1399
+ description: z.ZodString;
1400
+ pixelImpact: z.ZodOptional<z.ZodString>;
1401
+ coveredByRule: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1402
+ coveredByExistingRule: z.ZodOptional<z.ZodBoolean>;
1403
+ existingRule: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1404
+ causedByInterpretation: z.ZodOptional<z.ZodBoolean>;
1405
+ actionable: z.ZodOptional<z.ZodBoolean>;
1406
+ suggestedRuleCategory: z.ZodOptional<z.ZodString>;
1407
+ area: z.ZodOptional<z.ZodString>;
1408
+ }, z.core.$strip>>;
1409
+ summary: z.ZodOptional<z.ZodObject<{
1410
+ totalGaps: z.ZodNumber;
1411
+ actionableGaps: z.ZodNumber;
1412
+ coveredByExistingRules: z.ZodNumber;
1413
+ newRuleCandidates: z.ZodNumber;
1414
+ renderingArtifacts: z.ZodNumber;
1415
+ }, z.core.$strip>>;
1416
+ newRuleSuggestions: z.ZodOptional<z.ZodArray<z.ZodObject<{
1417
+ ruleId: z.ZodString;
1418
+ rationale: z.ZodOptional<z.ZodString>;
1419
+ }, z.core.$strip>>>;
1420
+ }, z.core.$strip>;
1421
+ type GapAnalyzerOutput = z.infer<typeof GapAnalyzerOutputSchema>;
1422
+
991
1423
  /**
992
1424
  * Extract rule scores map from analysis result for downstream agents
993
1425
  */
@@ -1003,23 +1435,6 @@ declare function extractRuleScores(result: AnalysisResult): Record<string, {
1003
1435
  */
1004
1436
  declare function runAnalysisAgent(input: AnalysisAgentInput): AnalysisAgentOutput;
1005
1437
 
1006
- /**
1007
- * Conversion Agent - Step 2 of calibration pipeline
1008
- *
1009
- * Attempts code conversion for each node via an injected executor.
1010
- * Uses dependency inversion: the executor handles actual LLM/MCP calls.
1011
- * Failures on individual nodes are captured, not thrown.
1012
- */
1013
- declare function runConversionAgent(input: ConversionAgentInput, executor: ConversionExecutor): Promise<ConversionAgentOutput>;
1014
-
1015
- /**
1016
- * Prompt template for the conversion executor.
1017
- *
1018
- * The executor (typically an LLM session with Figma MCP access) receives
1019
- * this prompt to guide code generation and difficulty assessment.
1020
- */
1021
- declare function buildConversionPrompt(nodeId: string, fileKey: string, flaggedRuleIds: string[]): string;
1022
-
1023
1438
  /**
1024
1439
  * Evaluation Agent - Step 3 of calibration pipeline
1025
1440
  *
@@ -1036,6 +1451,7 @@ declare function runEvaluationAgent(input: EvaluationAgentInput): EvaluationAgen
1036
1451
  */
1037
1452
  declare function runTuningAgent(input: TuningAgentInput): TuningAgentOutput;
1038
1453
 
1454
+ /** Data structure for generating calibration report markdown. */
1039
1455
  interface CalibrationReportData {
1040
1456
  fileKey: string;
1041
1457
  fileName: string;
@@ -1049,31 +1465,22 @@ interface CalibrationReportData {
1049
1465
  validatedRules: string[];
1050
1466
  adjustments: ScoreAdjustment[];
1051
1467
  newRuleProposals: NewRuleProposal[];
1468
+ /** Design tree token metrics (optional — present when design-tree stats are available) */
1469
+ tokenMetrics?: {
1470
+ designTreeTokens: number;
1471
+ designTreeBytes: number;
1472
+ tokensPerNode: number;
1473
+ } | undefined;
1052
1474
  }
1053
1475
  /**
1054
1476
  * Generate a CALIBRATION_REPORT.md from calibration pipeline results
1055
1477
  */
1056
1478
  declare function generateCalibrationReport(data: CalibrationReportData): string;
1057
1479
 
1058
- interface CalibrationRunOptions {
1059
- enableActivityLog?: boolean;
1060
- }
1061
- interface CalibrationRunResult {
1062
- status: CalibrationStatus;
1063
- scoreReport: ScoreReport;
1064
- nodeIssueSummaries: NodeIssueSummary[];
1065
- mismatches: MismatchCase[];
1066
- validatedRules: string[];
1067
- adjustments: ScoreAdjustment[];
1068
- newRuleProposals: NewRuleProposal[];
1069
- reportPath: string;
1070
- logPath?: string | undefined;
1071
- error?: string;
1072
- }
1073
1480
  /**
1074
1481
  * Run Step 1 only: analysis + save JSON output
1075
1482
  */
1076
- declare function runCalibrationAnalyze(config: CalibrationConfig): Promise<{
1483
+ declare function runCalibrationAnalyze(config: CalibrationConfigInput): Promise<{
1077
1484
  analysisOutput: ReturnType<typeof runAnalysisAgent> extends infer T ? T : never;
1078
1485
  ruleScores: Record<string, {
1079
1486
  score: number;
@@ -1092,37 +1499,17 @@ declare function runCalibrationEvaluate(analysisJson: {
1092
1499
  analyzedAt: string;
1093
1500
  nodeCount: number;
1094
1501
  issueCount: number;
1095
- }, conversionJson: {
1096
- records: Array<{
1097
- nodeId: string;
1098
- nodePath: string;
1099
- difficulty: string;
1100
- ruleRelatedStruggles: Array<{
1101
- ruleId: string;
1102
- description: string;
1103
- actualImpact: string;
1104
- }>;
1105
- uncoveredStruggles: Array<{
1106
- description: string;
1107
- suggestedCategory: string;
1108
- estimatedImpact: string;
1109
- }>;
1110
- }>;
1111
- skippedNodeIds: string[];
1112
- }, ruleScores: Record<string, {
1502
+ }, conversionJson: Record<string, unknown>, ruleScores: Record<string, {
1113
1503
  score: number;
1114
1504
  severity: string;
1115
- }>): {
1505
+ }>, options?: {
1506
+ collectEvidence?: boolean | undefined;
1507
+ fixtureName?: string | undefined;
1508
+ }): {
1116
1509
  evaluationOutput: EvaluationAgentOutput;
1117
1510
  tuningOutput: TuningAgentOutput;
1118
1511
  report: string;
1119
1512
  };
1120
- /**
1121
- * Run the full calibration pipeline
1122
- *
1123
- * Sequence: validate -> load file -> analysis -> node selection -> conversion -> evaluation -> tuning -> report
1124
- */
1125
- declare function runCalibration(config: CalibrationConfig, executor: ConversionExecutor, options?: CalibrationRunOptions): Promise<CalibrationRunResult>;
1126
1513
 
1127
1514
  interface ActivityStep {
1128
1515
  step: string;
@@ -1133,17 +1520,17 @@ interface ActivityStep {
1133
1520
  declare class ActivityLogger {
1134
1521
  private logPath;
1135
1522
  private initialized;
1136
- constructor(fixturePath?: string, logDir?: string);
1523
+ constructor(runDir: string);
1137
1524
  /**
1138
1525
  * Ensure the log directory and file header exist
1139
1526
  */
1140
1527
  private ensureInitialized;
1141
1528
  /**
1142
- * Log a pipeline step
1529
+ * Log a pipeline step as a JSON Lines entry
1143
1530
  */
1144
1531
  logStep(activity: ActivityStep): Promise<void>;
1145
1532
  /**
1146
- * Log a summary at pipeline completion
1533
+ * Log a summary at pipeline completion as a JSON Lines entry
1147
1534
  */
1148
1535
  logSummary(summary: {
1149
1536
  totalDurationMs: number;
@@ -1156,4 +1543,4 @@ declare class ActivityLogger {
1156
1543
  getLogPath(): string;
1157
1544
  }
1158
1545
 
1159
- export { ActivityLogger, type AnalysisAgentInput, type AnalysisAgentOutput, type AnalysisFile, AnalysisFileSchema, type AnalysisIssue, type AnalysisNode, AnalysisNodeSchema, type AnalysisNodeType, AnalysisNodeTypeSchema, type AnalysisResult, CATEGORIES, CATEGORY_LABELS, type CalibrationConfig, CalibrationConfigSchema, type CalibrationRun, type CalibrationStatus, CalibrationStatusSchema, type Category, CategorySchema, type CategoryScore, type CategoryScoreResult, CategoryScoreSchema, type Confidence, ConfidenceSchema, type ConversionAgentInput, type ConversionAgentOutput, type ConversionExecutor, type ConversionExecutorResult, type ConversionRecord, ConversionRecordSchema, DEPTH_WEIGHT_CATEGORIES, type Difficulty, DifficultySchema, type EvaluationAgentInput, type EvaluationAgentOutput, FigmaClient, FigmaClientError, type FigmaClientOptions, FigmaFileLoadError, type FigmaUrlInfo, FigmaUrlInfoSchema, FigmaUrlParseError, type GetFileNodesResponse, type Grade, type Issue, IssueSchema, type LayoutAlign, LayoutAlignSchema, type LayoutMode, LayoutModeSchema, type LayoutPositioning, LayoutPositioningSchema, type MismatchCase, MismatchCaseSchema, type MismatchType, MismatchTypeSchema, type NewRuleProposal, NewRuleProposalSchema, type NodeIssueDetail, type NodeIssueSummary, NodeIssueSummarySchema, type Preset, RULE_CONFIGS, type Report, type ReportMetadata, ReportMetadataSchema, ReportSchema, type Rule, type RuleCheckFn, type RuleConfig, RuleConfigSchema, type RuleContext, type RuleDefinition, RuleDefinitionSchema, RuleEngine, type RuleEngineOptions, type RuleId, type RuleRelatedStruggle, RuleRelatedStruggleSchema, type RuleViolation, SEVERITY_LABELS, SEVERITY_WEIGHT, type SamplingStrategy, SamplingStrategySchema, type ScoreAdjustment, ScoreAdjustmentSchema, type ScoreReport, type Severity, SeveritySchema, type TuningAgentInput, type TuningAgentOutput, type UncoveredStruggle, UncoveredStruggleSchema, version as VERSION, absolutePositionInAutoLayout, ambiguousStructure, analyzeFile, buildConversionPrompt, buildFigmaDeepLink, buildResultJson, calculateScores, componentPropertyUnused, createRuleEngine, deepNesting, defaultName, defineRule, detachedInstance, emptyFrame, enrichWithDesignContext, extractRuleScores, fixedSizeInAutoLayout, fixedWidthInResponsiveContext, formatScoreSummary, generateCalibrationReport, getCategoryLabel, getConfigsWithPreset, getRuleOption, getSeverityLabel, gradeToClassName, groupUsage, hardcodeRisk, imageNoPlaceholder, inconsistentNamingConvention, inconsistentSiblingLayoutDirection, inconsistentSpacing, invisibleLayer, loadFigmaFileFromJson, magicNumberSpacing, missingComponent, missingComponentDescription, missingLayoutHint, missingMaxWidth, missingMinWidth, missingResponsiveBehavior, multipleFillColors, nestedInstanceOverride, noAutoLayout, noDevStatus, nonSemanticName, numericSuffixName, overflowHiddenAbuse, parseFigmaJson, parseFigmaUrl, parseMcpMetadataXml, prototypeLinkInDesign, rawColor, rawFont, rawOpacity, rawShadow, resetMissingComponentDescriptionState, ruleRegistry, runAnalysisAgent, runCalibration, runCalibrationAnalyze, runCalibrationEvaluate, runConversionAgent, runEvaluationAgent, runTuningAgent, singleUseComponent, supportsDepthWeight, textTruncationUnhandled, tooLongName, transformFigmaResponse, transformFileNodesResponse, variantNotUsed, zIndexDependentLayout };
1546
+ export { ALL_STRIP_TYPES, ActivityLogger, type AnalysisAgentInput, type AnalysisAgentOutput, type AnalysisFile, AnalysisFileSchema, type AnalysisIssue, type AnalysisNode, AnalysisNodeSchema, type AnalysisNodeType, AnalysisNodeTypeSchema, type AnalysisResult, CATEGORIES, CATEGORY_LABELS, type CalibrationConfig, type CalibrationConfigInput, CalibrationConfigSchema, type CalibrationRun, type CalibrationStatus, CalibrationStatusSchema, type Category, CategorySchema, type CategoryScore, type CategoryScoreResult, CategoryScoreSchema, type Confidence, ConfidenceSchema, type ConversionRecord, ConversionRecordSchema, DEPTH_WEIGHT_CATEGORIES, DESIGN_TREE_INFO_TYPES, type DesignTreeInfoType, type DesignTreeOptions, type DesignTreeResult, type DesignTreeStripType, type Difficulty, DifficultySchema, type EvaluationAgentInput, type EvaluationAgentOutput, FigmaClient, FigmaClientError, type FigmaClientOptions, FigmaFileLoadError, type FigmaUrlInfo, FigmaUrlInfoSchema, FigmaUrlParseError, type GapAnalyzerOutput, GapAnalyzerOutputSchema, type GapEntry, GapEntrySchema, type GetFileNodesResponse, type Grade, type GridChildAlign, GridChildAlignSchema, type Issue, IssueSchema, type LayoutAlign, LayoutAlignSchema, type LayoutConstraint, LayoutConstraintSchema, type LayoutMode, LayoutModeSchema, type LayoutPositioning, LayoutPositioningSchema, type LayoutWrap, LayoutWrapSchema, type MismatchCase, MismatchCaseSchema, type MismatchType, MismatchTypeSchema, type NewRuleProposal, NewRuleProposalSchema, type NodeIssueDetail, type NodeIssueSummary, NodeIssueSummarySchema, type OverflowDirection, OverflowDirectionSchema, type Preset, RULE_CONFIGS, RULE_ID_CATEGORY, type Report, type ReportMetadata, ReportMetadataSchema, ReportSchema, type Rule, type RuleCheckFn, type RuleConfig, RuleConfigSchema, type RuleContext, type RuleDefinition, RuleDefinitionSchema, RuleEngine, type RuleEngineOptions, type RuleFailure, type RuleId, RuleImpactAssessmentSchema, type RuleRelatedStruggle, RuleRelatedStruggleSchema, type RuleViolation, SEVERITY_LABELS, SEVERITY_WEIGHT, type SamplingStrategy, SamplingStrategySchema, type ScoreAdjustment, ScoreAdjustmentSchema, type ScoreReport, type Severity, SeveritySchema, type StripDeltaForEval, type StripDeltaResult, StripDeltaResultSchema, StripDeltasArraySchema, StripTypeEnum, type TuningAgentInput, type TuningAgentOutput, type UncoveredStruggle, UncoveredStruggleSchema, UncoveredStrugglesInputSchema, version as VERSION, type VisualCompareCliOptions, VisualCompareCliOptionsSchema, absolutePositionInAutoLayout, analyzeFile, buildFigmaDeepLink, buildResultJson, calculateScores, collectComponentIds, collectInteractionDestinationIds, createRuleEngine, deepNesting, defineRule, detachedInstance, extractRuleScores, fixedSizeInAutoLayout, formatScoreSummary, generateCalibrationReport, generateDesignTree, generateDesignTreeWithStats, getAnalysisState, getCategoryLabel, getConfigsWithPreset, getRuleOption, getSeverityLabel, gradeToClassName, inconsistentNamingConvention, irregularSpacing, loadFigmaFileFromJson, missingComponent, missingInteractionState, missingPrototype, missingSizeConstraint, noAutoLayout, nonLayoutContainer, nonSemanticName, nonStandardNaming, parseFigmaJson, parseFigmaUrl, rawValue, resolveComponentDefinitions, resolveInteractionDestinations, ruleRegistry, runAnalysisAgent, runCalibrationAnalyze, runCalibrationEvaluate, runEvaluationAgent, runTuningAgent, stripDeltaToDifficulty, stripDesignTree, supportsDepthWeight, toCommentableNodeId, tokenDeltaToDifficulty, transformComponentMasterNodes, transformFigmaResponse, transformFileNodesResponse, variantStructureMismatch };