@usefragments/core 1.10.2 → 1.11.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.
Files changed (126) hide show
  1. package/dist/{chunk-MZ4SW3TP.js → chunk-3IOWHECM.js} +8 -1
  2. package/dist/{chunk-MZ4SW3TP.js.map → chunk-3IOWHECM.js.map} +1 -1
  3. package/dist/chunk-7ULGH74M.js +66 -0
  4. package/dist/chunk-7ULGH74M.js.map +1 -0
  5. package/dist/{chunk-YF65VYRY.js → chunk-ML5S6QNU.js} +191 -169
  6. package/dist/chunk-ML5S6QNU.js.map +1 -0
  7. package/dist/chunk-PWIJMOI4.js +202 -0
  8. package/dist/chunk-PWIJMOI4.js.map +1 -0
  9. package/dist/{chunk-XN3LSDPY.js → chunk-RPSEABY3.js} +622 -344
  10. package/dist/chunk-RPSEABY3.js.map +1 -0
  11. package/dist/chunk-RYFULE43.js +578 -0
  12. package/dist/chunk-RYFULE43.js.map +1 -0
  13. package/dist/codes/index.d.ts +2 -2
  14. package/dist/codes/index.js +3 -2
  15. package/dist/compiled-types/index.d.ts +327 -2
  16. package/dist/compiled-types/index.js +1 -1
  17. package/dist/generate/index.d.ts +3 -2
  18. package/dist/{governance-CLk_wkP9.d.ts → governance-BAsy1k2H.d.ts} +472 -513
  19. package/dist/governance-telemetry.d.ts +6 -0
  20. package/dist/governance-telemetry.js +1 -1
  21. package/dist/{index-_sxhUNqx.d.ts → index-C8bcXVav.d.ts} +448 -448
  22. package/dist/index.d.ts +9165 -1297
  23. package/dist/index.js +3041 -350
  24. package/dist/index.js.map +1 -1
  25. package/dist/manifest.d.ts +228 -0
  26. package/dist/manifest.js +24 -0
  27. package/dist/manifest.js.map +1 -0
  28. package/dist/preview/index.js +45 -1
  29. package/dist/preview/index.js.map +1 -1
  30. package/dist/preview-runtime.d.ts +1 -2
  31. package/dist/preview-runtime.js +150 -14
  32. package/dist/preview-runtime.js.map +1 -1
  33. package/dist/react-types.d.ts +1 -2
  34. package/dist/registry.d.ts +1412 -203
  35. package/dist/registry.js +30 -3
  36. package/dist/schemas/index.d.ts +1 -1
  37. package/dist/schemas/index.js +3 -2
  38. package/dist/storyAdapter.d.ts +1 -2
  39. package/dist/storyAdapter.js +11 -49
  40. package/dist/storyAdapter.js.map +1 -1
  41. package/dist/test-utils.d.ts +3 -2
  42. package/package.json +8 -2
  43. package/src/__tests__/contract-parser.test.ts +318 -277
  44. package/src/__tests__/preview-runtime-hook.test.tsx +315 -0
  45. package/src/__tests__/preview-runtime.test.tsx +30 -8
  46. package/src/__tests__/schema.test.ts +191 -14
  47. package/src/analysis-plan/analysis-plan-v1.test.ts +320 -0
  48. package/src/analysis-plan/coverage.ts +181 -0
  49. package/src/analysis-plan/digest.ts +141 -0
  50. package/src/analysis-plan/index.ts +34 -0
  51. package/src/analysis-plan/types.ts +207 -0
  52. package/src/codes/__tests__/codes.test.ts +9 -0
  53. package/src/codes/codes.ts +30 -0
  54. package/src/compiled-types/index.ts +640 -39
  55. package/src/compiled-types/parse.test.ts +145 -4
  56. package/src/component-contract.ts +95 -53
  57. package/src/composition.ts +7 -13
  58. package/src/constants.ts +3 -6
  59. package/src/contract/hash.test.ts +20 -0
  60. package/src/contract/hash.ts +66 -9
  61. package/src/contract/index.ts +24 -1
  62. package/src/contract/manifest.test.ts +94 -0
  63. package/src/contract/manifest.ts +68 -0
  64. package/src/contract/preimage.test.ts +219 -1
  65. package/src/contract/preimage.ts +326 -6
  66. package/src/contract/stamp.test.ts +3 -0
  67. package/src/contract/stamp.ts +1 -1
  68. package/src/contract-parser.ts +54 -30
  69. package/src/defineFragment.test.ts +476 -91
  70. package/src/defineFragment.ts +204 -114
  71. package/src/domain-ids.test.ts +52 -0
  72. package/src/domain-ids.ts +106 -0
  73. package/src/evaluation/evaluate.test.ts +522 -0
  74. package/src/evaluation/evaluate.ts +680 -0
  75. package/src/evaluation/evaluation-v2-receipt-v1.test.ts +760 -0
  76. package/src/evaluation/index.ts +58 -0
  77. package/src/evaluation/receipt.ts +753 -0
  78. package/src/evaluation/types.ts +406 -0
  79. package/src/facts/builders.ts +2 -0
  80. package/src/facts/compile.ts +29 -6
  81. package/src/facts/fact-index.ts +13 -3
  82. package/src/facts/fact-integrity-v1.test.ts +172 -0
  83. package/src/facts/facts.test.ts +15 -0
  84. package/src/facts/ids.ts +46 -3
  85. package/src/facts/index.ts +14 -1
  86. package/src/facts/integrity.ts +134 -0
  87. package/src/facts/types.ts +36 -0
  88. package/src/feature-plan/digest.ts +217 -0
  89. package/src/feature-plan/feature-plan-v1.test.ts +529 -0
  90. package/src/feature-plan/index.ts +65 -0
  91. package/src/feature-plan/types.ts +628 -0
  92. package/src/governance-integrity.test.ts +1 -0
  93. package/src/governance-integrity.ts +5 -3
  94. package/src/governance-telemetry.ts +8 -0
  95. package/src/governance.ts +52 -8
  96. package/src/index.ts +299 -37
  97. package/src/preview/validation.test.ts +62 -0
  98. package/src/preview/validation.ts +48 -2
  99. package/src/preview-runtime.tsx +227 -20
  100. package/src/registry-install-plan.ts +200 -109
  101. package/src/registry-shards.test.ts +263 -0
  102. package/src/registry.ts +237 -0
  103. package/src/repository-binding.test.ts +50 -0
  104. package/src/repository-binding.ts +96 -0
  105. package/src/rules/families.test.ts +36 -0
  106. package/src/rules/finding.ts +7 -2
  107. package/src/rules/index.ts +17 -1
  108. package/src/rules/rule-config.test.ts +66 -0
  109. package/src/rules/rule-config.ts +73 -0
  110. package/src/rules/rules.test.ts +26 -0
  111. package/src/rules/tokens-css-vars-must-be-defined.test.ts +51 -2
  112. package/src/rules/tokens-css-vars-must-be-defined.ts +34 -1
  113. package/src/schema.ts +293 -113
  114. package/src/schemas/index.ts +1 -1
  115. package/src/storyAdapter.test.ts +68 -12
  116. package/src/storyAdapter.ts +44 -75
  117. package/src/types.ts +258 -37
  118. package/dist/chunk-RANPUC6C.js +0 -72
  119. package/dist/chunk-RANPUC6C.js.map +0 -1
  120. package/dist/chunk-XN3LSDPY.js.map +0 -1
  121. package/dist/chunk-YF65VYRY.js.map +0 -1
  122. package/src/fragment-types.ts +0 -214
  123. package/src/react-create-element.test.ts +0 -22
  124. package/src/react-create-element.ts +0 -12
  125. package/src/storyFilters.test.ts +0 -350
  126. package/src/storyFilters.ts +0 -253
package/src/types.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import type { ComponentType, ReactNode, JSX } from "react";
2
- import type { GovernanceConfig } from "./governance.js";
2
+ import type {
3
+ ComponentGovernanceBuilder,
4
+ ComponentGovernanceRecord,
5
+ GovernanceConfig,
6
+ } from "./governance.js";
3
7
  import type { InspectConfig } from "./local-canonical.js";
4
8
  import type { Topology } from "./topology/resolve-area.js";
5
9
 
@@ -115,6 +119,19 @@ export interface FragmentUsage {
115
119
  /** When NOT to use this component (with alternatives) */
116
120
  whenNot: string[];
117
121
 
122
+ /** Optional v3 choose-among-alternates guidance carried into the wire document */
123
+ choose?: Record<string, string>;
124
+
125
+ /**
126
+ * Serialized v3 anti-pattern guidance. The source API keeps `good` as JSX;
127
+ * the compiled catalog stores its exact checked source span as a string.
128
+ */
129
+ dont?: Array<{
130
+ reason: string;
131
+ bad: string;
132
+ good: string;
133
+ }>;
134
+
118
135
  /** Additional usage guidelines and best practices */
119
136
  guidelines?: string[];
120
137
 
@@ -288,6 +305,13 @@ export interface FragmentVariant {
288
305
  /** Async loaders to execute before rendering (from Storybook loaders) */
289
306
  loaders?: VariantLoader[];
290
307
 
308
+ /**
309
+ * The adapted Storybook story declared one or more loaders. Their original
310
+ * Storybook context is not available to a Fragment variant, so adapters
311
+ * report presence without attempting to execute them.
312
+ */
313
+ hasUnsupportedStorybookLoaders?: boolean;
314
+
291
315
  /** The args/props used to render this variant (for code generation) */
292
316
  args?: Record<string, unknown>;
293
317
  }
@@ -337,7 +361,7 @@ export interface FragmentContract {
337
361
  */
338
362
  export interface FragmentGenerated {
339
363
  /** Source of this fragment definition */
340
- source: "storybook" | "manual" | "ai" | "extracted" | "merged" | "migrated";
364
+ source: "storybook" | "manual" | "ai" | "scan" | "extracted" | "merged" | "migrated";
341
365
 
342
366
  /** Original source file (e.g., "Button.stories.tsx") */
343
367
  sourceFile?: string;
@@ -455,7 +479,7 @@ export interface FragmentProvenance {
455
479
  confidence?: number;
456
480
 
457
481
  /** Whether the fragment has been verified against source */
458
- verified: boolean;
482
+ verified?: boolean;
459
483
 
460
484
  /** Framework support level */
461
485
  frameworkSupport?: "native" | "manual-only";
@@ -514,6 +538,177 @@ export interface FragmentDefinitionV2<TProps = unknown> {
514
538
  _provenance?: FragmentProvenance;
515
539
  }
516
540
 
541
+ // ---------------------------------------------------------------------------
542
+ // v3 API — component-bound, arity-discriminated authoring
543
+ // ---------------------------------------------------------------------------
544
+
545
+ /**
546
+ * v3 component metadata. `purpose` is the required plain-English line for
547
+ * exec/agent surfaces; intent-search vocabulary lives in `aliases`.
548
+ *
549
+ * @since 3.0
550
+ */
551
+ export interface FragmentMetaV3 {
552
+ name: string;
553
+ purpose: string;
554
+ category: string;
555
+ status?: "stable" | "beta" | "deprecated" | "experimental";
556
+ aliases?: string[];
557
+ tags?: string[];
558
+ since?: string;
559
+ dependencies?: Array<{
560
+ name: string;
561
+ version: string;
562
+ reason?: string;
563
+ }>;
564
+ figma?: string;
565
+ figmaProps?: Record<string, FigmaPropMapping>;
566
+ }
567
+
568
+ /**
569
+ * A single authored state. Display `code` is extracted from the checked JSX
570
+ * AST by the compiler — authored `code` strings are forbidden in v3.
571
+ *
572
+ * @since 3.0
573
+ */
574
+ export interface FragmentStateV3 {
575
+ /** Type-checked JSX (element or render thunk). Never an authored code string. */
576
+ render: Exclude<ReactNode, string | undefined> | ((options?: VariantRenderOptions) => ReactNode);
577
+ note?: string;
578
+ canonical?: boolean;
579
+ /** Forbidden in v3 — display code is extracted from `render`. */
580
+ code?: never;
581
+ }
582
+
583
+ /**
584
+ * Negative example with a type-checked `good` replacement.
585
+ *
586
+ * @since 3.0
587
+ */
588
+ export interface FragmentDontExampleV3 {
589
+ reason: string;
590
+ /** Anti-pattern shown as a string (intentionally not type-checked). */
591
+ bad: string;
592
+ /** Correct replacement — real JSX bound to the component. */
593
+ good: Exclude<ReactNode, string | undefined> | ((options?: VariantRenderOptions) => ReactNode);
594
+ }
595
+
596
+ /**
597
+ * v3 guidance: v2 when/whenNot plus choose/dont.
598
+ *
599
+ * @since 3.0
600
+ */
601
+ export interface FragmentGuidanceV3 {
602
+ when: string[];
603
+ whenNot: string[];
604
+ choose?: Record<string, string>;
605
+ dont?: FragmentDontExampleV3[];
606
+ guidelines?: string[];
607
+ accessibility?: string[];
608
+ }
609
+
610
+ /**
611
+ * Workshop matrix axes. `"auto"` means extraction fills proven prop enums.
612
+ *
613
+ * @since 3.0
614
+ */
615
+ export interface FragmentMatrixV3 {
616
+ axes?: Record<string, "auto" | readonly string[]>;
617
+ forced?: string[];
618
+ worstCase?: Record<string, unknown>;
619
+ }
620
+
621
+ /**
622
+ * Preview runtime hints (providers + visual-diff masks).
623
+ *
624
+ * @since 3.0
625
+ */
626
+ export interface FragmentPreviewV3 {
627
+ providers?: unknown[];
628
+ dynamicRegions?: string[];
629
+ }
630
+
631
+ /**
632
+ * Optional design-tool comparison input.
633
+ *
634
+ * @since 3.0
635
+ */
636
+ export interface FragmentDesignV3 {
637
+ figmaNode?: string;
638
+ }
639
+
640
+ /**
641
+ * Prop annotations annotate extracted truth — they never redefine `type`,
642
+ * `default`, `values`, or `required`.
643
+ *
644
+ * @since 3.0
645
+ */
646
+ export interface PropAnnotation {
647
+ description?: string;
648
+ controlType?: ControlType;
649
+ controlOptions?: Record<string, unknown>;
650
+ visibility?: "public" | "internal" | "hidden";
651
+ constraints?: string[];
652
+ /** Forbidden — derived from component types. */
653
+ type?: never;
654
+ /** Forbidden — derived from component defaults. */
655
+ default?: never;
656
+ values?: never;
657
+ required?: never;
658
+ }
659
+
660
+ /**
661
+ * Freeform authoring annotations (docs notes, review markers). Separate from
662
+ * prop annotations, which live under `props`.
663
+ *
664
+ * @since 3.0
665
+ */
666
+ export interface FragmentAnnotationsV3 {
667
+ notes?: string[];
668
+ review?: string[];
669
+ [key: string]: unknown;
670
+ }
671
+
672
+ type FragmentPropAnnotations<TProps> = [keyof TProps] extends [never]
673
+ ? Record<string, PropAnnotation>
674
+ : { [K in Extract<keyof TProps, string>]?: PropAnnotation };
675
+
676
+ /**
677
+ * v3 definition body — the second argument to
678
+ * `defineFragment(Component, definition)`. The component is bound by arity,
679
+ * not authored inside the body.
680
+ *
681
+ * @since 3.0
682
+ */
683
+ export interface FragmentDefinitionV3Body<TProps = unknown> {
684
+ meta: FragmentMetaV3;
685
+ states: Record<string, FragmentStateV3>;
686
+ guidance: FragmentGuidanceV3;
687
+ matrix?: FragmentMatrixV3;
688
+ preview?: FragmentPreviewV3;
689
+ design?: FragmentDesignV3;
690
+ annotations?: FragmentAnnotationsV3;
691
+ /** Annotate-only prop docs keyed by prop name. */
692
+ props?: FragmentPropAnnotations<TProps>;
693
+ relations?: ComponentRelation[];
694
+ composition?: CompositionMetadata;
695
+ contract?: FragmentContract;
696
+ _provenance?: FragmentProvenance;
697
+ /** Optional governance authoring (resolved when present). */
698
+ govern?: (g: ComponentGovernanceBuilder<TProps>) => ComponentGovernanceRecord[];
699
+ governance?: ComponentGovernanceRecord[];
700
+ }
701
+
702
+ /**
703
+ * Resolved v3 fragment after `defineFragment(Component, body)` binds the
704
+ * component. Governance is always resolved (empty array when none authored).
705
+ *
706
+ * @since 3.0
707
+ */
708
+ export interface FragmentDefinitionV3<TProps = unknown> extends FragmentDefinitionV3Body<TProps> {
709
+ component: FragmentComponent<TProps>;
710
+ governance: ComponentGovernanceRecord[];
711
+ }
517
712
  /**
518
713
  * Registry generation options
519
714
  */
@@ -529,9 +724,64 @@ export interface RegistryOptions {
529
724
 
530
725
  /** Include props in registry (default: false - AI can read TypeScript directly) */
531
726
  includeProps?: boolean;
727
+ }
728
+
729
+ /** Prop entry in the lightweight source registry. */
730
+ export interface RegistryPropEntry {
731
+ type?: string;
732
+ typeKind?:
733
+ | "string"
734
+ | "number"
735
+ | "boolean"
736
+ | "enum"
737
+ | "object"
738
+ | "array"
739
+ | "function"
740
+ | "node"
741
+ | "element"
742
+ | "union"
743
+ | "unknown";
744
+ options?: string[];
745
+ default?: unknown;
746
+ required?: boolean;
747
+ description?: string;
748
+ }
532
749
 
533
- /** Include full fragment data in registry (default: false - reference fragmentPath instead) */
534
- embedFragments?: boolean;
750
+ /** Component entry in the lightweight source registry. */
751
+ export interface RegistryComponentEntry {
752
+ path: string;
753
+ storyPath?: string;
754
+ category?: string;
755
+ props?: Record<string, RegistryPropEntry>;
756
+ exports?: string[];
757
+ dependencies?: string[];
758
+ }
759
+
760
+ /** Minimal component index for quick source navigation. */
761
+ export interface FragmentIndex {
762
+ version: string;
763
+ generatedAt: string;
764
+ components: Record<string, string>;
765
+ categories?: Record<string, string[]>;
766
+ }
767
+
768
+ /** Source registry with resolved component paths and optional extracted props. */
769
+ export interface FragmentRegistry {
770
+ $schema?: string;
771
+ version: string;
772
+ generatedAt: string;
773
+ componentCount: number;
774
+ components: Record<string, RegistryComponentEntry>;
775
+ categories?: Record<string, string[]>;
776
+ }
777
+
778
+ /** Context file options for source-registry generation. */
779
+ export interface FragmentContextOptions {
780
+ format?: "markdown" | "json";
781
+ compact?: boolean;
782
+ include?: {
783
+ props?: boolean;
784
+ };
535
785
  }
536
786
 
537
787
  /**
@@ -661,25 +911,6 @@ export interface SnippetPolicyConfig {
661
911
  allowedExternalModules?: string[];
662
912
  }
663
913
 
664
- /**
665
- * Storybook adapter filtering configuration.
666
- * Controls which Storybook stories are included when generating fragments.
667
- */
668
- export interface StorybookFilterConfig {
669
- /** Glob-style patterns for component names to explicitly exclude */
670
- exclude?: string[];
671
- /** Glob-style patterns for component names to force-include (bypasses all heuristic filters) */
672
- include?: string[];
673
- /** Exclude stories with "Deprecated" in the title (default: true) */
674
- excludeDeprecated?: boolean;
675
- /** Exclude test stories (title ending /test(s) or *.test.stories.* files) (default: true) */
676
- excludeTests?: boolean;
677
- /** Exclude SVG icon components (names matching Svg[A-Z]*) (default: true) */
678
- excludeSvgIcons?: boolean;
679
- /** Exclude sub-components detected by directory structure (default: true) */
680
- excludeSubComponents?: boolean;
681
- }
682
-
683
914
  /**
684
915
  * Theme seed configuration.
685
916
  * The 5 root values that derive 120+ CSS custom properties.
@@ -776,9 +1007,6 @@ export interface FragmentsConfig {
776
1007
  /** Performance budgets: preset name or custom config */
777
1008
  performance?: string | { preset?: string; budgets?: { bundleSize?: number } };
778
1009
 
779
- /** Storybook adapter filtering configuration */
780
- storybook?: StorybookFilterConfig;
781
-
782
1010
  /** Theme seed values for the 5-seed theming system */
783
1011
  theme?: ThemeSeeds;
784
1012
 
@@ -1070,6 +1298,9 @@ export interface VerifyResult {
1070
1298
  // Compiled types — re-exported from ./compiled-types.
1071
1299
  export type {
1072
1300
  CompiledFragment,
1301
+ CompiledFragmentDesign,
1302
+ CompiledFragmentMatrix,
1303
+ CompiledFragmentPreview,
1073
1304
  CompiledBlock,
1074
1305
  CompiledTokenEntry,
1075
1306
  CompiledTokenData,
@@ -1092,13 +1323,3 @@ export interface BlockDefinition {
1092
1323
  code: string;
1093
1324
  tags?: string[];
1094
1325
  }
1095
-
1096
- /**
1097
- * @deprecated Use BlockDefinition instead
1098
- */
1099
- export type RecipeDefinition = BlockDefinition;
1100
-
1101
- /**
1102
- * @deprecated Use CompiledBlock instead
1103
- */
1104
- export type CompiledRecipe = _CompiledBlock;
@@ -1,72 +0,0 @@
1
- // src/compiled-types/index.ts
2
- var CompiledFragmentsFileValidationError = class extends Error {
3
- constructor(source, issues) {
4
- super(`Invalid compiled Fragments catalog at ${source}: ${issues.join("; ")}`);
5
- this.source = source;
6
- this.issues = issues;
7
- this.name = "CompiledFragmentsFileValidationError";
8
- }
9
- source;
10
- issues;
11
- };
12
- function parseCompiledFragmentsFile(input, source = "fragments.json") {
13
- let value = input;
14
- if (typeof input === "string") {
15
- try {
16
- value = JSON.parse(input);
17
- } catch (error) {
18
- throw new CompiledFragmentsFileValidationError(source, [
19
- `invalid JSON (${error instanceof Error ? error.message : String(error)})`
20
- ]);
21
- }
22
- }
23
- const issues = [];
24
- if (!isRecord(value)) {
25
- throw new CompiledFragmentsFileValidationError(source, ["root must be an object"]);
26
- }
27
- if (typeof value.version !== "string" || value.version.length === 0) {
28
- issues.push("version must be a non-empty string");
29
- }
30
- if (typeof value.generatedAt !== "string" || value.generatedAt.length === 0) {
31
- issues.push("generatedAt must be a non-empty string");
32
- }
33
- if (!isRecord(value.fragments)) {
34
- issues.push("fragments must be an object");
35
- } else {
36
- for (const [key, fragment] of Object.entries(value.fragments)) {
37
- validateCompiledFragment(key, fragment, issues);
38
- }
39
- }
40
- if (value.graph !== void 0) {
41
- if (!isRecord(value.graph) || !Array.isArray(value.graph.nodes) || !Array.isArray(value.graph.edges) || !isRecord(value.graph.health)) {
42
- issues.push("graph must contain nodes[], edges[], and health");
43
- }
44
- }
45
- if (issues.length > 0) throw new CompiledFragmentsFileValidationError(source, issues);
46
- return value;
47
- }
48
- function validateCompiledFragment(key, value, issues) {
49
- const path = `fragments.${key}`;
50
- if (!isRecord(value)) {
51
- issues.push(`${path} must be an object`);
52
- return;
53
- }
54
- if (typeof value.filePath !== "string") issues.push(`${path}.filePath must be a string`);
55
- if (!isRecord(value.meta) || typeof value.meta.name !== "string") {
56
- issues.push(`${path}.meta.name must be a string`);
57
- }
58
- if (!isRecord(value.props)) issues.push(`${path}.props must be an object`);
59
- if (!Array.isArray(value.variants)) issues.push(`${path}.variants must be an array`);
60
- if (!isRecord(value.usage) || !Array.isArray(value.usage.when) || !Array.isArray(value.usage.whenNot)) {
61
- issues.push(`${path}.usage must contain when[] and whenNot[]`);
62
- }
63
- }
64
- function isRecord(value) {
65
- return value !== null && typeof value === "object" && !Array.isArray(value);
66
- }
67
-
68
- export {
69
- CompiledFragmentsFileValidationError,
70
- parseCompiledFragmentsFile
71
- };
72
- //# sourceMappingURL=chunk-RANPUC6C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/compiled-types/index.ts"],"sourcesContent":["/**\n * Compiled fragment types — shared between CLI and MCP packages.\n *\n * These are the JSON-serializable types used in fragments.json and consumed\n * by AI agents, MCP servers, and context generators.\n */\n\nimport type { ComponentGovernanceRecord } from '../governance.js';\n\n/**\n * Component metadata\n */\nexport interface FragmentMeta {\n name: string;\n description: string;\n category: string;\n tags?: string[];\n status?: \"stable\" | \"beta\" | \"deprecated\" | \"experimental\";\n since?: string;\n dependencies?: Array<{ name: string; version: string; reason?: string }>;\n figma?: string;\n figmaProps?: Record<string, unknown>;\n}\n\n/**\n * Usage guidelines for AI agents and developers\n */\nexport interface FragmentUsage {\n when: string[];\n whenNot: string[];\n guidelines?: string[];\n accessibility?: string[];\n}\n\n/**\n * Definition for a single prop\n */\nexport interface PropDefinition {\n type: string;\n values?: readonly string[];\n default?: unknown;\n description: string;\n required?: boolean;\n constraints?: string[];\n typeDetails?: Record<string, unknown>;\n controlType?: string;\n controlOptions?: {\n min?: number;\n max?: number;\n step?: number;\n presetColors?: string[];\n };\n}\n\n/**\n * Relationship to another component\n */\nexport interface ComponentRelation {\n component: string;\n relationship: string;\n note: string;\n}\n\n/**\n * Agent-optimized contract metadata\n */\nexport interface FragmentContract {\n propsSummary?: string[];\n a11yRules?: string[];\n bans?: Array<{ pattern: string; message: string }>;\n scenarioTags?: string[];\n /** Per-component performance budget override in bytes (gzipped) */\n performanceBudget?: number;\n /** Sub-component slot metadata for compound components */\n compoundChildren?: Record<string, {\n required?: boolean;\n accepts?: string[];\n description?: string;\n }>;\n /** Canonical JSX usage examples showing how to assemble the component */\n canonicalUsage?: string[];\n}\n\n/**\n * Provenance tracking for generated fragments\n */\nexport interface FragmentGenerated {\n source: \"storybook\" | \"manual\" | \"ai\" | \"extracted\" | \"merged\" | \"migrated\";\n sourceFile?: string;\n /** @deprecated Use provenance.verified instead */\n confidence?: number;\n verified?: boolean;\n timestamp?: string;\n}\n\n/**\n * AI-specific metadata\n */\nexport interface AIMetadata {\n compositionPattern?: \"compound\" | \"simple\" | \"controlled\" | \"wrapper\";\n subComponents?: string[];\n requiredChildren?: string[];\n commonPatterns?: string[];\n}\n\n/**\n * Performance data for a component (from bundle size measurement)\n */\n/**\n * A single import contributing to bundle size\n */\nexport interface ImportEntry {\n /** Resolved file path (relative to project root) */\n path: string;\n /** Bytes contributed to the bundle */\n bytes: number;\n /** Percentage of total bundle size */\n percent: number;\n}\n\nexport interface PerformanceData {\n /** Gzipped bundle size in bytes */\n bundleSize: number;\n /** Raw (minified, not gzipped) bundle size in bytes */\n rawSize: number;\n /** Complexity classification */\n complexity: 'lightweight' | 'moderate' | 'heavy';\n /** Percentage of budget used (0-100+) */\n budgetPercent: number;\n /** Whether the component exceeds its budget */\n overBudget: boolean;\n /** ISO timestamp when measured */\n measuredAt: string;\n /** Top imports by size (largest first) */\n imports?: ImportEntry[];\n}\n\nexport interface ObservedUsageProp {\n name: string;\n kind: 'static' | 'dynamic' | 'spread' | 'jsx' | 'boolean' | 'null';\n value?: string | number | boolean | null;\n}\n\nexport interface ObservedComponentUsage {\n /** Source file path relative to the fragments config root */\n file: string;\n /** 1-indexed source line */\n line: number;\n /** 0-indexed source column */\n column: number;\n props: ObservedUsageProp[];\n parentElement?: string;\n conditional?: boolean;\n}\n\n/**\n * Compiled fragment data (JSON-serializable for AI consumption)\n */\nexport interface CompiledFragment {\n filePath: string;\n meta: FragmentMeta;\n /** Canonical v2 guidance. `usage` is retained for compatibility. */\n guidance?: FragmentUsage;\n usage: FragmentUsage;\n props: Record<string, PropDefinition>;\n /** Normalized component governance records emitted from *.fragment.ts. */\n governance?: ComponentGovernanceRecord[];\n relations?: ComponentRelation[];\n variants: Array<{\n name: string;\n description: string;\n code?: string;\n figma?: string;\n args?: Record<string, unknown>;\n }>;\n contract?: FragmentContract;\n ai?: AIMetadata;\n /** Framework hint from contract, used by preview adapters and Cloud */\n framework?: string;\n /** Top-level compact prop summaries for agent first-pass */\n propsSummary?: string[];\n /** Source file path relative to config root (for contract-sourced fragments) */\n sourcePath?: string;\n /** Named export for preview adapter resolution */\n exportName?: string;\n /** Clean provenance tracking (V2) */\n provenance?: {\n source: string;\n verified: boolean;\n frameworkSupport?: string;\n sourceHash?: string;\n extractedAt?: string;\n };\n /** Component performance data from bundle size measurement */\n performance?: PerformanceData;\n /** Observed JSX call sites captured during `fragments scan` */\n usages?: ObservedComponentUsage[];\n _generated?: FragmentGenerated;\n}\n\n/**\n * Compiled block data (JSON-serializable for AI consumption)\n */\nexport interface CompiledBlock {\n filePath: string;\n name: string;\n description: string;\n category: string;\n components: string[];\n code: string;\n tags?: string[];\n}\n\n/**\n * A single token entry in the compiled output\n */\nexport interface CompiledTokenEntry {\n name: string;\n value?: string;\n description?: string;\n}\n\n/**\n * Compiled token data stored in fragments.json\n */\nexport interface CompiledTokenData {\n prefix: string;\n total: number;\n categories: Record<string, CompiledTokenEntry[]>;\n}\n\n/**\n * Performance summary across all components\n */\nexport interface PerformanceSummary {\n /** Preset name used */\n preset: string;\n /** Budget applied in bytes */\n budget: number;\n /** Total components measured */\n total: number;\n /** Number of components over budget */\n overBudget: number;\n /** Distribution by tier */\n tiers: Record<string, number>;\n}\n\n/**\n * The compiled fragments.json structure\n */\nexport interface CompiledFragmentsFile {\n version: string;\n generatedAt: string;\n /** CLI version that produced this file, used for freshness checks */\n generatorVersion?: string;\n /** Relative source/config inputs used to build this file, used for freshness checks */\n buildInputs?: string[];\n packageName?: string;\n fragments: Record<string, CompiledFragment>;\n blocks?: Record<string, CompiledBlock>;\n tokens?: CompiledTokenData;\n /** Component relationship graph for AI structural queries */\n graph?: import('../graph/types.js').SerializedComponentGraph;\n /** Performance measurement summary */\n performanceSummary?: PerformanceSummary;\n /** @deprecated Use blocks instead */\n recipes?: Record<string, CompiledBlock>;\n}\n\nexport class CompiledFragmentsFileValidationError extends Error {\n constructor(\n readonly source: string,\n readonly issues: string[]\n ) {\n super(`Invalid compiled Fragments catalog at ${source}: ${issues.join(\"; \")}`);\n this.name = \"CompiledFragmentsFileValidationError\";\n }\n}\n\nexport function parseCompiledFragmentsFile(\n input: string | unknown,\n source = \"fragments.json\"\n): CompiledFragmentsFile {\n let value: unknown = input;\n if (typeof input === \"string\") {\n try {\n value = JSON.parse(input);\n } catch (error) {\n throw new CompiledFragmentsFileValidationError(source, [\n `invalid JSON (${error instanceof Error ? error.message : String(error)})`,\n ]);\n }\n }\n\n const issues: string[] = [];\n if (!isRecord(value)) {\n throw new CompiledFragmentsFileValidationError(source, [\"root must be an object\"]);\n }\n if (typeof value.version !== \"string\" || value.version.length === 0) {\n issues.push(\"version must be a non-empty string\");\n }\n if (typeof value.generatedAt !== \"string\" || value.generatedAt.length === 0) {\n issues.push(\"generatedAt must be a non-empty string\");\n }\n if (!isRecord(value.fragments)) {\n issues.push(\"fragments must be an object\");\n } else {\n for (const [key, fragment] of Object.entries(value.fragments)) {\n validateCompiledFragment(key, fragment, issues);\n }\n }\n if (value.graph !== undefined) {\n if (\n !isRecord(value.graph) ||\n !Array.isArray(value.graph.nodes) ||\n !Array.isArray(value.graph.edges) ||\n !isRecord(value.graph.health)\n ) {\n issues.push(\"graph must contain nodes[], edges[], and health\");\n }\n }\n if (issues.length > 0) throw new CompiledFragmentsFileValidationError(source, issues);\n return value as unknown as CompiledFragmentsFile;\n}\n\nfunction validateCompiledFragment(key: string, value: unknown, issues: string[]): void {\n const path = `fragments.${key}`;\n if (!isRecord(value)) {\n issues.push(`${path} must be an object`);\n return;\n }\n if (typeof value.filePath !== \"string\") issues.push(`${path}.filePath must be a string`);\n if (!isRecord(value.meta) || typeof value.meta.name !== \"string\") {\n issues.push(`${path}.meta.name must be a string`);\n }\n if (!isRecord(value.props)) issues.push(`${path}.props must be an object`);\n if (!Array.isArray(value.variants)) issues.push(`${path}.variants must be an array`);\n if (\n !isRecord(value.usage) ||\n !Array.isArray(value.usage.when) ||\n !Array.isArray(value.usage.whenNot)\n ) {\n issues.push(`${path}.usage must contain when[] and whenNot[]`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Theme identifier\n */\nexport type Theme = \"light\" | \"dark\";\n\n/**\n * Verification result\n */\nexport interface VerifyResult {\n verdict: \"pass\" | \"fail\" | \"error\";\n matches: boolean;\n diffPercentage: number;\n screenshot: string;\n baseline: string;\n diffImage?: string;\n notes: string[];\n error?: string;\n timing: {\n renderMs: number;\n captureMs: number;\n diffMs: number;\n totalMs: number;\n };\n}\n"],"mappings":";AA6QO,IAAM,uCAAN,cAAmD,MAAM;AAAA,EAC9D,YACW,QACA,QACT;AACA,UAAM,yCAAyC,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,EAAE;AAHpE;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EALW;AAAA,EACA;AAKb;AAEO,SAAS,2BACd,OACA,SAAS,kBACc;AACvB,MAAI,QAAiB;AACrB,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,cAAQ,KAAK,MAAM,KAAK;AAAA,IAC1B,SAAS,OAAO;AACd,YAAM,IAAI,qCAAqC,QAAQ;AAAA,QACrD,iBAAiB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,UAAM,IAAI,qCAAqC,QAAQ,CAAC,wBAAwB,CAAC;AAAA,EACnF;AACA,MAAI,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,WAAW,GAAG;AACnE,WAAO,KAAK,oCAAoC;AAAA,EAClD;AACA,MAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,YAAY,WAAW,GAAG;AAC3E,WAAO,KAAK,wCAAwC;AAAA,EACtD;AACA,MAAI,CAAC,SAAS,MAAM,SAAS,GAAG;AAC9B,WAAO,KAAK,6BAA6B;AAAA,EAC3C,OAAO;AACL,eAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,SAAS,GAAG;AAC7D,+BAAyB,KAAK,UAAU,MAAM;AAAA,IAChD;AAAA,EACF;AACA,MAAI,MAAM,UAAU,QAAW;AAC7B,QACE,CAAC,SAAS,MAAM,KAAK,KACrB,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,KAChC,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,KAChC,CAAC,SAAS,MAAM,MAAM,MAAM,GAC5B;AACA,aAAO,KAAK,iDAAiD;AAAA,IAC/D;AAAA,EACF;AACA,MAAI,OAAO,SAAS,EAAG,OAAM,IAAI,qCAAqC,QAAQ,MAAM;AACpF,SAAO;AACT;AAEA,SAAS,yBAAyB,KAAa,OAAgB,QAAwB;AACrF,QAAM,OAAO,aAAa,GAAG;AAC7B,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC;AAAA,EACF;AACA,MAAI,OAAO,MAAM,aAAa,SAAU,QAAO,KAAK,GAAG,IAAI,4BAA4B;AACvF,MAAI,CAAC,SAAS,MAAM,IAAI,KAAK,OAAO,MAAM,KAAK,SAAS,UAAU;AAChE,WAAO,KAAK,GAAG,IAAI,6BAA6B;AAAA,EAClD;AACA,MAAI,CAAC,SAAS,MAAM,KAAK,EAAG,QAAO,KAAK,GAAG,IAAI,0BAA0B;AACzE,MAAI,CAAC,MAAM,QAAQ,MAAM,QAAQ,EAAG,QAAO,KAAK,GAAG,IAAI,4BAA4B;AACnF,MACE,CAAC,SAAS,MAAM,KAAK,KACrB,CAAC,MAAM,QAAQ,MAAM,MAAM,IAAI,KAC/B,CAAC,MAAM,QAAQ,MAAM,MAAM,OAAO,GAClC;AACA,WAAO,KAAK,GAAG,IAAI,0CAA0C;AAAA,EAC/D;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;","names":[]}