@fragments-sdk/cli 0.15.0 → 0.15.2

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 (120) hide show
  1. package/dist/{ai-client-I6MDWNYA.js → ai-client-LSLQGOMM.js} +1 -2
  2. package/dist/bin.js +565 -548
  3. package/dist/bin.js.map +1 -1
  4. package/dist/chunk-5JF26E55.js +1255 -0
  5. package/dist/chunk-5JF26E55.js.map +1 -0
  6. package/dist/{chunk-XJQ5BIWI.js → chunk-6SQPP47U.js} +30 -314
  7. package/dist/chunk-6SQPP47U.js.map +1 -0
  8. package/dist/{chunk-65WSVDV5.js → chunk-HQ6A6DTV.js} +1386 -1097
  9. package/dist/chunk-HQ6A6DTV.js.map +1 -0
  10. package/dist/chunk-MHIBEEW4.js +511 -0
  11. package/dist/chunk-MHIBEEW4.js.map +1 -0
  12. package/dist/{chunk-CZD3AD4Q.js → chunk-ONUP6Z4W.js} +17 -6
  13. package/dist/chunk-ONUP6Z4W.js.map +1 -0
  14. package/dist/{codebase-scanner-VOTPXRYW.js → codebase-scanner-MQHUZC2G.js} +1 -2
  15. package/dist/{converter-JLINP7CJ.js → converter-7XM3Y6NJ.js} +1 -2
  16. package/dist/{converter-JLINP7CJ.js.map → converter-7XM3Y6NJ.js.map} +1 -1
  17. package/dist/core/index.js +0 -1
  18. package/dist/create-JVAU3YKN.js +852 -0
  19. package/dist/create-JVAU3YKN.js.map +1 -0
  20. package/dist/doctor-BDPMYYE6.js +385 -0
  21. package/dist/doctor-BDPMYYE6.js.map +1 -0
  22. package/dist/{generate-A4FP5426.js → generate-PVOLUAAC.js} +3 -4
  23. package/dist/{generate-A4FP5426.js.map → generate-PVOLUAAC.js.map} +1 -1
  24. package/dist/{govern-scan-UCBZR6D6.js → govern-scan-OYFZYOQW.js} +142 -9
  25. package/dist/govern-scan-OYFZYOQW.js.map +1 -0
  26. package/dist/index.d.ts +2 -22
  27. package/dist/index.js +8 -7
  28. package/dist/index.js.map +1 -1
  29. package/dist/{init-HGSM35XA.js → init-SSGUSP7Z.js} +3 -4
  30. package/dist/{init-HGSM35XA.js.map → init-SSGUSP7Z.js.map} +1 -1
  31. package/dist/{init-cloud-MQ6GRJAZ.js → init-cloud-3DNKPWFB.js} +29 -4
  32. package/dist/{init-cloud-MQ6GRJAZ.js.map → init-cloud-3DNKPWFB.js.map} +1 -1
  33. package/dist/mcp-bin.js +1 -2
  34. package/dist/mcp-bin.js.map +1 -1
  35. package/dist/node-37AUE74M.js +65 -0
  36. package/dist/push-contracts-WY32TFP6.js +84 -0
  37. package/dist/push-contracts-WY32TFP6.js.map +1 -0
  38. package/dist/{scan-VNNKACG2.js → scan-PKSYSTRR.js} +5 -5
  39. package/dist/{scan-generate-TWRHNU5M.js → scan-generate-VY27PIOX.js} +8 -9
  40. package/dist/scan-generate-VY27PIOX.js.map +1 -0
  41. package/dist/{scanner-7LAZYPWZ.js → scanner-4KZNOXAK.js} +1 -2
  42. package/dist/{service-FHQU7YS7.js → service-QJGWUIVL.js} +16 -9
  43. package/dist/{snapshot-KQEQ6XHL.js → snapshot-WIJMEIFT.js} +1 -2
  44. package/dist/{snapshot-KQEQ6XHL.js.map → snapshot-WIJMEIFT.js.map} +1 -1
  45. package/dist/{static-viewer-63PG6FWY.js → static-viewer-7QIBQZRC.js} +1 -2
  46. package/dist/{test-UQYUCZIS.js → test-64Z5BKBA.js} +2 -3
  47. package/dist/{test-UQYUCZIS.js.map → test-64Z5BKBA.js.map} +1 -1
  48. package/dist/token-normalizer-TEPOVBPV.js +312 -0
  49. package/dist/token-normalizer-TEPOVBPV.js.map +1 -0
  50. package/dist/token-parser-32KOIOFN.js +22 -0
  51. package/dist/token-parser-32KOIOFN.js.map +1 -0
  52. package/dist/{tokens-6GYKDV6U.js → tokens-NZWFQIAB.js} +7 -7
  53. package/dist/{tokens-generate-VTZV5EEW.js → tokens-generate-5JQSJ27E.js} +1 -2
  54. package/dist/{tokens-generate-VTZV5EEW.js.map → tokens-generate-5JQSJ27E.js.map} +1 -1
  55. package/dist/tokens-push-HY3KO36V.js +148 -0
  56. package/dist/tokens-push-HY3KO36V.js.map +1 -0
  57. package/package.json +18 -16
  58. package/src/bin.ts +94 -1
  59. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
  60. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
  61. package/src/commands/__tests__/build-freshness.test.ts +231 -0
  62. package/src/commands/__tests__/create.test.ts +71 -0
  63. package/src/commands/__tests__/drift-sync.test.ts +1 -1
  64. package/src/commands/__tests__/govern.test.ts +258 -0
  65. package/src/commands/__tests__/init.test.ts +9 -1
  66. package/src/commands/__tests__/scan-generate.test.ts +1 -1
  67. package/src/commands/build.ts +54 -1
  68. package/src/commands/context.ts +1 -1
  69. package/src/commands/create.ts +590 -0
  70. package/src/commands/doctor.ts +3 -2
  71. package/src/commands/govern-scan.ts +187 -8
  72. package/src/commands/govern.ts +65 -2
  73. package/src/commands/init-cloud.ts +32 -4
  74. package/src/commands/push-contracts.ts +112 -0
  75. package/src/commands/scan-generate.ts +1 -1
  76. package/src/commands/scan.ts +13 -0
  77. package/src/commands/sync.ts +2 -2
  78. package/src/commands/tokens-push.ts +199 -0
  79. package/src/core/__tests__/token-resolver.test.ts +1 -1
  80. package/src/core/component-extractor.test.ts +1 -1
  81. package/src/core/drift-verifier.ts +1 -1
  82. package/src/core/extractor-adapter.ts +1 -1
  83. package/src/index.ts +3 -3
  84. package/src/migrate/fragment-to-contract.ts +2 -2
  85. package/src/service/index.ts +8 -0
  86. package/src/service/tailwind-v4-parser.ts +314 -0
  87. package/src/service/token-parser.ts +56 -0
  88. package/src/setup.ts +10 -39
  89. package/src/theme/__tests__/component-contrast.test.ts +2 -2
  90. package/src/theme/__tests__/serializer.test.ts +1 -1
  91. package/src/theme/generator.ts +30 -1
  92. package/src/theme/schema.ts +8 -0
  93. package/src/theme/serializer.ts +13 -9
  94. package/src/theme/types.ts +8 -0
  95. package/src/validators.ts +1 -2
  96. package/dist/chunk-65WSVDV5.js.map +0 -1
  97. package/dist/chunk-7WHVW72L.js +0 -2664
  98. package/dist/chunk-7WHVW72L.js.map +0 -1
  99. package/dist/chunk-CZD3AD4Q.js.map +0 -1
  100. package/dist/chunk-MN3TJ3D5.js +0 -695
  101. package/dist/chunk-MN3TJ3D5.js.map +0 -1
  102. package/dist/chunk-XJQ5BIWI.js.map +0 -1
  103. package/dist/chunk-Z7EY4VHE.js +0 -50
  104. package/dist/govern-scan-UCBZR6D6.js.map +0 -1
  105. package/dist/sass.node-4XJK6YBF.js +0 -130708
  106. package/dist/sass.node-4XJK6YBF.js.map +0 -1
  107. package/dist/scan-generate-TWRHNU5M.js.map +0 -1
  108. package/src/build.ts +0 -736
  109. package/src/core/auto-props.ts +0 -464
  110. package/src/core/component-extractor.ts +0 -1121
  111. package/src/core/token-resolver.ts +0 -155
  112. package/src/viewer/preview-adapter.ts +0 -116
  113. /package/dist/{ai-client-I6MDWNYA.js.map → ai-client-LSLQGOMM.js.map} +0 -0
  114. /package/dist/{chunk-Z7EY4VHE.js.map → codebase-scanner-MQHUZC2G.js.map} +0 -0
  115. /package/dist/{codebase-scanner-VOTPXRYW.js.map → node-37AUE74M.js.map} +0 -0
  116. /package/dist/{scan-VNNKACG2.js.map → scan-PKSYSTRR.js.map} +0 -0
  117. /package/dist/{scanner-7LAZYPWZ.js.map → scanner-4KZNOXAK.js.map} +0 -0
  118. /package/dist/{service-FHQU7YS7.js.map → service-QJGWUIVL.js.map} +0 -0
  119. /package/dist/{static-viewer-63PG6FWY.js.map → static-viewer-7QIBQZRC.js.map} +0 -0
  120. /package/dist/{tokens-6GYKDV6U.js.map → tokens-NZWFQIAB.js.map} +0 -0
package/dist/bin.js CHANGED
@@ -1,43 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
3
+ import {
4
+ setup
5
+ } from "./chunk-BJE3425I.js";
3
6
  import {
4
7
  scan
5
- } from "./chunk-CZD3AD4Q.js";
8
+ } from "./chunk-ONUP6Z4W.js";
6
9
  import {
7
10
  createAIClient,
8
11
  detectProvider,
9
12
  getApiKey
10
13
  } from "./chunk-SXTKFDCR.js";
11
14
  import {
12
- setup
13
- } from "./chunk-BJE3425I.js";
14
- import {
15
- buildFragments,
16
- buildFragmentsDir,
17
- measureBundleSizes,
18
- resolveComponentSourcePath,
19
15
  runAnalyzeCommand,
20
16
  runDiffCommand,
21
17
  runScreenshotCommand,
22
- toPerformanceData,
23
18
  validateAll,
24
19
  validateCoverage,
25
20
  validateDrift,
26
21
  validateSchema,
27
22
  validateSnippets
28
- } from "./chunk-7WHVW72L.js";
29
- import {
30
- createComponentExtractor
31
- } from "./chunk-MN3TJ3D5.js";
32
- import {
33
- discoverFragmentFiles,
34
- loadConfig,
35
- loadFragmentFile,
36
- parseFragmentFile
37
- } from "./chunk-65WSVDV5.js";
38
- import {
39
- projectFields
40
- } from "./chunk-T47OLCSF.js";
23
+ } from "./chunk-5JF26E55.js";
41
24
  import {
42
25
  FigmaClient,
43
26
  StorageManager,
@@ -51,28 +34,38 @@ import {
51
34
  parseAllStories,
52
35
  renderAllComponentVariants,
53
36
  shutdownSharedPool
54
- } from "./chunk-XJQ5BIWI.js";
37
+ } from "./chunk-6SQPP47U.js";
38
+ import {
39
+ projectFields
40
+ } from "./chunk-T47OLCSF.js";
55
41
  import "./chunk-D2CDBRNU.js";
42
+ import {
43
+ discoverFragmentFiles,
44
+ loadConfig,
45
+ loadFragmentFile,
46
+ parseFragmentFile
47
+ } from "./chunk-HQ6A6DTV.js";
56
48
  import {
57
49
  BRAND,
58
50
  budgetBar,
51
+ classifyComplexity,
59
52
  formatBytes,
60
53
  generateContext,
61
54
  resolvePerformanceConfig
62
55
  } from "./chunk-32LIWN2P.js";
56
+ import "./chunk-MHIBEEW4.js";
63
57
  import {
64
58
  getScanStats,
65
59
  scanCodebase
66
60
  } from "./chunk-QCN35LJU.js";
67
61
  import "./chunk-7DZC4YEV.js";
68
- import "./chunk-Z7EY4VHE.js";
69
62
 
70
63
  // src/bin.ts
71
64
  import { Command } from "commander";
72
- import pc26 from "picocolors";
65
+ import pc25 from "picocolors";
73
66
  import { readFileSync } from "fs";
74
67
  import { fileURLToPath } from "url";
75
- import { dirname as dirname5, join as join11 } from "path";
68
+ import { dirname as dirname6, join as join11 } from "path";
76
69
 
77
70
  // src/commands/validate.ts
78
71
  import pc from "picocolors";
@@ -168,6 +161,7 @@ function printDriftReport(result) {
168
161
 
169
162
  // src/commands/build.ts
170
163
  import pc2 from "picocolors";
164
+ import { buildFragments, buildFragmentsDir, getFragmentsJsonStatus } from "@fragments-sdk/compiler";
171
165
  async function build(options = {}) {
172
166
  if (options.fromSource) {
173
167
  console.log(pc2.cyan(`
@@ -202,6 +196,50 @@ ${BRAND.name} Build
202
196
  let registryPath;
203
197
  let contextPath;
204
198
  if (!options.registryOnly) {
199
+ const status = await getFragmentsJsonStatus(config, configDir, {
200
+ output: config.outFile,
201
+ configPath: options.config
202
+ });
203
+ if (options.check) {
204
+ if (status.missing || status.stale) {
205
+ const message = status.missing ? `${BRAND.outFile} is missing` : `${BRAND.outFile} is stale${status.reason ? ` (${status.reason})` : ""}`;
206
+ console.log(pc2.red(`\u2717 ${message}
207
+ `));
208
+ errors.push({
209
+ file: status.outputPath,
210
+ error: message
211
+ });
212
+ return {
213
+ success: false,
214
+ outputPath: status.outputPath,
215
+ errors
216
+ };
217
+ }
218
+ console.log(pc2.green(`\u2713 ${BRAND.outFile} is up to date`));
219
+ console.log(pc2.dim(` Output: ${status.outputPath}
220
+ `));
221
+ if (!options.registry) {
222
+ return {
223
+ success: true,
224
+ fragmentCount: Object.keys(status.data?.fragments ?? {}).length,
225
+ outputPath: status.outputPath,
226
+ errors
227
+ };
228
+ }
229
+ }
230
+ if (options.ifNeeded && !status.missing && !status.stale) {
231
+ console.log(pc2.green(`\u2713 ${BRAND.outFile} is up to date`));
232
+ console.log(pc2.dim(` Output: ${status.outputPath}
233
+ `));
234
+ if (!options.registry) {
235
+ return {
236
+ success: true,
237
+ fragmentCount: Object.keys(status.data?.fragments ?? {}).length,
238
+ outputPath: status.outputPath,
239
+ errors
240
+ };
241
+ }
242
+ }
205
243
  console.log(pc2.dim("Compiling fragments...\n"));
206
244
  const result = await buildFragments(config, configDir);
207
245
  if (result.errors.length > 0) {
@@ -277,6 +315,7 @@ ${BRAND.name} Build
277
315
  import { readFile } from "fs/promises";
278
316
  import { resolve } from "path";
279
317
  import pc3 from "picocolors";
318
+ import { buildFragments as buildFragments2 } from "@fragments-sdk/compiler";
280
319
  async function context(options = {}) {
281
320
  const {
282
321
  format = "markdown",
@@ -293,7 +332,7 @@ async function context(options = {}) {
293
332
  fragments = Object.values(data.fragments);
294
333
  } else {
295
334
  const { config, configDir } = await loadConfig(options.config);
296
- const result = await buildFragments(config, configDir);
335
+ const result = await buildFragments2(config, configDir);
297
336
  if (result.errors.length > 0 && result.fragmentCount === 0) {
298
337
  console.error(pc3.red("Error: No fragments found. Run `fragments build` first or fix errors."));
299
338
  return { success: false, tokenEstimate: 0 };
@@ -5488,13 +5527,259 @@ ${BRAND.name} Components (${fragments.length})
5488
5527
  // src/commands/perf.ts
5489
5528
  import pc21 from "picocolors";
5490
5529
  import { readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
5491
- import { resolve as resolve10 } from "path";
5530
+ import { resolve as resolve11 } from "path";
5531
+
5532
+ // src/core/bundle-measurer.ts
5533
+ import { build as build2 } from "esbuild";
5534
+ import { gzipSync } from "zlib";
5535
+ import { resolve as resolve10, dirname as dirname4, join as join10, basename } from "path";
5536
+ import { existsSync as existsSync3 } from "fs";
5537
+ function resolveEntryPoint(fragmentFilePath, configDir) {
5538
+ const absPath = resolve10(configDir, fragmentFilePath);
5539
+ const dir = dirname4(absPath);
5540
+ const candidates = ["index.tsx", "index.ts", "index.jsx", "index.js"];
5541
+ for (const candidate of candidates) {
5542
+ const path = join10(dir, candidate);
5543
+ if (existsSync3(path)) return path;
5544
+ }
5545
+ return null;
5546
+ }
5547
+ function labelForPath(filePath) {
5548
+ const lastNmIdx = filePath.lastIndexOf("node_modules/");
5549
+ if (lastNmIdx >= 0) {
5550
+ const afterNm = filePath.slice(lastNmIdx + "node_modules/".length);
5551
+ if (afterNm.startsWith("@")) {
5552
+ const parts = afterNm.split("/");
5553
+ return parts.slice(0, 2).join("/");
5554
+ }
5555
+ return afterNm.split("/")[0];
5556
+ }
5557
+ const componentsIdx = filePath.indexOf("components/");
5558
+ if (componentsIdx >= 0) {
5559
+ const afterComponents = filePath.slice(componentsIdx + "components/".length);
5560
+ const componentName = afterComponents.split("/")[0];
5561
+ return componentName;
5562
+ }
5563
+ const srcIdx = filePath.indexOf("src/");
5564
+ if (srcIdx >= 0) return filePath.slice(srcIdx);
5565
+ return filePath;
5566
+ }
5567
+ function groupImportsByDirectDep(metafile, entryPoint) {
5568
+ const inputs = metafile.inputs;
5569
+ const outputKey = Object.keys(metafile.outputs)[0];
5570
+ const outputMeta = outputKey ? metafile.outputs[outputKey] : void 0;
5571
+ if (!outputMeta?.inputs) return [];
5572
+ const bytesMap = /* @__PURE__ */ new Map();
5573
+ for (const [path, info] of Object.entries(outputMeta.inputs)) {
5574
+ if (info.bytesInOutput > 0) {
5575
+ bytesMap.set(path, info.bytesInOutput);
5576
+ }
5577
+ }
5578
+ let entryKey;
5579
+ for (const key of Object.keys(inputs)) {
5580
+ if (key === entryPoint || entryPoint.endsWith(key) || key.endsWith(basename(entryPoint))) {
5581
+ const entryDir = dirname4(entryPoint);
5582
+ if (key.includes(basename(entryDir))) {
5583
+ entryKey = key;
5584
+ break;
5585
+ }
5586
+ }
5587
+ }
5588
+ if (!entryKey) {
5589
+ const entryBasename = basename(dirname4(entryPoint));
5590
+ for (const key of Object.keys(inputs)) {
5591
+ if (key.includes(`/${entryBasename}/index.`)) {
5592
+ entryKey = key;
5593
+ break;
5594
+ }
5595
+ }
5596
+ }
5597
+ if (!entryKey || !inputs[entryKey]) {
5598
+ return groupByPackage(bytesMap);
5599
+ }
5600
+ const directImports = inputs[entryKey].imports.map((imp) => imp.path).filter((p) => inputs[p]);
5601
+ const claimed = /* @__PURE__ */ new Set();
5602
+ claimed.add(entryKey);
5603
+ const groupMap = /* @__PURE__ */ new Map();
5604
+ for (const directPath of directImports) {
5605
+ if (claimed.has(directPath)) continue;
5606
+ const queue = [directPath];
5607
+ const reachable = /* @__PURE__ */ new Set();
5608
+ while (queue.length > 0) {
5609
+ const current = queue.pop();
5610
+ if (reachable.has(current) || claimed.has(current)) continue;
5611
+ reachable.add(current);
5612
+ claimed.add(current);
5613
+ const entry = inputs[current];
5614
+ if (entry?.imports) {
5615
+ for (const imp of entry.imports) {
5616
+ if (inputs[imp.path] && !claimed.has(imp.path)) {
5617
+ queue.push(imp.path);
5618
+ }
5619
+ }
5620
+ }
5621
+ }
5622
+ let totalBytes = 0;
5623
+ for (const path of reachable) {
5624
+ totalBytes += bytesMap.get(path) ?? 0;
5625
+ }
5626
+ if (totalBytes > 0) {
5627
+ const label = labelForPath(directPath);
5628
+ const existing = groupMap.get(label);
5629
+ if (existing) {
5630
+ existing.bytes += totalBytes;
5631
+ } else {
5632
+ const entry = { path: label, bytes: totalBytes };
5633
+ groupMap.set(label, entry);
5634
+ }
5635
+ }
5636
+ }
5637
+ const entryLabel = labelForPath(entryKey);
5638
+ const selfLabel = entryLabel + " (self)";
5639
+ let selfBytes = bytesMap.get(entryKey) ?? 0;
5640
+ const siblingGroup = groupMap.get(entryLabel);
5641
+ if (siblingGroup) {
5642
+ selfBytes += siblingGroup.bytes;
5643
+ groupMap.delete(entryLabel);
5644
+ }
5645
+ if (selfBytes > 0) {
5646
+ groupMap.set(selfLabel, { path: selfLabel, bytes: selfBytes });
5647
+ }
5648
+ let unclaimedBytes = 0;
5649
+ for (const [path, bytes] of bytesMap) {
5650
+ if (!claimed.has(path)) unclaimedBytes += bytes;
5651
+ }
5652
+ if (unclaimedBytes > 0) {
5653
+ groupMap.set("(other)", { path: "(other)", bytes: unclaimedBytes });
5654
+ }
5655
+ return [...groupMap.values()].sort((a, b) => b.bytes - a.bytes);
5656
+ }
5657
+ function groupByPackage(bytesMap) {
5658
+ const groups = /* @__PURE__ */ new Map();
5659
+ for (const [path, bytes] of bytesMap) {
5660
+ const label = labelForPath(path);
5661
+ const key = label.includes("/") && !label.startsWith("components/") ? label.split("/").slice(0, label.startsWith("@") ? 2 : 1).join("/") : label;
5662
+ groups.set(key, (groups.get(key) ?? 0) + bytes);
5663
+ }
5664
+ return [...groups.entries()].map(([path, bytes]) => ({ path, bytes })).sort((a, b) => b.bytes - a.bytes);
5665
+ }
5666
+ async function measureSingleComponent(entryPoint, name) {
5667
+ const result = await build2({
5668
+ entryPoints: [entryPoint],
5669
+ bundle: true,
5670
+ write: false,
5671
+ minify: true,
5672
+ metafile: true,
5673
+ format: "esm",
5674
+ target: "es2020",
5675
+ platform: "browser",
5676
+ treeShaking: true,
5677
+ external: [
5678
+ "react",
5679
+ "react-dom",
5680
+ "react/jsx-runtime",
5681
+ "react/jsx-dev-runtime",
5682
+ // Optional peer deps — excluded from measurement
5683
+ "recharts",
5684
+ "shiki",
5685
+ "react-day-picker",
5686
+ "@tanstack/react-table",
5687
+ "date-fns",
5688
+ "@base-ui-components/*",
5689
+ "@base-ui/react/*"
5690
+ ],
5691
+ loader: {
5692
+ ".scss": "empty",
5693
+ ".css": "empty",
5694
+ ".svg": "empty",
5695
+ ".png": "empty",
5696
+ ".jpg": "empty",
5697
+ ".gif": "empty",
5698
+ ".woff": "empty",
5699
+ ".woff2": "empty",
5700
+ ".ttf": "empty",
5701
+ ".eot": "empty"
5702
+ },
5703
+ logLevel: "silent"
5704
+ });
5705
+ const output = result.outputFiles[0];
5706
+ const rawBytes = output.contents.byteLength;
5707
+ const gzipBytes = gzipSync(output.contents).byteLength;
5708
+ const imports = result.metafile ? groupImportsByDirectDep(result.metafile, entryPoint) : void 0;
5709
+ return { name, rawBytes, gzipBytes, imports };
5710
+ }
5711
+ async function measureBundleSizes(fragments, configDir, options = {}) {
5712
+ const concurrency = options.concurrency ?? 4;
5713
+ const measurements = /* @__PURE__ */ new Map();
5714
+ const errors = [];
5715
+ const start = Date.now();
5716
+ const entries = [];
5717
+ for (const [name, fragment] of Object.entries(fragments)) {
5718
+ const entryPoint = resolveEntryPoint(fragment.filePath, configDir);
5719
+ if (entryPoint) {
5720
+ entries.push({ name, entryPoint });
5721
+ } else {
5722
+ errors.push({
5723
+ name,
5724
+ error: `Could not resolve entry point from ${fragment.filePath}`
5725
+ });
5726
+ }
5727
+ }
5728
+ let completed = 0;
5729
+ for (let i = 0; i < entries.length; i += concurrency) {
5730
+ const batch = entries.slice(i, i + concurrency);
5731
+ const results = await Promise.allSettled(
5732
+ batch.map(
5733
+ ({ name, entryPoint }) => measureSingleComponent(entryPoint, name)
5734
+ )
5735
+ );
5736
+ for (let j = 0; j < results.length; j++) {
5737
+ const result = results[j];
5738
+ const { name } = batch[j];
5739
+ completed++;
5740
+ if (result.status === "fulfilled") {
5741
+ measurements.set(name, result.value);
5742
+ } else {
5743
+ errors.push({
5744
+ name,
5745
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
5746
+ });
5747
+ }
5748
+ options.onProgress?.(completed, entries.length, name);
5749
+ }
5750
+ }
5751
+ return {
5752
+ measurements,
5753
+ errors,
5754
+ elapsed: Date.now() - start
5755
+ };
5756
+ }
5757
+ function toPerformanceData(measurement, config, contractBudget) {
5758
+ const budget = contractBudget ?? config.budgets.bundleSize;
5759
+ const budgetPercent = Math.round(measurement.gzipBytes / budget * 100);
5760
+ const imports = measurement.imports?.slice(0, 10).map((imp) => ({
5761
+ path: imp.path,
5762
+ bytes: imp.bytes,
5763
+ percent: Math.round(imp.bytes / measurement.rawBytes * 100)
5764
+ }));
5765
+ return {
5766
+ bundleSize: measurement.gzipBytes,
5767
+ rawSize: measurement.rawBytes,
5768
+ complexity: classifyComplexity(measurement.gzipBytes),
5769
+ budgetPercent,
5770
+ overBudget: budgetPercent > 100,
5771
+ measuredAt: (/* @__PURE__ */ new Date()).toISOString(),
5772
+ ...imports && imports.length > 0 ? { imports } : {}
5773
+ };
5774
+ }
5775
+
5776
+ // src/commands/perf.ts
5492
5777
  async function perf(options) {
5493
5778
  const { config: configPath, json, component, concurrency, detail } = options;
5494
5779
  const shouldWrite = options.write !== false;
5495
5780
  const { config, configDir } = await loadConfig(configPath);
5496
5781
  const perfConfig = resolvePerformanceConfig(config.performance ?? "standard");
5497
- const outFile = resolve10(configDir, config.outFile ?? BRAND.outFile);
5782
+ const outFile = resolve11(configDir, config.outFile ?? BRAND.outFile);
5498
5783
  let data;
5499
5784
  try {
5500
5785
  data = JSON.parse(await readFile10(outFile, "utf-8"));
@@ -5636,418 +5921,45 @@ ${pc21.bold("Summary")}`);
5636
5921
  };
5637
5922
  }
5638
5923
 
5639
- // src/commands/doctor.ts
5640
- import { readFile as readFile11, access as access3 } from "fs/promises";
5641
- import { join as join10, resolve as resolve11 } from "path";
5642
- import pc22 from "picocolors";
5643
- var VALID_NEUTRALS = ["stone", "ice", "earth", "sand", "fire"];
5644
- var VALID_DENSITIES = ["compact", "default", "relaxed"];
5645
- var VALID_RADII = ["sharp", "subtle", "default", "rounded", "pill"];
5646
- async function checkPackageInstalled(root) {
5647
- try {
5648
- const pkgPath = join10(root, "package.json");
5649
- const content = await readFile11(pkgPath, "utf-8");
5650
- const pkg2 = JSON.parse(content);
5651
- const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
5652
- if (allDeps["@fragments-sdk/ui"]) {
5653
- return {
5654
- name: "Package installed",
5655
- status: "pass",
5656
- message: `@fragments-sdk/ui ${allDeps["@fragments-sdk/ui"]} found in dependencies`
5657
- };
5658
- }
5659
- return {
5660
- name: "Package installed",
5661
- status: "fail",
5662
- message: "@fragments-sdk/ui not found in package.json",
5663
- fix: "npm install @fragments-sdk/ui"
5664
- };
5665
- } catch {
5666
- return {
5667
- name: "Package installed",
5668
- status: "fail",
5669
- message: "No package.json found"
5670
- };
5671
- }
5672
- }
5673
- async function checkStylesImport(root) {
5674
- const entryPatterns = [
5675
- "src/main.tsx",
5676
- "src/main.ts",
5677
- "src/index.tsx",
5678
- "src/index.ts",
5679
- "src/App.tsx",
5680
- "src/App.ts",
5681
- "app/layout.tsx",
5682
- "app/layout.ts",
5683
- "src/app/layout.tsx",
5684
- "src/app/layout.ts",
5685
- "app/root.tsx",
5686
- "pages/_app.tsx",
5687
- "pages/_app.ts"
5688
- ];
5689
- for (const pattern of entryPatterns) {
5690
- try {
5691
- const content = await readFile11(join10(root, pattern), "utf-8");
5692
- if (content.includes("@fragments-sdk/ui/styles")) {
5693
- return {
5694
- name: "Styles import",
5695
- status: "pass",
5696
- message: `Found styles import in ${pattern}`
5697
- };
5698
- }
5699
- if (content.includes("@fragments-sdk/ui/globals")) {
5700
- return {
5701
- name: "Styles import",
5702
- status: "warn",
5703
- message: `${pattern} uses deprecated '@fragments-sdk/ui/globals'. Use '@fragments-sdk/ui/styles' instead`,
5704
- fix: `Replace '@fragments-sdk/ui/globals' with '@fragments-sdk/ui/styles' in ${pattern}`
5705
- };
5706
- }
5707
- } catch {
5708
- }
5709
- }
5710
- const scssPatterns = [
5711
- "src/styles/globals.scss",
5712
- "src/globals.scss",
5713
- "styles/globals.scss",
5714
- "app/globals.scss",
5715
- "src/app/globals.scss",
5716
- "app/styles/globals.scss"
5717
- ];
5718
- for (const pattern of scssPatterns) {
5719
- try {
5720
- const content = await readFile11(join10(root, pattern), "utf-8");
5721
- if (content.includes("@fragments-sdk/ui/styles")) {
5722
- return {
5723
- name: "Styles import",
5724
- status: "pass",
5725
- message: `Found SCSS @use import in ${pattern}`
5726
- };
5727
- }
5728
- } catch {
5729
- }
5730
- }
5731
- return {
5732
- name: "Styles import",
5733
- status: "fail",
5734
- message: "No @fragments-sdk/ui/styles import found in entry files",
5735
- fix: "Add `import '@fragments-sdk/ui/styles'` to your app's entry file"
5736
- };
5737
- }
5738
- async function checkThemeProvider(root) {
5739
- const providerPatterns = [
5740
- "src/main.tsx",
5741
- "src/App.tsx",
5742
- "src/providers.tsx",
5743
- "app/layout.tsx",
5744
- "app/providers.tsx",
5745
- "src/app/layout.tsx",
5746
- "src/app/providers.tsx",
5747
- "app/root.tsx",
5748
- "pages/_app.tsx"
5749
- ];
5750
- for (const pattern of providerPatterns) {
5751
- try {
5752
- const content = await readFile11(join10(root, pattern), "utf-8");
5753
- if (content.includes("ThemeProvider")) {
5754
- if (content.includes("defaultTheme=") || content.includes("defaultTheme =")) {
5755
- return {
5756
- name: "ThemeProvider",
5757
- status: "warn",
5758
- message: `${pattern} uses deprecated 'defaultTheme' prop. Use 'defaultMode' instead`,
5759
- fix: `Replace 'defaultTheme' with 'defaultMode' in ${pattern}`
5760
- };
5761
- }
5762
- return {
5763
- name: "ThemeProvider",
5764
- status: "pass",
5765
- message: `ThemeProvider found in ${pattern}`
5766
- };
5767
- }
5768
- } catch {
5769
- }
5770
- }
5771
- return {
5772
- name: "ThemeProvider",
5773
- status: "warn",
5774
- message: "ThemeProvider not found in common entry files (optional but recommended)",
5775
- fix: 'Wrap your app with <ThemeProvider defaultMode="system">'
5776
- };
5777
- }
5778
- async function checkScssSeeds(root) {
5779
- const checks = [];
5780
- const scssPatterns = [
5781
- "src/styles/globals.scss",
5782
- "src/globals.scss",
5783
- "styles/globals.scss",
5784
- "app/globals.scss",
5785
- "src/app/globals.scss",
5786
- "app/styles/globals.scss"
5787
- ];
5788
- for (const pattern of scssPatterns) {
5789
- try {
5790
- const content = await readFile11(join10(root, pattern), "utf-8");
5791
- if (!content.includes("@fragments-sdk/ui/styles")) continue;
5792
- const standalonePattern = /^\$fui-\w+:\s*.+;$/m;
5793
- if (standalonePattern.test(content) && !content.includes("@use")) {
5794
- checks.push({
5795
- name: "SCSS syntax",
5796
- status: "fail",
5797
- message: `${pattern} uses standalone $fui- variables. Must use @use...with() syntax`,
5798
- fix: "@use '@fragments-sdk/ui/styles' with ($fui-brand: #0066ff);"
5799
- });
5800
- }
5801
- const neutralMatch = content.match(/\$fui-neutral:\s*"([^"]+)"/);
5802
- if (neutralMatch && !VALID_NEUTRALS.includes(neutralMatch[1])) {
5803
- checks.push({
5804
- name: "SCSS seed: neutral",
5805
- status: "fail",
5806
- message: `Invalid $fui-neutral: "${neutralMatch[1]}" in ${pattern}`,
5807
- fix: `Valid neutrals: ${VALID_NEUTRALS.join(", ")}`
5808
- });
5809
- }
5810
- const densityMatch = content.match(/\$fui-density:\s*"([^"]+)"/);
5811
- if (densityMatch && !VALID_DENSITIES.includes(densityMatch[1])) {
5812
- checks.push({
5813
- name: "SCSS seed: density",
5814
- status: "fail",
5815
- message: `Invalid $fui-density: "${densityMatch[1]}" in ${pattern}`,
5816
- fix: `Valid densities: ${VALID_DENSITIES.join(", ")}`
5817
- });
5818
- }
5819
- const radiusMatch = content.match(/\$fui-radius-style:\s*"([^"]+)"/);
5820
- if (radiusMatch && !VALID_RADII.includes(radiusMatch[1])) {
5821
- checks.push({
5822
- name: "SCSS seed: radius-style",
5823
- status: "fail",
5824
- message: `Invalid $fui-radius-style: "${radiusMatch[1]}" in ${pattern}`,
5825
- fix: `Valid radius styles: ${VALID_RADII.join(", ")}`
5826
- });
5827
- }
5828
- const brandMatch = content.match(/\$fui-brand:\s*(#[0-9a-fA-F]+)/);
5829
- if (brandMatch) {
5830
- const hex = brandMatch[1];
5831
- if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(hex)) {
5832
- checks.push({
5833
- name: "SCSS seed: brand",
5834
- status: "fail",
5835
- message: `Invalid $fui-brand color: "${hex}" in ${pattern}`,
5836
- fix: "Must be a valid hex color (e.g., #0066ff)"
5837
- });
5838
- }
5839
- }
5840
- if (checks.length === 0) {
5841
- checks.push({
5842
- name: "SCSS seeds",
5843
- status: "pass",
5844
- message: `Seed values in ${pattern} are valid`
5845
- });
5846
- }
5847
- return checks;
5848
- } catch {
5849
- }
5850
- }
5851
- checks.push({
5852
- name: "SCSS seeds",
5853
- status: "pass",
5854
- message: "No custom SCSS seeds configured (using defaults)"
5855
- });
5856
- return checks;
5857
- }
5858
- async function checkPeerDeps(root) {
5859
- const checks = [];
5860
- try {
5861
- const pkgPath = join10(root, "package.json");
5862
- const content = await readFile11(pkgPath, "utf-8");
5863
- const pkg2 = JSON.parse(content);
5864
- const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
5865
- if (!allDeps["react"]) {
5866
- checks.push({
5867
- name: "Peer dep: react",
5868
- status: "fail",
5869
- message: "react not found in dependencies (required)",
5870
- fix: "npm install react react-dom"
5871
- });
5872
- } else {
5873
- checks.push({
5874
- name: "Peer dep: react",
5875
- status: "pass",
5876
- message: `react ${allDeps["react"]} installed`
5877
- });
5878
- }
5879
- if (!allDeps["sass"]) {
5880
- checks.push({
5881
- name: "Peer dep: sass",
5882
- status: "warn",
5883
- message: "sass not installed (needed for custom SCSS theming)",
5884
- fix: "npm install -D sass"
5885
- });
5886
- }
5887
- const optionalPeers = [
5888
- { pkg: "recharts", components: "Chart" },
5889
- { pkg: "shiki", components: "CodeBlock" },
5890
- { pkg: "react-day-picker", components: "DatePicker" },
5891
- { pkg: "@tanstack/react-table", components: "DataTable" }
5892
- ];
5893
- for (const peer of optionalPeers) {
5894
- if (allDeps[peer.pkg]) {
5895
- checks.push({
5896
- name: `Optional dep: ${peer.pkg}`,
5897
- status: "pass",
5898
- message: `${peer.pkg} installed (enables ${peer.components})`
5899
- });
5900
- }
5901
- }
5902
- } catch {
5903
- checks.push({
5904
- name: "Peer dependencies",
5905
- status: "fail",
5906
- message: "Could not read package.json"
5907
- });
5908
- }
5909
- return checks;
5910
- }
5911
- async function checkMcpConfig(root) {
5912
- const mcpConfigPaths = [
5913
- ".mcp.json",
5914
- ".cursor/mcp.json",
5915
- ".vscode/mcp.json"
5916
- ];
5917
- for (const configPath of mcpConfigPaths) {
5918
- try {
5919
- const fullPath = join10(root, configPath);
5920
- const content = await readFile11(fullPath, "utf-8");
5921
- const config = JSON.parse(content);
5922
- const servers = config.mcpServers || config.servers || {};
5923
- const hasFragments = Object.values(servers).some((server) => {
5924
- const s = server;
5925
- return s.args?.some((arg) => arg.includes("@fragments-sdk/mcp")) || s.command?.includes("fragments");
5926
- });
5927
- if (hasFragments) {
5928
- return {
5929
- name: "MCP configuration",
5930
- status: "pass",
5931
- message: `Fragments MCP server configured in ${configPath}`
5932
- };
5933
- }
5934
- } catch {
5935
- }
5936
- }
5937
- return {
5938
- name: "MCP configuration",
5939
- status: "warn",
5940
- message: "No Fragments MCP server configuration found (optional)",
5941
- fix: "Run `fragments init` or add @fragments-sdk/mcp to your MCP config"
5942
- };
5943
- }
5944
- async function checkTypeScript(root) {
5945
- try {
5946
- const tsconfigPath = join10(root, "tsconfig.json");
5947
- await access3(tsconfigPath);
5948
- return {
5949
- name: "TypeScript",
5950
- status: "pass",
5951
- message: "tsconfig.json found"
5952
- };
5953
- } catch {
5954
- return {
5955
- name: "TypeScript",
5956
- status: "warn",
5957
- message: "No tsconfig.json found (TypeScript recommended but not required)"
5958
- };
5959
- }
5960
- }
5961
- async function doctor(options = {}) {
5962
- const root = resolve11(options.root ?? process.cwd());
5963
- const checks = [];
5964
- if (!options.json) {
5965
- console.log(pc22.cyan(`
5966
- ${BRAND.name} Doctor
5967
- `));
5968
- console.log(pc22.dim(`Checking project at ${root}
5969
- `));
5970
- }
5971
- checks.push(await checkPackageInstalled(root));
5972
- checks.push(await checkStylesImport(root));
5973
- checks.push(await checkThemeProvider(root));
5974
- checks.push(...await checkScssSeeds(root));
5975
- checks.push(...await checkPeerDeps(root));
5976
- checks.push(await checkMcpConfig(root));
5977
- checks.push(await checkTypeScript(root));
5978
- const passed = checks.filter((c) => c.status === "pass").length;
5979
- const warned = checks.filter((c) => c.status === "warn").length;
5980
- const failed = checks.filter((c) => c.status === "fail").length;
5981
- const result = {
5982
- success: failed === 0,
5983
- checks,
5984
- passed,
5985
- warned,
5986
- failed
5987
- };
5988
- if (options.json) {
5989
- console.log(JSON.stringify(result, null, 2));
5990
- } else {
5991
- for (const check of checks) {
5992
- const icon = check.status === "pass" ? pc22.green("\u2713") : check.status === "warn" ? pc22.yellow("!") : pc22.red("\u2717");
5993
- const msg = check.status === "pass" ? check.message : check.status === "warn" ? pc22.yellow(check.message) : pc22.red(check.message);
5994
- console.log(` ${icon} ${pc22.bold(check.name)}: ${msg}`);
5995
- if (check.fix && check.status !== "pass") {
5996
- console.log(pc22.dim(` \u2192 ${check.fix}`));
5997
- }
5998
- }
5999
- console.log();
6000
- if (failed === 0 && warned === 0) {
6001
- console.log(pc22.green(`\u2713 All ${passed} checks passed \u2014 your setup looks great!`));
6002
- } else if (failed === 0) {
6003
- console.log(pc22.green(`\u2713 ${passed} passed`) + pc22.yellow(`, ${warned} warning(s)`));
6004
- } else {
6005
- console.log(
6006
- pc22.red(`\u2717 ${failed} failed`) + (warned > 0 ? pc22.yellow(`, ${warned} warning(s)`) : "") + pc22.dim(`, ${passed} passed`)
6007
- );
6008
- }
6009
- console.log();
6010
- }
6011
- return result;
6012
- }
6013
-
6014
5924
  // src/commands/sync.ts
6015
- import pc23 from "picocolors";
6016
- import { readFile as readFile12, writeFile as writeFile9 } from "fs/promises";
5925
+ import pc22 from "picocolors";
5926
+ import { readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
5927
+ import { resolveComponentSourcePath } from "@fragments-sdk/extract";
5928
+ import { createComponentExtractor } from "@fragments-sdk/extract";
6017
5929
  async function sync(options = {}) {
6018
5930
  const { config, configDir } = await loadConfig(options.config);
6019
- console.log(pc23.cyan(`
5931
+ console.log(pc22.cyan(`
6020
5932
  ${BRAND.name} Sync
6021
5933
  `));
6022
5934
  if (options.dryRun) {
6023
- console.log(pc23.dim("Dry run \u2014 no files will be modified.\n"));
5935
+ console.log(pc22.dim("Dry run \u2014 no files will be modified.\n"));
6024
5936
  }
6025
5937
  const result = await runSync(config, configDir, options);
6026
5938
  if (result.updated.length > 0) {
6027
5939
  const verb = options.dryRun ? "Would update" : "Updated";
6028
- console.log(pc23.bold(`${verb} ${result.updated.length} fragment(s):
5940
+ console.log(pc22.bold(`${verb} ${result.updated.length} fragment(s):
6029
5941
  `));
6030
5942
  for (const comp of result.updated) {
6031
- console.log(` ${pc23.green("\u2713")} ${pc23.bold(comp.name)} ${pc23.dim(`(${comp.file})`)}`);
5943
+ console.log(` ${pc22.green("\u2713")} ${pc22.bold(comp.name)} ${pc22.dim(`(${comp.file})`)}`);
6032
5944
  for (const change of comp.changes) {
6033
- console.log(` ${pc23.dim("\u2022")} ${change}`);
5945
+ console.log(` ${pc22.dim("\u2022")} ${change}`);
6034
5946
  }
6035
5947
  }
6036
5948
  console.log();
6037
5949
  }
6038
5950
  if (result.skipped.length > 0) {
6039
- console.log(pc23.dim(`Skipped ${result.skipped.length}: ${result.skipped.map((s) => s.name).join(", ")}
5951
+ console.log(pc22.dim(`Skipped ${result.skipped.length}: ${result.skipped.map((s) => s.name).join(", ")}
6040
5952
  `));
6041
5953
  }
6042
5954
  if (result.errors.length > 0) {
6043
- console.log(pc23.red(pc23.bold("Errors:")));
5955
+ console.log(pc22.red(pc22.bold("Errors:")));
6044
5956
  for (const err of result.errors) {
6045
- console.log(` ${pc23.red("\u2717")} ${pc23.bold(err.file)}: ${err.message}`);
5957
+ console.log(` ${pc22.red("\u2717")} ${pc22.bold(err.file)}: ${err.message}`);
6046
5958
  }
6047
5959
  console.log();
6048
5960
  }
6049
5961
  if (result.updated.length === 0 && result.errors.length === 0) {
6050
- console.log(pc23.green("All fragments are in sync \u2014 nothing to update.\n"));
5962
+ console.log(pc22.green("All fragments are in sync \u2014 nothing to update.\n"));
6051
5963
  }
6052
5964
  return result;
6053
5965
  }
@@ -6066,7 +5978,7 @@ async function runSync(config, configDir, options) {
6066
5978
  const fragment = await loadFragmentFile(file.absolutePath);
6067
5979
  if (!fragment?.meta?.name) continue;
6068
5980
  if (options.component && fragment.meta.name !== options.component) continue;
6069
- const fileContent = await readFile12(file.absolutePath, "utf-8");
5981
+ const fileContent = await readFile11(file.absolutePath, "utf-8");
6070
5982
  const parsed = parseFragmentFile(fileContent, file.absolutePath);
6071
5983
  if (!parsed.componentImport) {
6072
5984
  skipped.push({ name: fragment.meta.name, reason: "No component import found" });
@@ -6228,9 +6140,9 @@ function escapeRegex(str) {
6228
6140
  }
6229
6141
 
6230
6142
  // src/commands/govern.ts
6231
- import pc24 from "picocolors";
6143
+ import pc23 from "picocolors";
6232
6144
  async function governCheck(options = {}) {
6233
- console.log(pc24.cyan(`
6145
+ console.log(pc23.cyan(`
6234
6146
  ${BRAND.name} Governance Check
6235
6147
  `));
6236
6148
  const { cliCheck, formatVerdict } = await import("@fragments-sdk/govern");
@@ -6241,42 +6153,89 @@ ${BRAND.name} Governance Check
6241
6153
  console.log();
6242
6154
  }
6243
6155
  if (result.verdict.passed) {
6244
- console.log(pc24.green(`\u2713 Governance check passed (score: ${result.verdict.score}/100)
6156
+ console.log(pc23.green(`\u2713 Governance check passed (score: ${result.verdict.score}/100)
6245
6157
  `));
6246
6158
  } else {
6247
- console.log(pc24.red(`\u2717 Governance check failed (score: ${result.verdict.score}/100)
6159
+ console.log(pc23.red(`\u2717 Governance check failed (score: ${result.verdict.score}/100)
6248
6160
  `));
6249
6161
  }
6250
6162
  return { exitCode: result.exitCode };
6251
6163
  }
6252
6164
  async function governInit(options = {}) {
6253
6165
  const { writeFile: writeFile11 } = await import("fs/promises");
6166
+ const { existsSync: existsSync4 } = await import("fs");
6254
6167
  const { resolve: resolve14 } = await import("path");
6255
6168
  const { generateConfigTemplate } = await import("@fragments-sdk/govern");
6169
+ const { findTailwindConfig } = await import("./token-normalizer-TEPOVBPV.js");
6170
+ const cwd = process.cwd();
6171
+ const detected = {
6172
+ tokenIncludes: [],
6173
+ projectType: "unknown"
6174
+ };
6175
+ const tailwindPath = findTailwindConfig(cwd);
6176
+ if (tailwindPath) {
6177
+ const { relative: relative9 } = await import("path");
6178
+ detected.tokenIncludes.push(relative9(cwd, tailwindPath));
6179
+ detected.projectType = "tailwind";
6180
+ console.log(pc23.dim(` Detected Tailwind config: ${detected.tokenIncludes[0]}`));
6181
+ }
6182
+ if (detected.tokenIncludes.length === 0) {
6183
+ const candidates = [
6184
+ "src/styles/tokens.scss",
6185
+ "src/styles/variables.scss",
6186
+ "src/styles/theme.scss",
6187
+ "src/tokens.css",
6188
+ "src/styles/tokens.css",
6189
+ "src/styles/variables.css",
6190
+ "styles/tokens.scss",
6191
+ "styles/variables.scss",
6192
+ "tokens.json",
6193
+ "src/tokens.json"
6194
+ ];
6195
+ for (const candidate of candidates) {
6196
+ if (existsSync4(resolve14(cwd, candidate))) {
6197
+ detected.tokenIncludes.push(candidate);
6198
+ detected.projectType = candidate.endsWith(".scss") ? "scss" : candidate.endsWith(".json") ? "dtcg" : "css";
6199
+ console.log(pc23.dim(` Detected token source: ${candidate}`));
6200
+ }
6201
+ }
6202
+ }
6203
+ if (detected.tokenIncludes.length === 0) {
6204
+ console.log(pc23.dim(" No token sources auto-detected. You can add them manually."));
6205
+ }
6256
6206
  const outputPath = resolve14(options.output ?? "fragments.config.ts");
6257
- const template = generateConfigTemplate();
6207
+ const template = generateConfigTemplate({ tokenIncludes: detected.tokenIncludes });
6258
6208
  await writeFile11(outputPath, template, "utf-8");
6259
- console.log(pc24.green(`\u2713 Created ${outputPath}
6209
+ console.log(pc23.green(`
6210
+ \u2713 Created ${outputPath}
6260
6211
  `));
6212
+ if (detected.tokenIncludes.length > 0) {
6213
+ console.log(
6214
+ pc23.dim(` Token sources configured: ${detected.tokenIncludes.join(", ")}`)
6215
+ );
6216
+ }
6217
+ console.log(
6218
+ pc23.dim(" Run ") + pc23.cyan("fragments govern scan") + pc23.dim(" to check your project.\n")
6219
+ );
6261
6220
  }
6262
6221
  async function governConnect() {
6263
- const { readFile: readFile14, writeFile: writeFile11, appendFile } = await import("fs/promises");
6264
- const { existsSync: existsSync3 } = await import("fs");
6222
+ const { readFile: readFile13, writeFile: writeFile11, appendFile } = await import("fs/promises");
6223
+ const { existsSync: existsSync4 } = await import("fs");
6265
6224
  const { resolve: resolve14 } = await import("path");
6266
6225
  const { platform } = await import("os");
6267
6226
  const { exec } = await import("child_process");
6268
6227
  const { password, confirm } = await import("@inquirer/prompts");
6269
6228
  const cloudUrl = process.env.FRAGMENTS_URL ?? "https://app.usefragments.com";
6270
- console.log(pc24.cyan(`
6229
+ console.log(pc23.cyan(`
6271
6230
  ${BRAND.name} \u2014 Connect to Cloud
6272
6231
  `));
6273
6232
  console.log(
6274
- pc24.dim(" This will connect your project to the Fragments dashboard\n") + pc24.dim(" for centralized audit tracking and team visibility.\n")
6233
+ pc23.dim(" This will connect your project to the Fragments dashboard\n") + pc23.dim(" for centralized audit tracking and team visibility.\n")
6275
6234
  );
6276
- console.log(pc24.bold(" Step 1 of 3: Get your API key\n"));
6235
+ console.log(pc23.bold(" Step 1 of 3: Get your API key\n"));
6277
6236
  const dashboardUrl = `${cloudUrl}/api-keys`;
6278
- console.log(pc24.dim(` \u2192 Opening the dashboard in your browser...`));
6279
- console.log(pc24.dim(` Copy your API key from Settings \u2192 API Keys
6237
+ console.log(pc23.dim(` \u2192 Opening the dashboard in your browser...`));
6238
+ console.log(pc23.dim(` Copy your API key from Settings \u2192 API Keys
6280
6239
  `));
6281
6240
  const os = platform();
6282
6241
  const openCmd = os === "darwin" ? `open "${dashboardUrl}"` : os === "win32" ? `start "" "${dashboardUrl}"` : `xdg-open "${dashboardUrl}"`;
@@ -6289,42 +6248,42 @@ async function governConnect() {
6289
6248
  mask: "*"
6290
6249
  });
6291
6250
  if (!apiKey.trim()) {
6292
- console.log(pc24.yellow("\n API key cannot be empty. Please try again.\n"));
6251
+ console.log(pc23.yellow("\n API key cannot be empty. Please try again.\n"));
6293
6252
  continue;
6294
6253
  }
6295
- console.log(pc24.dim("\n Verifying..."));
6254
+ console.log(pc23.dim("\n Verifying..."));
6296
6255
  try {
6297
6256
  const response = await fetch(`${cloudUrl}/api/verify`, {
6298
6257
  headers: { Authorization: `Bearer ${apiKey.trim()}` }
6299
6258
  });
6300
6259
  if (!response.ok) {
6301
- console.log(pc24.red(`
6260
+ console.log(pc23.red(`
6302
6261
  \u2717 Invalid API key (HTTP ${response.status}). Please try again.
6303
6262
  `));
6304
6263
  continue;
6305
6264
  }
6306
6265
  const data = await response.json();
6307
6266
  if (!data.valid) {
6308
- console.log(pc24.red("\n \u2717 API key not recognized. Please try again.\n"));
6267
+ console.log(pc23.red("\n \u2717 API key not recognized. Please try again.\n"));
6309
6268
  continue;
6310
6269
  }
6311
6270
  orgName = data.orgName ?? "your organization";
6312
- console.log(pc24.green(`
6271
+ console.log(pc23.green(`
6313
6272
  \u2713 Connected to "${orgName}" (verified)
6314
6273
  `));
6315
6274
  break;
6316
6275
  } catch (error) {
6317
6276
  console.log(
6318
- pc24.red("\n \u2717 Could not reach the dashboard.")
6277
+ pc23.red("\n \u2717 Could not reach the dashboard.")
6319
6278
  );
6320
6279
  console.log(
6321
- pc24.dim(` ${error instanceof Error ? error.message : "Network error"}
6280
+ pc23.dim(` ${error instanceof Error ? error.message : "Network error"}
6322
6281
  `)
6323
6282
  );
6324
6283
  continue;
6325
6284
  }
6326
6285
  }
6327
- console.log(pc24.bold(" Step 2 of 3: Save configuration\n"));
6286
+ console.log(pc23.bold(" Step 2 of 3: Save configuration\n"));
6328
6287
  const saveToEnv = await confirm({
6329
6288
  message: "Save API key to .env file?",
6330
6289
  default: true
@@ -6332,77 +6291,77 @@ async function governConnect() {
6332
6291
  if (saveToEnv) {
6333
6292
  const envPath = resolve14(".env");
6334
6293
  const envEntry = `FRAGMENTS_API_KEY=${apiKey.trim()}`;
6335
- if (existsSync3(envPath)) {
6336
- const envContent = await readFile14(envPath, "utf-8");
6294
+ if (existsSync4(envPath)) {
6295
+ const envContent = await readFile13(envPath, "utf-8");
6337
6296
  if (envContent.includes("FRAGMENTS_API_KEY=")) {
6338
6297
  const updated = envContent.replace(
6339
6298
  /^FRAGMENTS_API_KEY=.*$/m,
6340
6299
  envEntry
6341
6300
  );
6342
6301
  await writeFile11(envPath, updated, "utf-8");
6343
- console.log(pc24.green(" \u2713 Updated FRAGMENTS_API_KEY in .env"));
6302
+ console.log(pc23.green(" \u2713 Updated FRAGMENTS_API_KEY in .env"));
6344
6303
  } else {
6345
6304
  await appendFile(envPath, `
6346
6305
  ${envEntry}
6347
6306
  `, "utf-8");
6348
- console.log(pc24.green(" \u2713 Added FRAGMENTS_API_KEY to .env"));
6307
+ console.log(pc23.green(" \u2713 Added FRAGMENTS_API_KEY to .env"));
6349
6308
  }
6350
6309
  } else {
6351
6310
  await writeFile11(envPath, `${envEntry}
6352
6311
  `, "utf-8");
6353
- console.log(pc24.green(" \u2713 Created .env with FRAGMENTS_API_KEY"));
6312
+ console.log(pc23.green(" \u2713 Created .env with FRAGMENTS_API_KEY"));
6354
6313
  }
6355
6314
  if (cloudUrl !== "https://app.usefragments.com") {
6356
- const envContent = await readFile14(envPath, "utf-8");
6315
+ const envContent = await readFile13(envPath, "utf-8");
6357
6316
  if (!envContent.includes("FRAGMENTS_URL=")) {
6358
6317
  await appendFile(envPath, `FRAGMENTS_URL=${cloudUrl}
6359
6318
  `, "utf-8");
6360
- console.log(pc24.green(` \u2713 Added FRAGMENTS_URL to .env`));
6319
+ console.log(pc23.green(` \u2713 Added FRAGMENTS_URL to .env`));
6361
6320
  }
6362
6321
  }
6363
6322
  const gitignorePath = resolve14(".gitignore");
6364
- if (existsSync3(gitignorePath)) {
6365
- const gitignore = await readFile14(gitignorePath, "utf-8");
6323
+ if (existsSync4(gitignorePath)) {
6324
+ const gitignore = await readFile13(gitignorePath, "utf-8");
6366
6325
  if (!gitignore.split("\n").some((line) => line.trim() === ".env")) {
6367
6326
  await appendFile(gitignorePath, "\n.env\n", "utf-8");
6368
- console.log(pc24.green(" \u2713 Added .env to .gitignore"));
6327
+ console.log(pc23.green(" \u2713 Added .env to .gitignore"));
6369
6328
  }
6370
6329
  } else {
6371
6330
  await writeFile11(gitignorePath, ".env\n", "utf-8");
6372
- console.log(pc24.green(" \u2713 Created .gitignore with .env entry"));
6331
+ console.log(pc23.green(" \u2713 Created .gitignore with .env entry"));
6373
6332
  }
6374
6333
  }
6375
- console.log(pc24.bold("\n Step 3 of 3: Config check\n"));
6334
+ console.log(pc23.bold("\n Step 3 of 3: Config check\n"));
6376
6335
  const { findGovernConfig } = await import("@fragments-sdk/govern");
6377
6336
  const configPath = findGovernConfig();
6378
6337
  if (configPath) {
6379
- console.log(pc24.green(` \u2713 Found govern config: ${configPath}`));
6338
+ console.log(pc23.green(` \u2713 Found govern config: ${configPath}`));
6380
6339
  } else {
6381
6340
  console.log(
6382
- pc24.yellow(" No govern config found \u2014 run `fragments govern init` to create one")
6341
+ pc23.yellow(" No govern config found \u2014 run `fragments govern init` to create one")
6383
6342
  );
6384
6343
  }
6385
- console.log(pc24.dim("\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
6386
- console.log(pc24.green(" \u2713 All set!") + " Run `fragments govern check` to send your first audit.\n");
6387
- console.log(pc24.dim(` Dashboard: ${cloudUrl}/overview
6344
+ console.log(pc23.dim("\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
6345
+ console.log(pc23.green(" \u2713 All set!") + " Run `fragments govern check` to send your first audit.\n");
6346
+ console.log(pc23.dim(` Dashboard: ${cloudUrl}/overview
6388
6347
  `));
6389
6348
  }
6390
6349
  async function governReport() {
6391
- const { readFile: readFile14 } = await import("fs/promises");
6392
- console.log(pc24.cyan(`
6350
+ const { readFile: readFile13 } = await import("fs/promises");
6351
+ console.log(pc23.cyan(`
6393
6352
  ${BRAND.name} Governance Report
6394
6353
  `));
6395
6354
  let raw;
6396
6355
  try {
6397
- raw = await readFile14(".govern-audit.jsonl", "utf-8");
6356
+ raw = await readFile13(".govern-audit.jsonl", "utf-8");
6398
6357
  } catch {
6399
- console.log(pc24.yellow("No audit log found (.govern-audit.jsonl)\n"));
6400
- console.log(pc24.dim("Run `fragments govern check` to generate audit data.\n"));
6358
+ console.log(pc23.yellow("No audit log found (.govern-audit.jsonl)\n"));
6359
+ console.log(pc23.dim("Run `fragments govern check` to generate audit data.\n"));
6401
6360
  return;
6402
6361
  }
6403
6362
  const lines = raw.trim().split("\n").filter(Boolean);
6404
6363
  if (lines.length === 0) {
6405
- console.log(pc24.yellow("Audit log is empty.\n"));
6364
+ console.log(pc23.yellow("Audit log is empty.\n"));
6406
6365
  return;
6407
6366
  }
6408
6367
  let totalScore = 0;
@@ -6427,13 +6386,15 @@ ${BRAND.name} Governance Report
6427
6386
  }
6428
6387
 
6429
6388
  // src/commands/migrate-contract.ts
6430
- import pc25 from "picocolors";
6389
+ import pc24 from "picocolors";
6431
6390
  import fg4 from "fast-glob";
6432
6391
  import { resolve as resolve13 } from "path";
6433
6392
 
6434
6393
  // src/migrate/fragment-to-contract.ts
6435
- import { readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
6436
- import { resolve as resolve12, dirname as dirname4, relative as relative8 } from "path";
6394
+ import { readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
6395
+ import { resolve as resolve12, dirname as dirname5, relative as relative8 } from "path";
6396
+ import { createComponentExtractor as createComponentExtractor2 } from "@fragments-sdk/extract";
6397
+ import { resolveComponentSourcePath as resolveComponentSourcePath2 } from "@fragments-sdk/extract";
6437
6398
  function compilePropsSummaryFromExtracted(props) {
6438
6399
  return Object.entries(props).filter(([, p]) => p.source === "local").map(([name, prop]) => {
6439
6400
  let summary = name + ": ";
@@ -6471,17 +6432,17 @@ function compilePropsSummaryFromDocs(props) {
6471
6432
  async function migrateFragmentToContract(fragmentPath, configDir, options) {
6472
6433
  const warnings = [];
6473
6434
  const absFragmentPath = resolve12(fragmentPath);
6474
- const content = await readFile13(absFragmentPath, "utf-8");
6435
+ const content = await readFile12(absFragmentPath, "utf-8");
6475
6436
  const parsed = parseFragmentFile(content, fragmentPath);
6476
6437
  warnings.push(...parsed.warnings);
6477
6438
  if (!parsed.meta.name) {
6478
6439
  throw new Error(`Fragment file ${fragmentPath} has no meta.name`);
6479
6440
  }
6480
6441
  let extractedMeta = null;
6481
- const extractor = createComponentExtractor(options?.tsconfigPath);
6442
+ const extractor = createComponentExtractor2(options?.tsconfigPath);
6482
6443
  try {
6483
6444
  const componentExportName = parsed.componentName ?? parsed.meta.name;
6484
- const componentSourcePath = resolveComponentSourcePath(
6445
+ const componentSourcePath = resolveComponentSourcePath2(
6485
6446
  absFragmentPath,
6486
6447
  parsed.componentImport
6487
6448
  );
@@ -6497,7 +6458,7 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6497
6458
  }
6498
6459
  let sourcePath;
6499
6460
  if (parsed.componentImport) {
6500
- const absSource = resolveComponentSourcePath(absFragmentPath, parsed.componentImport);
6461
+ const absSource = resolveComponentSourcePath2(absFragmentPath, parsed.componentImport);
6501
6462
  if (absSource) {
6502
6463
  sourcePath = relative8(configDir, absSource);
6503
6464
  } else {
@@ -6505,7 +6466,7 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6505
6466
  warnings.push(`Could not resolve component source path: ${parsed.componentImport}`);
6506
6467
  }
6507
6468
  } else {
6508
- const fragDir = dirname4(absFragmentPath);
6469
+ const fragDir = dirname5(absFragmentPath);
6509
6470
  sourcePath = relative8(configDir, resolve12(fragDir, "index.tsx"));
6510
6471
  warnings.push("No component import found; assuming ./index.tsx");
6511
6472
  }
@@ -6609,16 +6570,16 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6609
6570
  async function migrateContract(options) {
6610
6571
  const { config, configDir } = await loadConfig(options.config);
6611
6572
  const pattern = options.glob ?? "src/**/*.fragment.tsx";
6612
- console.log(pc25.blue(`Migrating fragment files matching: ${pattern}`));
6573
+ console.log(pc24.blue(`Migrating fragment files matching: ${pattern}`));
6613
6574
  if (options.dryRun) {
6614
- console.log(pc25.yellow("(dry run \u2014 no files will be written)"));
6575
+ console.log(pc24.yellow("(dry run \u2014 no files will be written)"));
6615
6576
  }
6616
6577
  const files = await fg4(pattern, { cwd: configDir, absolute: true });
6617
6578
  if (files.length === 0) {
6618
- console.log(pc25.yellow("No fragment files found matching pattern."));
6579
+ console.log(pc24.yellow("No fragment files found matching pattern."));
6619
6580
  return { migrated: 0, failed: 0, warnings: 0 };
6620
6581
  }
6621
- console.log(pc25.dim(`Found ${files.length} fragment file(s)`));
6582
+ console.log(pc24.dim(`Found ${files.length} fragment file(s)`));
6622
6583
  let migrated = 0;
6623
6584
  let failed = 0;
6624
6585
  let totalWarnings = 0;
@@ -6631,31 +6592,31 @@ async function migrateContract(options) {
6631
6592
  });
6632
6593
  migrated++;
6633
6594
  const verb = options.dryRun ? "Would migrate" : "Migrated";
6634
- console.log(pc25.green(` \u2713 ${verb}: ${result.contractPath}`));
6595
+ console.log(pc24.green(` \u2713 ${verb}: ${result.contractPath}`));
6635
6596
  if (result.warnings.length > 0) {
6636
6597
  totalWarnings += result.warnings.length;
6637
6598
  for (const w of result.warnings) {
6638
- console.log(pc25.yellow(` \u26A0 ${w}`));
6599
+ console.log(pc24.yellow(` \u26A0 ${w}`));
6639
6600
  }
6640
6601
  }
6641
6602
  } catch (error) {
6642
6603
  failed++;
6643
- console.log(pc25.red(` \u2717 Failed: ${file}`));
6644
- console.log(pc25.dim(` ${error instanceof Error ? error.message : String(error)}`));
6604
+ console.log(pc24.red(` \u2717 Failed: ${file}`));
6605
+ console.log(pc24.dim(` ${error instanceof Error ? error.message : String(error)}`));
6645
6606
  }
6646
6607
  }
6647
6608
  console.log("");
6648
- console.log(pc25.bold("Migration summary:"));
6649
- console.log(` ${pc25.green(`${migrated} migrated`)} ${pc25.red(`${failed} failed`)} ${pc25.yellow(`${totalWarnings} warnings`)}`);
6609
+ console.log(pc24.bold("Migration summary:"));
6610
+ console.log(` ${pc24.green(`${migrated} migrated`)} ${pc24.red(`${failed} failed`)} ${pc24.yellow(`${totalWarnings} warnings`)}`);
6650
6611
  if (!options.dryRun && migrated > 0) {
6651
6612
  console.log("");
6652
- console.log(pc25.dim("Run `fragments build` to verify migrated contracts compile correctly."));
6613
+ console.log(pc24.dim("Run `fragments build` to verify migrated contracts compile correctly."));
6653
6614
  }
6654
6615
  return { migrated, failed, warnings: totalWarnings };
6655
6616
  }
6656
6617
 
6657
6618
  // src/bin.ts
6658
- var __dirname = dirname5(fileURLToPath(import.meta.url));
6619
+ var __dirname = dirname6(fileURLToPath(import.meta.url));
6659
6620
  var pkg = JSON.parse(readFileSync(join11(__dirname, "../package.json"), "utf-8"));
6660
6621
  var EXPERIMENTAL = process.env.FRAGMENTS_EXPERIMENTAL === "1";
6661
6622
  var program = new Command();
@@ -6667,7 +6628,7 @@ program.command("validate").description("Validate fragment files").option("-c, -
6667
6628
  process.exit(1);
6668
6629
  }
6669
6630
  } catch (error) {
6670
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6631
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6671
6632
  process.exit(1);
6672
6633
  }
6673
6634
  });
@@ -6683,11 +6644,11 @@ program.command("sync").description("Auto-update fragment files from component s
6683
6644
  process.exit(1);
6684
6645
  }
6685
6646
  } catch (error) {
6686
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6647
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6687
6648
  process.exit(1);
6688
6649
  }
6689
6650
  });
6690
- program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAND.dataDir}/ directory`).option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path").option("--registry", `Also generate ${BRAND.dataDir}/${BRAND.registryFile} and ${BRAND.contextFile}`).option("--registry-only", `Only generate ${BRAND.dataDir}/ directory (skip ${BRAND.outFile})`).option("--from-source", "Build from source code (zero-config, no fragment files needed)").option("--skip-usage", "Skip usage analysis when building from source").option("--skip-storybook", "Skip Storybook parsing when building from source").option("-v, --verbose", "Verbose output").action(async (options) => {
6651
+ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAND.dataDir}/ directory`).option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path").option("--registry", `Also generate ${BRAND.dataDir}/${BRAND.registryFile} and ${BRAND.contextFile}`).option("--registry-only", `Only generate ${BRAND.dataDir}/ directory (skip ${BRAND.outFile})`).option("--from-source", "Build from source code (zero-config, no fragment files needed)").option("--if-needed", `Skip rebuilding when ${BRAND.outFile} is already fresh`).option("--check", `Check whether ${BRAND.outFile} is fresh and exit non-zero if it is stale`).option("--skip-usage", "Skip usage analysis when building from source").option("--skip-storybook", "Skip Storybook parsing when building from source").option("-v, --verbose", "Verbose output").action(async (options) => {
6691
6652
  try {
6692
6653
  const result = await build({
6693
6654
  config: options.config,
@@ -6695,6 +6656,8 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
6695
6656
  registry: options.registry,
6696
6657
  registryOnly: options.registryOnly,
6697
6658
  fromSource: options.fromSource,
6659
+ ifNeeded: options.ifNeeded,
6660
+ check: options.check,
6698
6661
  skipUsage: options.skipUsage,
6699
6662
  skipStorybook: options.skipStorybook,
6700
6663
  verbose: options.verbose
@@ -6703,7 +6666,7 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
6703
6666
  process.exit(1);
6704
6667
  }
6705
6668
  } catch (error) {
6706
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6669
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6707
6670
  process.exit(1);
6708
6671
  }
6709
6672
  });
@@ -6722,7 +6685,7 @@ program.command("context").description("Generate AI-ready context for your desig
6722
6685
  process.exit(1);
6723
6686
  }
6724
6687
  } catch (error) {
6725
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6688
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6726
6689
  process.exit(1);
6727
6690
  }
6728
6691
  });
@@ -6749,7 +6712,7 @@ program.command("ai").description("Generate context optimized for AI assistants
6749
6712
  }
6750
6713
  }
6751
6714
  } catch (error) {
6752
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6715
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6753
6716
  process.exit(1);
6754
6717
  }
6755
6718
  });
@@ -6757,7 +6720,7 @@ program.command("list").description("List all discovered fragment files").option
6757
6720
  try {
6758
6721
  await list(options);
6759
6722
  } catch (error) {
6760
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6723
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6761
6724
  process.exit(1);
6762
6725
  }
6763
6726
  });
@@ -6765,7 +6728,7 @@ program.command("reset").description("Reset to initial state (delete all generat
6765
6728
  try {
6766
6729
  await reset(options);
6767
6730
  } catch (error) {
6768
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6731
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6769
6732
  process.exit(1);
6770
6733
  }
6771
6734
  });
@@ -6779,7 +6742,7 @@ linkCommand.command("figma").argument("[figma-url]", "Figma file URL to link com
6779
6742
  variants: options.variants
6780
6743
  });
6781
6744
  } catch (error) {
6782
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6745
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6783
6746
  process.exit(1);
6784
6747
  }
6785
6748
  });
@@ -6794,7 +6757,7 @@ linkCommand.command("storybook").description("Bootstrap fragments from existing
6794
6757
  exclude: options.exclude
6795
6758
  });
6796
6759
  } catch (error) {
6797
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6760
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6798
6761
  process.exit(1);
6799
6762
  }
6800
6763
  });
@@ -6814,7 +6777,7 @@ program.command("screenshot").description("Capture screenshots of component vari
6814
6777
  process.exit(1);
6815
6778
  }
6816
6779
  } catch (error) {
6817
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6780
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6818
6781
  process.exit(1);
6819
6782
  }
6820
6783
  });
@@ -6833,7 +6796,7 @@ program.command("diff").argument("[component]", "Component name to diff (optiona
6833
6796
  process.exit(1);
6834
6797
  }
6835
6798
  } catch (error) {
6836
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6799
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6837
6800
  process.exit(1);
6838
6801
  }
6839
6802
  });
@@ -6852,8 +6815,8 @@ program.command("compare").argument("[component]", "Component name to compare").
6852
6815
  process.exit(1);
6853
6816
  }
6854
6817
  } catch (error) {
6855
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6856
- console.log(pc26.dim(`
6818
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6819
+ console.log(pc25.dim(`
6857
6820
  Make sure a dev server is running on the expected port.`));
6858
6821
  process.exit(1);
6859
6822
  }
@@ -6872,7 +6835,7 @@ program.command("analyze").description("Analyze design system and generate repor
6872
6835
  process.exit(1);
6873
6836
  }
6874
6837
  } catch (error) {
6875
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6838
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6876
6839
  process.exit(1);
6877
6840
  }
6878
6841
  });
@@ -6891,7 +6854,7 @@ program.command("verify").argument("[component]", "Component name to verify (opt
6891
6854
  if (options.ci) {
6892
6855
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Verification failed" }));
6893
6856
  } else {
6894
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6857
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6895
6858
  }
6896
6859
  process.exit(1);
6897
6860
  }
@@ -6908,7 +6871,7 @@ program.command("audit").description("Scan all fragments and show compliance met
6908
6871
  if (options.json) {
6909
6872
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Audit failed" }));
6910
6873
  } else {
6911
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6874
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6912
6875
  }
6913
6876
  process.exit(1);
6914
6877
  }
@@ -6930,7 +6893,7 @@ program.command("a11y").description("Run accessibility checks on all component v
6930
6893
  if (options.json) {
6931
6894
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "A11y check failed" }));
6932
6895
  } else {
6933
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6896
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6934
6897
  }
6935
6898
  process.exit(1);
6936
6899
  }
@@ -6953,7 +6916,7 @@ program.command("enhance").description("AI-powered documentation generation from
6953
6916
  if (options.format === "json") {
6954
6917
  console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Enhance failed" }));
6955
6918
  } else {
6956
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6919
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6957
6920
  }
6958
6921
  process.exit(1);
6959
6922
  }
@@ -6974,7 +6937,7 @@ program.command("scan").description(`Zero-config ${BRAND.outFile} generation fro
6974
6937
  process.exit(1);
6975
6938
  }
6976
6939
  } catch (error) {
6977
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6940
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6978
6941
  process.exit(1);
6979
6942
  }
6980
6943
  });
@@ -6990,7 +6953,7 @@ program.command("migrate-contract").description("Migrate .fragment.tsx files to
6990
6953
  process.exit(1);
6991
6954
  }
6992
6955
  } catch (error) {
6993
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6956
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
6994
6957
  process.exit(1);
6995
6958
  }
6996
6959
  });
@@ -7003,7 +6966,7 @@ program.command("storygen").description("Generate Storybook stories from fragmen
7003
6966
  format: options.format
7004
6967
  });
7005
6968
  } catch (error) {
7006
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6969
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7007
6970
  process.exit(1);
7008
6971
  }
7009
6972
  });
@@ -7015,7 +6978,7 @@ program.command("metrics").argument("[component]", "Component name (optional, sh
7015
6978
  json: options.json
7016
6979
  });
7017
6980
  } catch (error) {
7018
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6981
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7019
6982
  process.exit(1);
7020
6983
  }
7021
6984
  });
@@ -7029,9 +6992,9 @@ program.command("baseline").description("Manage visual regression baselines").ar
7029
6992
  port: options.port
7030
6993
  });
7031
6994
  } catch (error) {
7032
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
6995
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7033
6996
  if (action === "update") {
7034
- console.log(pc26.dim(`
6997
+ console.log(pc25.dim(`
7035
6998
  Make sure a dev server is running on the expected port.`));
7036
6999
  }
7037
7000
  process.exit(1);
@@ -7039,27 +7002,27 @@ Make sure a dev server is running on the expected port.`));
7039
7002
  });
7040
7003
  program.command("view").description(`Generate a static HTML viewer for ${BRAND.outFile}`).option("-i, --input <path>", `Path to ${BRAND.outFile}`, BRAND.outFile).option("-o, --output <path>", "Output HTML file path", BRAND.viewerHtmlFile).option("--open", "Open in browser after generation").action(async (options) => {
7041
7004
  try {
7042
- const { generateViewerFromJson } = await import("./static-viewer-63PG6FWY.js");
7005
+ const { generateViewerFromJson } = await import("./static-viewer-7QIBQZRC.js");
7043
7006
  const fs2 = await import("fs/promises");
7044
7007
  const path = await import("path");
7045
7008
  const inputPath = path.resolve(process.cwd(), options.input);
7046
7009
  const outputPath = path.resolve(process.cwd(), options.output);
7047
- console.log(pc26.cyan(`
7010
+ console.log(pc25.cyan(`
7048
7011
  ${BRAND.name} Viewer Generator
7049
7012
  `));
7050
7013
  try {
7051
7014
  await fs2.access(inputPath);
7052
7015
  } catch {
7053
- console.log(pc26.red(`Error: ${options.input} not found.`));
7054
- console.log(pc26.dim(`
7055
- Run ${pc26.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
7016
+ console.log(pc25.red(`Error: ${options.input} not found.`));
7017
+ console.log(pc25.dim(`
7018
+ Run ${pc25.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
7056
7019
  `));
7057
7020
  process.exit(1);
7058
7021
  }
7059
- console.log(pc26.dim(`Reading: ${options.input}`));
7022
+ console.log(pc25.dim(`Reading: ${options.input}`));
7060
7023
  const html = await generateViewerFromJson(inputPath);
7061
7024
  await fs2.writeFile(outputPath, html);
7062
- console.log(pc26.green(`
7025
+ console.log(pc25.green(`
7063
7026
  \u2713 Generated: ${options.output}
7064
7027
  `));
7065
7028
  if (options.open) {
@@ -7068,7 +7031,7 @@ Run ${pc26.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
7068
7031
  exec(`${openCmd} "${outputPath}"`);
7069
7032
  }
7070
7033
  } catch (error) {
7071
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7034
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7072
7035
  process.exit(1);
7073
7036
  }
7074
7037
  });
@@ -7081,7 +7044,31 @@ program.command("add").argument("[name]", 'Component name (e.g., "Button", "Text
7081
7044
  component: options.component
7082
7045
  });
7083
7046
  } catch (error) {
7084
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7047
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7048
+ process.exit(1);
7049
+ }
7050
+ });
7051
+ program.command("create").argument("[name]", "Project name").description("Create a new project with Fragments UI and your custom theme").option("-t, --template <template>", "Framework template (nextjs, vite)", "nextjs").option("--pm <manager>", "Package manager (npm, pnpm, yarn, bun)").option("--theme <encoded>", "Encoded theme string").option("--preset <id>", "Theme preset ID from usefragments.com/create").option("--brand <color>", "Brand color hex (e.g., #6366f1)").option("--scss", "Use SCSS output (installs sass)").option("--mcp", "Configure MCP server for AI tooling").option("-y, --yes", "Skip interactive prompts").option("--no-git", "Skip git initialization").action(async (name, options) => {
7052
+ try {
7053
+ const { create } = await import("./create-JVAU3YKN.js");
7054
+ const result = await create({
7055
+ name,
7056
+ template: options.template,
7057
+ packageManager: options.pm,
7058
+ theme: options.theme,
7059
+ preset: options.preset,
7060
+ brand: options.brand,
7061
+ scss: options.scss,
7062
+ mcp: options.mcp,
7063
+ yes: options.yes,
7064
+ noGit: !options.git
7065
+ });
7066
+ if (!result.success) {
7067
+ if (result.error) console.error(pc25.red(`Error: ${result.error}`));
7068
+ process.exit(1);
7069
+ }
7070
+ } catch (error) {
7071
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7085
7072
  process.exit(1);
7086
7073
  }
7087
7074
  });
@@ -7098,7 +7085,7 @@ program.command("setup").description("Configure @fragments-sdk/ui in a consumer
7098
7085
  process.exit(1);
7099
7086
  }
7100
7087
  } catch (error) {
7101
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7088
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7102
7089
  process.exit(1);
7103
7090
  }
7104
7091
  });
@@ -7110,13 +7097,13 @@ initCmd.action(async (options) => {
7110
7097
  try {
7111
7098
  if (options.cloud) {
7112
7099
  if (!EXPERIMENTAL) {
7113
- console.log(pc26.yellow(`
7100
+ console.log(pc25.yellow(`
7114
7101
  Fragments Cloud is not yet publicly available.`));
7115
- console.log(pc26.dim(` Set FRAGMENTS_EXPERIMENTAL=1 to enable preview features.
7102
+ console.log(pc25.dim(` Set FRAGMENTS_EXPERIMENTAL=1 to enable preview features.
7116
7103
  `));
7117
7104
  process.exit(1);
7118
7105
  }
7119
- const { initCloud } = await import("./init-cloud-MQ6GRJAZ.js");
7106
+ const { initCloud } = await import("./init-cloud-3DNKPWFB.js");
7120
7107
  await initCloud({
7121
7108
  url: options.cloudUrl,
7122
7109
  port: options.port ? Number(options.port) : void 0,
@@ -7125,7 +7112,7 @@ initCmd.action(async (options) => {
7125
7112
  });
7126
7113
  return;
7127
7114
  }
7128
- const { init } = await import("./init-HGSM35XA.js");
7115
+ const { init } = await import("./init-SSGUSP7Z.js");
7129
7116
  const result = await init({
7130
7117
  projectRoot: process.cwd(),
7131
7118
  force: options.force,
@@ -7141,20 +7128,20 @@ initCmd.action(async (options) => {
7141
7128
  govern: options.govern
7142
7129
  });
7143
7130
  if (!result.success) {
7144
- console.error(pc26.red("\nInit failed with errors:"));
7131
+ console.error(pc25.red("\nInit failed with errors:"));
7145
7132
  for (const error of result.errors) {
7146
- console.error(pc26.red(` - ${error}`));
7133
+ console.error(pc25.red(` - ${error}`));
7147
7134
  }
7148
7135
  process.exit(1);
7149
7136
  }
7150
7137
  } catch (error) {
7151
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7138
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7152
7139
  process.exit(1);
7153
7140
  }
7154
7141
  });
7155
7142
  program.command("snapshot").description("Run visual snapshot tests per component variant").option("-p, --port <port>", "Port of running dev server (skips starting one)").option("--update", "Update existing snapshots instead of comparing").option("--component <name>", "Filter to a specific component").option("--spec <path>", "Path to snapshot spec file").option("--ci", "CI mode - exit 1 on mismatch").action(async (options) => {
7156
7143
  try {
7157
- const { snapshot } = await import("./snapshot-KQEQ6XHL.js");
7144
+ const { snapshot } = await import("./snapshot-WIJMEIFT.js");
7158
7145
  const result = await snapshot({
7159
7146
  port: options.port,
7160
7147
  update: options.update,
@@ -7166,14 +7153,14 @@ program.command("snapshot").description("Run visual snapshot tests per component
7166
7153
  process.exit(1);
7167
7154
  }
7168
7155
  } catch (error) {
7169
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7156
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7170
7157
  process.exit(1);
7171
7158
  }
7172
7159
  });
7173
7160
  var tokensCmd = program.command("tokens").description("Design token discovery, listing, and generation");
7174
7161
  tokensCmd.command("list", { isDefault: true }).description("Discover and list design tokens from CSS/SCSS/DTCG files").option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--categories", "Group tokens by category").option("--theme <theme>", "Filter by theme name").option("--category <category>", "Filter by category (color, spacing, typography, etc.)").option("--verbose", "Show all tokens (no truncation)").action(async (options) => {
7175
7162
  try {
7176
- const { tokens } = await import("./tokens-6GYKDV6U.js");
7163
+ const { tokens } = await import("./tokens-NZWFQIAB.js");
7177
7164
  const result = await tokens({
7178
7165
  config: options.config,
7179
7166
  json: options.json,
@@ -7186,13 +7173,13 @@ tokensCmd.command("list", { isDefault: true }).description("Discover and list de
7186
7173
  process.exit(1);
7187
7174
  }
7188
7175
  } catch (error) {
7189
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7176
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7190
7177
  process.exit(1);
7191
7178
  }
7192
7179
  });
7193
7180
  tokensCmd.command("generate").description("Generate CSS, SCSS, Tailwind, or Figma output from a DTCG .tokens.json file").requiredOption("--from <path>", "Path to DTCG .tokens.json source file").requiredOption("--format <formats>", "Output formats (comma-separated: css, scss, tailwind, figma)").option("--out <dir>", "Output directory (default: same directory as source)").option("--prefix <prefix>", "Token name prefix").option("--selector <selector>", "CSS selector for custom properties (default: :root)").option("--verbose", "Verbose output").action(async (options) => {
7194
7181
  try {
7195
- const { tokensGenerate } = await import("./tokens-generate-VTZV5EEW.js");
7182
+ const { tokensGenerate } = await import("./tokens-generate-5JQSJ27E.js");
7196
7183
  await tokensGenerate({
7197
7184
  from: options.from,
7198
7185
  format: options.format,
@@ -7202,13 +7189,27 @@ tokensCmd.command("generate").description("Generate CSS, SCSS, Tailwind, or Figm
7202
7189
  verbose: options.verbose
7203
7190
  });
7204
7191
  } catch (error) {
7205
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7192
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7193
+ process.exit(1);
7194
+ }
7195
+ });
7196
+ tokensCmd.command("push").description("Push code tokens to Fragments Cloud for drift comparison").option("-c, --config <path>", "Path to fragments config file").option("--tailwind-v4 <path>", "Path to Tailwind v4 CSS file with @theme block").option("--dry-run", "Parse and display tokens without pushing").option("--verbose", "Show detailed output").action(async (options) => {
7197
+ try {
7198
+ const { tokensPush } = await import("./tokens-push-HY3KO36V.js");
7199
+ await tokensPush({
7200
+ config: options.config,
7201
+ tailwindV4: options.tailwindV4,
7202
+ dryRun: options.dryRun,
7203
+ verbose: options.verbose
7204
+ });
7205
+ } catch (error) {
7206
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7206
7207
  process.exit(1);
7207
7208
  }
7208
7209
  });
7209
7210
  program.command("generate").description("Generate fragment files from component source code").argument("[component]", "Specific component name to generate (optional)").option("--force", "Overwrite existing fragment files").option("--pattern <glob>", "Pattern for component files", "src/components/**/*.tsx").action(async (component, options) => {
7210
7211
  try {
7211
- const { generate } = await import("./generate-A4FP5426.js");
7212
+ const { generate } = await import("./generate-PVOLUAAC.js");
7212
7213
  const result = await generate({
7213
7214
  projectRoot: process.cwd(),
7214
7215
  component,
@@ -7216,11 +7217,11 @@ program.command("generate").description("Generate fragment files from component
7216
7217
  componentPattern: options.pattern
7217
7218
  });
7218
7219
  if (!result.success) {
7219
- console.error(pc26.red("\nGenerate completed with errors"));
7220
+ console.error(pc25.red("\nGenerate completed with errors"));
7220
7221
  process.exit(1);
7221
7222
  }
7222
7223
  } catch (error) {
7223
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7224
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7224
7225
  process.exit(1);
7225
7226
  }
7226
7227
  });
@@ -7228,7 +7229,7 @@ program.command("graph").description("Query the component relationship graph").a
7228
7229
  try {
7229
7230
  await graph(component, options);
7230
7231
  } catch (error) {
7231
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7232
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7232
7233
  process.exit(1);
7233
7234
  }
7234
7235
  });
@@ -7246,7 +7247,7 @@ program.command("inspect").description("Inspect a single component from compiled
7246
7247
  if (options.json) {
7247
7248
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Inspect failed" }));
7248
7249
  } else {
7249
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7250
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7250
7251
  }
7251
7252
  process.exit(1);
7252
7253
  }
@@ -7265,7 +7266,7 @@ program.command("discover").description("List and filter components from compile
7265
7266
  if (options.json) {
7266
7267
  console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Discover failed" }));
7267
7268
  } else {
7268
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7269
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7269
7270
  }
7270
7271
  process.exit(1);
7271
7272
  }
@@ -7284,14 +7285,14 @@ program.command("perf").description("Profile component bundle sizes and performa
7284
7285
  process.exit(1);
7285
7286
  }
7286
7287
  } catch (error) {
7287
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7288
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7288
7289
  process.exit(1);
7289
7290
  }
7290
7291
  });
7291
7292
  program.command("test").description("Run interaction tests for fragments with play functions").option("-c, --config <path>", "Path to config file").option("--component <name>", "Filter by component name").option("--tags <tags>", "Filter by tags (comma-separated)").option("--grep <pattern>", "Filter by variant name pattern").option("--exclude <pattern>", "Exclude tests matching pattern").option("--parallel <count>", "Number of parallel browser contexts", parseInt, 4).option("--timeout <ms>", "Timeout per test in milliseconds", parseInt, 3e4).option("--retries <count>", "Number of retries for failed tests", parseInt, 0).option("--bail", "Stop on first failure").option("--browser <name>", "Browser to use (chromium, firefox, webkit)", "chromium").option("--headed", "Run in headed mode (show browser)").option("--a11y", "Run accessibility checks with axe-core").option("--visual", "Capture screenshots for visual regression").option("--update-snapshots", "Update visual snapshots").option("--watch", "Watch mode - re-run on file changes").option("--reporters <names>", "Reporters to use (console, junit, json)", "console").option("-o, --output <dir>", "Output directory for results", "./test-results").option("--server-url <url>", "URL of running dev server (skips starting server)").option("-p, --port <port>", "Port for dev server", parseInt, 6006).option("--ci", "CI mode - non-interactive, exit with code 1 on failure").option("--list", "List available tests without running them").action(async (options) => {
7292
7293
  try {
7293
7294
  const { config, configDir } = await loadConfig(options.config);
7294
- const { runTestCommand, listTests } = await import("./test-UQYUCZIS.js");
7295
+ const { runTestCommand, listTests } = await import("./test-64Z5BKBA.js");
7295
7296
  if (options.list) {
7296
7297
  await listTests(config, configDir, {
7297
7298
  component: options.component,
@@ -7324,12 +7325,13 @@ program.command("test").description("Run interaction tests for fragments with pl
7324
7325
  });
7325
7326
  process.exit(exitCode);
7326
7327
  } catch (error) {
7327
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7328
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7328
7329
  process.exit(1);
7329
7330
  }
7330
7331
  });
7331
7332
  program.command("doctor").description("Diagnose design system configuration issues").option("--root <dir>", "Project root directory", process.cwd()).option("--json", "Output results as JSON").option("--fix", "Auto-fix issues where possible").action(async (options) => {
7332
7333
  try {
7334
+ const { doctor } = await import("./doctor-BDPMYYE6.js");
7333
7335
  const result = await doctor({
7334
7336
  root: options.root,
7335
7337
  json: options.json,
@@ -7339,15 +7341,15 @@ program.command("doctor").description("Diagnose design system configuration issu
7339
7341
  process.exit(1);
7340
7342
  }
7341
7343
  } catch (error) {
7342
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7344
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7343
7345
  process.exit(1);
7344
7346
  }
7345
7347
  });
7346
7348
  var governCmd = program.command("govern").description(EXPERIMENTAL ? "AI UI governance checks" : "AI UI governance checks (preview \u2014 set FRAGMENTS_EXPERIMENTAL=1)").hook("preAction", () => {
7347
7349
  if (!EXPERIMENTAL) {
7348
- console.log(pc26.yellow(`
7350
+ console.log(pc25.yellow(`
7349
7351
  Fragments governance is not yet publicly available.`));
7350
- console.log(pc26.dim(` Set FRAGMENTS_EXPERIMENTAL=1 to enable preview features.
7352
+ console.log(pc25.dim(` Set FRAGMENTS_EXPERIMENTAL=1 to enable preview features.
7351
7353
  `));
7352
7354
  process.exit(1);
7353
7355
  }
@@ -7362,7 +7364,7 @@ governCmd.command("check").description("Validate a UISpec against governance pol
7362
7364
  });
7363
7365
  process.exit(exitCode);
7364
7366
  } catch (error) {
7365
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7367
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7366
7368
  process.exit(1);
7367
7369
  }
7368
7370
  });
@@ -7370,7 +7372,7 @@ governCmd.command("init").description("Generate a fragments.config.ts with gover
7370
7372
  try {
7371
7373
  await governInit({ output: options.output });
7372
7374
  } catch (error) {
7373
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7375
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7374
7376
  process.exit(1);
7375
7377
  }
7376
7378
  });
@@ -7378,7 +7380,7 @@ governCmd.command("report").description("Summarize governance audit log").action
7378
7380
  try {
7379
7381
  await governReport();
7380
7382
  } catch (error) {
7381
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7383
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7382
7384
  process.exit(1);
7383
7385
  }
7384
7386
  });
@@ -7386,13 +7388,13 @@ governCmd.command("connect").description("Connect your project to the Fragments
7386
7388
  try {
7387
7389
  await governConnect();
7388
7390
  } catch (error) {
7389
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7391
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7390
7392
  process.exit(1);
7391
7393
  }
7392
7394
  });
7393
7395
  governCmd.command("scan").description("Scan JSX/TSX codebase for governance violations").option("-d, --dir <path>", "Root directory (default: auto-detect)").option("-c, --config <path>", "Path to govern.config.ts").option("-f, --format <format>", "Output format: summary, json, sarif", "summary").option("-q, --quiet", "Suppress non-error output").action(async (options) => {
7394
7396
  try {
7395
- const { governScan } = await import("./govern-scan-UCBZR6D6.js");
7397
+ const { governScan } = await import("./govern-scan-OYFZYOQW.js");
7396
7398
  const { exitCode } = await governScan({
7397
7399
  dir: options.dir,
7398
7400
  config: options.config,
@@ -7401,13 +7403,13 @@ governCmd.command("scan").description("Scan JSX/TSX codebase for governance viol
7401
7403
  });
7402
7404
  process.exit(exitCode);
7403
7405
  } catch (error) {
7404
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7406
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7405
7407
  process.exit(1);
7406
7408
  }
7407
7409
  });
7408
7410
  governCmd.command("watch").description("Watch JSX/TSX files and re-check on changes").option("-d, --dir <path>", "Root directory (default: auto-detect)").option("-c, --config <path>", "Path to govern.config.ts").option("-q, --quiet", "Suppress non-error output").option("--debounce <ms>", "Debounce interval in ms", "300").action(async (options) => {
7409
7411
  try {
7410
- const { governWatch } = await import("./govern-scan-UCBZR6D6.js");
7412
+ const { governWatch } = await import("./govern-scan-OYFZYOQW.js");
7411
7413
  await governWatch({
7412
7414
  dir: options.dir,
7413
7415
  config: options.config,
@@ -7415,7 +7417,22 @@ governCmd.command("watch").description("Watch JSX/TSX files and re-check on chan
7415
7417
  debounce: parseInt(options.debounce, 10)
7416
7418
  });
7417
7419
  } catch (error) {
7418
- console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7420
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7421
+ process.exit(1);
7422
+ }
7423
+ });
7424
+ governCmd.command("push-contracts").description("Push component contracts to Fragments Cloud").option("-i, --input <path>", "Path to fragments.json (default: ./fragments.json)").option("--url <url>", "Fragments Cloud URL").option("--api-key <key>", "API key (default: FRAGMENTS_API_KEY env var)").option("-q, --quiet", "Suppress non-error output").action(async (options) => {
7425
+ try {
7426
+ const { pushContracts } = await import("./push-contracts-WY32TFP6.js");
7427
+ const { exitCode } = await pushContracts({
7428
+ input: options.input,
7429
+ url: options.url,
7430
+ apiKey: options.apiKey,
7431
+ quiet: options.quiet
7432
+ });
7433
+ process.exit(exitCode);
7434
+ } catch (error) {
7435
+ console.error(pc25.red("Error:"), error instanceof Error ? error.message : error);
7419
7436
  process.exit(1);
7420
7437
  }
7421
7438
  });