canicode 0.8.8 → 0.9.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/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.8";
4
+ var version = "0.9.0";
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,10 +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>>;
261
+ cornerRadius: z.ZodOptional<z.ZodNumber>;
262
+ opacity: z.ZodOptional<z.ZodNumber>;
160
263
  boundVariables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
161
264
  characters: z.ZodOptional<z.ZodString>;
162
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>;
163
271
  devStatus: z.ZodOptional<z.ZodObject<{
164
272
  type: z.ZodEnum<{
165
273
  NONE: "NONE";
@@ -168,6 +276,7 @@ declare const BaseAnalysisNodeSchema: z.ZodObject<{
168
276
  }>;
169
277
  description: z.ZodOptional<z.ZodString>;
170
278
  }, z.core.$strip>>;
279
+ interactions: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
171
280
  isAsset: z.ZodOptional<z.ZodBoolean>;
172
281
  }, z.core.$strip>;
173
282
  type AnalysisNode = z.infer<typeof BaseAnalysisNodeSchema> & {
@@ -182,12 +291,15 @@ declare const AnalysisFileSchema: z.ZodObject<{
182
291
  name: z.ZodString;
183
292
  lastModified: z.ZodString;
184
293
  version: z.ZodString;
294
+ sourceUrl: z.ZodOptional<z.ZodString>;
185
295
  document: z.ZodType<AnalysisNode, unknown, z.core.$ZodTypeInternals<AnalysisNode, unknown>>;
186
296
  components: z.ZodRecord<z.ZodString, z.ZodObject<{
187
297
  key: z.ZodString;
188
298
  name: z.ZodString;
189
299
  description: z.ZodString;
190
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>>>>;
191
303
  styles: z.ZodRecord<z.ZodString, z.ZodObject<{
192
304
  key: z.ZodString;
193
305
  name: z.ZodString;
@@ -203,12 +315,12 @@ declare const RuleDefinitionSchema: z.ZodObject<{
203
315
  id: z.ZodString;
204
316
  name: z.ZodString;
205
317
  category: z.ZodEnum<{
206
- layout: "layout";
207
- token: "token";
208
- component: "component";
209
- naming: "naming";
210
- "ai-readability": "ai-readability";
211
- "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";
212
324
  }>;
213
325
  why: z.ZodString;
214
326
  impact: z.ZodString;
@@ -238,18 +350,32 @@ interface RuleContext {
238
350
  file: AnalysisFile;
239
351
  parent?: AnalysisNode | undefined;
240
352
  depth: number;
353
+ /** Depth relative to the nearest COMPONENT/INSTANCE ancestor. Resets at component boundaries. */
354
+ componentDepth: number;
241
355
  maxDepth: number;
242
356
  path: string[];
357
+ /** Ancestor node types from root to parent (excludes current node). */
358
+ ancestorTypes: string[];
243
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>;
244
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;
245
368
  /**
246
369
  * Rule violation result from check function
247
370
  */
248
371
  interface RuleViolation {
249
372
  ruleId: string;
373
+ subType?: string;
250
374
  nodeId: string;
251
375
  nodePath: string;
252
376
  message: string;
377
+ suggestion: string;
378
+ guide?: string;
253
379
  }
254
380
  /**
255
381
  * Rule check function signature
@@ -265,7 +391,7 @@ interface Rule {
265
391
  /**
266
392
  * Rule ID type for type safety
267
393
  */
268
- 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";
269
395
  /**
270
396
  * Categories that support depthWeight
271
397
  */
@@ -292,12 +418,12 @@ type Issue = z.infer<typeof IssueSchema>;
292
418
 
293
419
  declare const CategoryScoreSchema: z.ZodObject<{
294
420
  category: z.ZodEnum<{
295
- layout: "layout";
296
- token: "token";
297
- component: "component";
298
- naming: "naming";
299
- "ai-readability": "ai-readability";
300
- "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";
301
427
  }>;
302
428
  score: z.ZodNumber;
303
429
  maxScore: z.ZodNumber;
@@ -326,12 +452,12 @@ declare const ReportSchema: z.ZodObject<{
326
452
  totalScore: z.ZodNumber;
327
453
  categoryScores: z.ZodArray<z.ZodObject<{
328
454
  category: z.ZodEnum<{
329
- layout: "layout";
330
- token: "token";
331
- component: "component";
332
- naming: "naming";
333
- "ai-readability": "ai-readability";
334
- "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";
335
461
  }>;
336
462
  score: z.ZodNumber;
337
463
  maxScore: z.ZodNumber;
@@ -364,6 +490,19 @@ declare const ReportSchema: z.ZodObject<{
364
490
  }, z.core.$strip>;
365
491
  type Report = z.infer<typeof ReportSchema>;
366
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
+
367
506
  /**
368
507
  * Analysis issue with calculated score and metadata
369
508
  */
@@ -375,12 +514,22 @@ interface AnalysisIssue {
375
514
  maxDepth: number;
376
515
  calculatedScore: number;
377
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
+ }
378
526
  /**
379
527
  * Analysis result from the rule engine
380
528
  */
381
529
  interface AnalysisResult {
382
530
  file: AnalysisFile;
383
531
  issues: AnalysisIssue[];
532
+ failedRules: RuleFailure[];
384
533
  maxDepth: number;
385
534
  nodeCount: number;
386
535
  analyzedAt: string;
@@ -477,10 +626,14 @@ declare function gradeToClassName(grade: Grade): string;
477
626
  * Calculate scores from analysis result using density + diversity scoring
478
627
  *
479
628
  * Density Score = 100 - (weighted issue count / node count) * 100
480
- * Diversity Score = (1 - unique rules / total category rules) * 100
629
+ * Diversity Score = (1 - weighted triggered rule scores / total category scores) * 100
481
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.
482
635
  */
483
- declare function calculateScores(result: AnalysisResult): ScoreReport;
636
+ declare function calculateScores(result: AnalysisResult, configs?: Record<RuleId, RuleConfig>): ScoreReport;
484
637
  /**
485
638
  * Format score report as a summary string
486
639
  */
@@ -497,7 +650,258 @@ declare function getSeverityLabel(severity: Severity): string;
497
650
  * Build a JSON-serializable analysis result summary.
498
651
  * Shared by CLI (--json) and MCP server (analyze tool response).
499
652
  */
500
- 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;
501
905
 
502
906
  /**
503
907
  * Registry for all rules
@@ -547,8 +951,26 @@ declare const ruleRegistry: RuleRegistry;
547
951
  declare function defineRule(rule: Rule): Rule;
548
952
 
549
953
  /**
550
- * Central configuration for all rules
551
- * 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.
552
974
  */
553
975
  declare const RULE_CONFIGS: Record<RuleId, RuleConfig>;
554
976
  /**
@@ -566,55 +988,24 @@ declare function getRuleOption<T>(ruleId: RuleId, optionKey: string, defaultValu
566
988
 
567
989
  declare const noAutoLayout: Rule;
568
990
  declare const absolutePositionInAutoLayout: Rule;
569
- declare const fixedWidthInResponsiveContext: Rule;
570
- declare const missingResponsiveBehavior: Rule;
571
- declare const groupUsage: Rule;
572
991
  declare const fixedSizeInAutoLayout: Rule;
573
- declare const missingMinWidth: Rule;
574
- declare const missingMaxWidth: Rule;
992
+ declare const missingSizeConstraint: Rule;
993
+ declare const nonLayoutContainer: Rule;
575
994
  declare const deepNesting: Rule;
576
- declare const overflowHiddenAbuse: Rule;
577
- declare const inconsistentSiblingLayoutDirection: Rule;
578
995
 
579
- declare const rawColor: Rule;
580
- declare const rawFont: Rule;
581
- declare const inconsistentSpacing: Rule;
582
- declare const magicNumberSpacing: Rule;
583
- declare const rawShadow: Rule;
584
- declare const rawOpacity: Rule;
585
- declare const multipleFillColors: Rule;
996
+ declare const rawValue: Rule;
997
+ declare const irregularSpacing: Rule;
586
998
 
587
999
  declare const missingComponent: Rule;
588
1000
  declare const detachedInstance: Rule;
589
- declare const nestedInstanceOverride: Rule;
590
- declare const variantNotUsed: Rule;
591
- declare const componentPropertyUnused: Rule;
592
- declare const singleUseComponent: Rule;
593
- declare const missingComponentDescription: Rule;
594
- /**
595
- * Reset deduplication state between analysis runs.
596
- * Call this at the start of each analysis if the process is long-running
597
- * (e.g. MCP server mode).
598
- */
599
- declare function resetMissingComponentDescriptionState(): void;
1001
+ declare const variantStructureMismatch: Rule;
600
1002
 
601
- declare const defaultName: Rule;
602
1003
  declare const nonSemanticName: Rule;
603
1004
  declare const inconsistentNamingConvention: Rule;
604
- declare const numericSuffixName: Rule;
605
- declare const tooLongName: Rule;
606
-
607
- declare const ambiguousStructure: Rule;
608
- declare const zIndexDependentLayout: Rule;
609
- declare const missingLayoutHint: Rule;
610
- declare const invisibleLayer: Rule;
611
- declare const emptyFrame: Rule;
1005
+ declare const nonStandardNaming: Rule;
612
1006
 
613
- declare const hardcodeRisk: Rule;
614
- declare const textTruncationUnhandled: Rule;
615
- declare const imageNoPlaceholder: Rule;
616
- declare const prototypeLinkInDesign: Rule;
617
- declare const noDevStatus: Rule;
1007
+ declare const missingInteractionState: Rule;
1008
+ declare const missingPrototype: Rule;
618
1009
 
619
1010
  declare const FigmaUrlInfoSchema: z.ZodObject<{
620
1011
  fileKey: z.ZodString;
@@ -626,6 +1017,13 @@ declare function parseFigmaUrl(url: string): FigmaUrlInfo;
626
1017
  declare class FigmaUrlParseError extends Error {
627
1018
  constructor(message: string);
628
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;
629
1027
  declare function buildFigmaDeepLink(fileKey: string, nodeId: string): string;
630
1028
 
631
1029
  interface GetFileNodesResponse {
@@ -654,6 +1052,11 @@ declare class FigmaClient {
654
1052
  format?: "png" | "svg" | "jpg";
655
1053
  scale?: number;
656
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>>;
657
1060
  /**
658
1061
  * Download an image URL and return as base64
659
1062
  */
@@ -675,6 +1078,11 @@ declare function transformFigmaResponse(fileKey: string, response: GetFileRespon
675
1078
  * Returns the first node's subtree as the document.
676
1079
  */
677
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>;
678
1086
 
679
1087
  /**
680
1088
  * Load Figma data from a JSON file
@@ -691,25 +1099,32 @@ declare class FigmaFileLoadError extends Error {
691
1099
  }
692
1100
 
693
1101
  /**
694
- * Parse MCP get_metadata XML output into an AnalysisFile.
695
- *
696
- * The XML represents a subtree of the Figma file. We wrap it in a
697
- * DOCUMENT node and fill in minimal file metadata.
1102
+ * Recursively collect all unique componentId values from INSTANCE nodes.
698
1103
  */
699
- declare function parseMcpMetadataXml(xml: string, fileKey: string, fileName?: string): AnalysisFile;
1104
+ declare function collectComponentIds(node: AnalysisNode): Set<string>;
700
1105
  /**
701
- * Enrich an AnalysisFile (from get_metadata) with style data extracted
702
- * 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).
703
1116
  *
704
- * The design context code is React+Tailwind generated for a specific node.
705
- * We parse Tailwind classes to extract layout, color, spacing, and effect
706
- * 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).
707
1123
  *
708
- * @param file - AnalysisFile from parseMcpMetadataXml
709
- * @param designContextCode - Code string from get_design_context
710
- * @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.
711
1126
  */
712
- 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>>;
713
1128
 
714
1129
  declare const SamplingStrategySchema: z.ZodEnum<{
715
1130
  all: "all";
@@ -718,13 +1133,13 @@ declare const SamplingStrategySchema: z.ZodEnum<{
718
1133
  }>;
719
1134
  type SamplingStrategy = z.infer<typeof SamplingStrategySchema>;
720
1135
  declare const CalibrationStatusSchema: z.ZodEnum<{
1136
+ failed: "failed";
721
1137
  pending: "pending";
722
1138
  analyzing: "analyzing";
723
1139
  converting: "converting";
724
1140
  evaluating: "evaluating";
725
1141
  tuning: "tuning";
726
1142
  completed: "completed";
727
- failed: "failed";
728
1143
  }>;
729
1144
  type CalibrationStatus = z.infer<typeof CalibrationStatusSchema>;
730
1145
  declare const CalibrationConfigSchema: z.ZodObject<{
@@ -738,8 +1153,10 @@ declare const CalibrationConfigSchema: z.ZodObject<{
738
1153
  random: "random";
739
1154
  }>>;
740
1155
  outputPath: z.ZodDefault<z.ZodString>;
1156
+ runDir: z.ZodOptional<z.ZodString>;
741
1157
  }, z.core.$strip>;
742
1158
  type CalibrationConfig = z.infer<typeof CalibrationConfigSchema>;
1159
+ type CalibrationConfigInput = z.input<typeof CalibrationConfigSchema>;
743
1160
  interface CalibrationRun {
744
1161
  config: CalibrationConfig;
745
1162
  status: CalibrationStatus;
@@ -772,90 +1189,6 @@ interface NodeIssueDetail {
772
1189
  message: string;
773
1190
  }
774
1191
 
775
- declare const DifficultySchema: z.ZodEnum<{
776
- failed: "failed";
777
- easy: "easy";
778
- moderate: "moderate";
779
- hard: "hard";
780
- }>;
781
- type Difficulty = z.infer<typeof DifficultySchema>;
782
- declare const RuleRelatedStruggleSchema: z.ZodObject<{
783
- ruleId: z.ZodString;
784
- description: z.ZodString;
785
- actualImpact: z.ZodEnum<{
786
- failed: "failed";
787
- easy: "easy";
788
- moderate: "moderate";
789
- hard: "hard";
790
- }>;
791
- }, z.core.$strip>;
792
- type RuleRelatedStruggle = z.infer<typeof RuleRelatedStruggleSchema>;
793
- declare const UncoveredStruggleSchema: z.ZodObject<{
794
- description: z.ZodString;
795
- suggestedCategory: z.ZodString;
796
- estimatedImpact: z.ZodEnum<{
797
- failed: "failed";
798
- easy: "easy";
799
- moderate: "moderate";
800
- hard: "hard";
801
- }>;
802
- }, z.core.$strip>;
803
- type UncoveredStruggle = z.infer<typeof UncoveredStruggleSchema>;
804
- declare const ConversionRecordSchema: z.ZodObject<{
805
- nodeId: z.ZodString;
806
- nodePath: z.ZodString;
807
- generatedCode: z.ZodString;
808
- difficulty: z.ZodEnum<{
809
- failed: "failed";
810
- easy: "easy";
811
- moderate: "moderate";
812
- hard: "hard";
813
- }>;
814
- notes: z.ZodString;
815
- ruleRelatedStruggles: z.ZodArray<z.ZodObject<{
816
- ruleId: z.ZodString;
817
- description: z.ZodString;
818
- actualImpact: z.ZodEnum<{
819
- failed: "failed";
820
- easy: "easy";
821
- moderate: "moderate";
822
- hard: "hard";
823
- }>;
824
- }, z.core.$strip>>;
825
- uncoveredStruggles: z.ZodArray<z.ZodObject<{
826
- description: z.ZodString;
827
- suggestedCategory: z.ZodString;
828
- estimatedImpact: z.ZodEnum<{
829
- failed: "failed";
830
- easy: "easy";
831
- moderate: "moderate";
832
- hard: "hard";
833
- }>;
834
- }, z.core.$strip>>;
835
- durationMs: z.ZodNumber;
836
- }, z.core.$strip>;
837
- type ConversionRecord = z.infer<typeof ConversionRecordSchema>;
838
- interface ConversionExecutorResult {
839
- generatedCode: string;
840
- difficulty: Difficulty;
841
- notes: string;
842
- ruleRelatedStruggles: RuleRelatedStruggle[];
843
- uncoveredStruggles: UncoveredStruggle[];
844
- }
845
- type ConversionExecutor = (nodeId: string, fileKey: string, flaggedRuleIds: string[]) => Promise<ConversionExecutorResult>;
846
- interface ConversionAgentInput {
847
- fileKey: string;
848
- nodes: Array<{
849
- nodeId: string;
850
- nodePath: string;
851
- flaggedRuleIds: string[];
852
- }>;
853
- }
854
- interface ConversionAgentOutput {
855
- records: ConversionRecord[];
856
- skippedNodeIds: string[];
857
- }
858
-
859
1192
  declare const MismatchTypeSchema: z.ZodEnum<{
860
1193
  overscored: "overscored";
861
1194
  underscored: "underscored";
@@ -881,14 +1214,26 @@ declare const MismatchCaseSchema: z.ZodObject<{
881
1214
  suggestion: "suggestion";
882
1215
  }>>;
883
1216
  actualDifficulty: z.ZodEnum<{
884
- failed: "failed";
885
1217
  easy: "easy";
886
1218
  moderate: "moderate";
887
1219
  hard: "hard";
1220
+ failed: "failed";
888
1221
  }>;
889
1222
  reasoning: z.ZodString;
1223
+ category: z.ZodOptional<z.ZodString>;
1224
+ description: z.ZodOptional<z.ZodString>;
890
1225
  }, z.core.$strip>;
891
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
+ }
892
1237
  interface EvaluationAgentInput {
893
1238
  nodeIssueSummaries: Array<{
894
1239
  nodeId: string;
@@ -914,12 +1259,53 @@ interface EvaluationAgentInput {
914
1259
  score: number;
915
1260
  severity: string;
916
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;
917
1281
  }
918
1282
  interface EvaluationAgentOutput {
919
1283
  mismatches: MismatchCase[];
920
1284
  validatedRules: string[];
921
1285
  }
922
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
+
923
1309
  declare const ConfidenceSchema: z.ZodEnum<{
924
1310
  high: "high";
925
1311
  medium: "medium";
@@ -949,6 +1335,7 @@ declare const ScoreAdjustmentSchema: z.ZodObject<{
949
1335
  low: "low";
950
1336
  }>;
951
1337
  supportingCases: z.ZodNumber;
1338
+ proposedDisable: z.ZodOptional<z.ZodBoolean>;
952
1339
  }, z.core.$strip>;
953
1340
  type ScoreAdjustment = z.infer<typeof ScoreAdjustmentSchema>;
954
1341
  declare const NewRuleProposalSchema: z.ZodObject<{
@@ -976,17 +1363,63 @@ interface TuningAgentInput {
976
1363
  currentSeverity?: string | undefined;
977
1364
  actualDifficulty: string;
978
1365
  reasoning: string;
1366
+ category?: string | undefined;
1367
+ description?: string | undefined;
979
1368
  }>;
980
1369
  ruleScores: Record<string, {
981
1370
  score: number;
982
1371
  severity: string;
983
1372
  }>;
1373
+ priorEvidence?: CrossRunEvidence;
984
1374
  }
985
1375
  interface TuningAgentOutput {
986
1376
  adjustments: ScoreAdjustment[];
987
1377
  newRuleProposals: NewRuleProposal[];
988
1378
  }
989
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
+
990
1423
  /**
991
1424
  * Extract rule scores map from analysis result for downstream agents
992
1425
  */
@@ -1002,23 +1435,6 @@ declare function extractRuleScores(result: AnalysisResult): Record<string, {
1002
1435
  */
1003
1436
  declare function runAnalysisAgent(input: AnalysisAgentInput): AnalysisAgentOutput;
1004
1437
 
1005
- /**
1006
- * Conversion Agent - Step 2 of calibration pipeline
1007
- *
1008
- * Attempts code conversion for each node via an injected executor.
1009
- * Uses dependency inversion: the executor handles actual LLM/MCP calls.
1010
- * Failures on individual nodes are captured, not thrown.
1011
- */
1012
- declare function runConversionAgent(input: ConversionAgentInput, executor: ConversionExecutor): Promise<ConversionAgentOutput>;
1013
-
1014
- /**
1015
- * Prompt template for the conversion executor.
1016
- *
1017
- * The executor (typically an LLM session with Figma MCP access) receives
1018
- * this prompt to guide code generation and difficulty assessment.
1019
- */
1020
- declare function buildConversionPrompt(nodeId: string, fileKey: string, flaggedRuleIds: string[]): string;
1021
-
1022
1438
  /**
1023
1439
  * Evaluation Agent - Step 3 of calibration pipeline
1024
1440
  *
@@ -1035,6 +1451,7 @@ declare function runEvaluationAgent(input: EvaluationAgentInput): EvaluationAgen
1035
1451
  */
1036
1452
  declare function runTuningAgent(input: TuningAgentInput): TuningAgentOutput;
1037
1453
 
1454
+ /** Data structure for generating calibration report markdown. */
1038
1455
  interface CalibrationReportData {
1039
1456
  fileKey: string;
1040
1457
  fileName: string;
@@ -1048,31 +1465,22 @@ interface CalibrationReportData {
1048
1465
  validatedRules: string[];
1049
1466
  adjustments: ScoreAdjustment[];
1050
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;
1051
1474
  }
1052
1475
  /**
1053
1476
  * Generate a CALIBRATION_REPORT.md from calibration pipeline results
1054
1477
  */
1055
1478
  declare function generateCalibrationReport(data: CalibrationReportData): string;
1056
1479
 
1057
- interface CalibrationRunOptions {
1058
- enableActivityLog?: boolean;
1059
- }
1060
- interface CalibrationRunResult {
1061
- status: CalibrationStatus;
1062
- scoreReport: ScoreReport;
1063
- nodeIssueSummaries: NodeIssueSummary[];
1064
- mismatches: MismatchCase[];
1065
- validatedRules: string[];
1066
- adjustments: ScoreAdjustment[];
1067
- newRuleProposals: NewRuleProposal[];
1068
- reportPath: string;
1069
- logPath?: string | undefined;
1070
- error?: string;
1071
- }
1072
1480
  /**
1073
1481
  * Run Step 1 only: analysis + save JSON output
1074
1482
  */
1075
- declare function runCalibrationAnalyze(config: CalibrationConfig): Promise<{
1483
+ declare function runCalibrationAnalyze(config: CalibrationConfigInput): Promise<{
1076
1484
  analysisOutput: ReturnType<typeof runAnalysisAgent> extends infer T ? T : never;
1077
1485
  ruleScores: Record<string, {
1078
1486
  score: number;
@@ -1091,37 +1499,17 @@ declare function runCalibrationEvaluate(analysisJson: {
1091
1499
  analyzedAt: string;
1092
1500
  nodeCount: number;
1093
1501
  issueCount: number;
1094
- }, conversionJson: {
1095
- records: Array<{
1096
- nodeId: string;
1097
- nodePath: string;
1098
- difficulty: string;
1099
- ruleRelatedStruggles: Array<{
1100
- ruleId: string;
1101
- description: string;
1102
- actualImpact: string;
1103
- }>;
1104
- uncoveredStruggles: Array<{
1105
- description: string;
1106
- suggestedCategory: string;
1107
- estimatedImpact: string;
1108
- }>;
1109
- }>;
1110
- skippedNodeIds: string[];
1111
- }, ruleScores: Record<string, {
1502
+ }, conversionJson: Record<string, unknown>, ruleScores: Record<string, {
1112
1503
  score: number;
1113
1504
  severity: string;
1114
- }>): {
1505
+ }>, options?: {
1506
+ collectEvidence?: boolean | undefined;
1507
+ fixtureName?: string | undefined;
1508
+ }): {
1115
1509
  evaluationOutput: EvaluationAgentOutput;
1116
1510
  tuningOutput: TuningAgentOutput;
1117
1511
  report: string;
1118
1512
  };
1119
- /**
1120
- * Run the full calibration pipeline
1121
- *
1122
- * Sequence: validate -> load file -> analysis -> node selection -> conversion -> evaluation -> tuning -> report
1123
- */
1124
- declare function runCalibration(config: CalibrationConfig, executor: ConversionExecutor, options?: CalibrationRunOptions): Promise<CalibrationRunResult>;
1125
1513
 
1126
1514
  interface ActivityStep {
1127
1515
  step: string;
@@ -1132,17 +1520,17 @@ interface ActivityStep {
1132
1520
  declare class ActivityLogger {
1133
1521
  private logPath;
1134
1522
  private initialized;
1135
- constructor(fixturePath?: string, logDir?: string);
1523
+ constructor(runDir: string);
1136
1524
  /**
1137
1525
  * Ensure the log directory and file header exist
1138
1526
  */
1139
1527
  private ensureInitialized;
1140
1528
  /**
1141
- * Log a pipeline step
1529
+ * Log a pipeline step as a JSON Lines entry
1142
1530
  */
1143
1531
  logStep(activity: ActivityStep): Promise<void>;
1144
1532
  /**
1145
- * Log a summary at pipeline completion
1533
+ * Log a summary at pipeline completion as a JSON Lines entry
1146
1534
  */
1147
1535
  logSummary(summary: {
1148
1536
  totalDurationMs: number;
@@ -1155,4 +1543,4 @@ declare class ActivityLogger {
1155
1543
  getLogPath(): string;
1156
1544
  }
1157
1545
 
1158
- 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 };