@starklab/stark-mcp 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/package.json +10 -4
  2. package/src/adopt/adoptScanReport.js +124 -0
  3. package/src/adopt/catalog.js +26 -6
  4. package/src/adopt/foreignDiscoveryResolver.js +276 -0
  5. package/src/adopt/foreignPropSchemaResolver.js +134 -0
  6. package/src/adopt/foreignScanReport.js +210 -0
  7. package/src/adopt/foreignScoringResolver.js +192 -0
  8. package/src/adopt/foreignSystemConfig.js +356 -0
  9. package/src/adopt/installedPackageDiscoveryResolver.js +602 -0
  10. package/src/adopt/installedPackagePropSchemaResolver.js +279 -0
  11. package/src/adopt/installedPackageScoringResolver.js +153 -0
  12. package/src/adopt/installedSystemAutoDetector.js +51 -0
  13. package/src/adopt/installedSystemScan.js +101 -0
  14. package/src/adopt/jsxOpportunityHelpers.js +99 -0
  15. package/src/adopt/moduleGraph.js +39 -8
  16. package/src/adopt/opportunityResolver.js +255 -0
  17. package/src/adopt/opportunitySignaturesNative.js +47 -0
  18. package/src/adopt/usageRulesResolver.js +298 -0
  19. package/src/adopt/vecnaMaterializer.js +165 -0
  20. package/src/adopt/vecnaVerifier.js +127 -0
  21. package/src/cli.js +407 -1
  22. package/src/server.js +38 -14
  23. package/src/adopt/__fixtures__/dominion-fixture-app/src/pages/Home.jsx +0 -21
  24. package/src/adopt/__fixtures__/dominion-fixture-app/src/pages/Menu.jsx +0 -13
  25. package/src/adopt/__fixtures__/dominion-fixture-app/src/pages/Profile.jsx +0 -11
  26. package/src/adopt/__fixtures__/dominion-fixture-app/src/theme.css +0 -34
  27. package/src/adopt/__fixtures__/dominion-fixture-app/src/wrappers/AppButton.jsx +0 -8
  28. package/src/adopt/__fixtures__/dominion-fixture-app/src/wrappers/BrandButton.jsx +0 -9
  29. package/src/adopt/__fixtures__/dominion-fixture-app/src/wrappers/CardBase.jsx +0 -9
  30. package/src/adopt/__fixtures__/dominion-fixture-app/src/wrappers/FeatureCard.jsx +0 -7
  31. package/src/adopt/__fixtures__/dominion-fixture-app/src/wrappers/SectionCard.jsx +0 -12
  32. package/src/adopt/dominionFixture.test.js +0 -165
  33. package/src/adopt/propApiResolver.test.js +0 -229
  34. package/src/adopt/referenceResolver.test.js +0 -213
  35. package/src/adopt/rnTailwindResolver.test.js +0 -263
  36. package/src/adopt/rnTokenAliasResolver.test.js +0 -260
  37. package/src/adopt/tailwindResolver.test.js +0 -178
  38. package/src/adopt/targetDiscovery.test.js +0 -227
  39. package/src/adopt/tokenAliasResolver.test.js +0 -319
  40. package/src/adopt/wrapperResolver.test.js +0 -324
  41. package/src/data.test.js +0 -231
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Data-only registry of foreign design systems `stark-cli scan-foreign`
3
+ * knows how to detect. Phase 1 ships one entry — shadcn/ui, the only
4
+ * system that scored 4/4 in the B1 spike (ADOPTION_APP_PLAN.md §10
5
+ * decision #25) because its copy-paste distribution puts real component
6
+ * source (and therefore real prop types) inside the repo, with no
7
+ * node_modules boundary to cross. Structured so Phase 2's installed-
8
+ * package adapter (MUI, most likely) adds a second entry of a different
9
+ * shape rather than a new code path — the same reasoning catalog.json
10
+ * already gives Stark's own components, applied here to foreign ones.
11
+ */
12
+ export const FOREIGN_SYSTEMS = {
13
+ shadcn: {
14
+ id: 'shadcn',
15
+ label: 'shadcn/ui',
16
+ distribution: 'copy-paste', // vs Phase 2's 'installed-package'
17
+ // Same display-only hint as every installed-package entry below (see the
18
+ // comment above `mui`). shadcn generates React DOM components wrapping
19
+ // Radix web primitives, so 'web' is the only honest value — it was
20
+ // omitted rather than deliberated, which made shadcn the one row
21
+ // listForeignSystems() emitted as `platform: undefined`.
22
+ platform: 'web',
23
+ packageDetect: {
24
+ // shadcn is never itself an npm dependency — components.json (written
25
+ // by `npx shadcn init`) is the primary signal; @radix-ui/* deps (what
26
+ // shadcn's generated components wrap) are corroborating evidence only.
27
+ configFiles: ['components.json'],
28
+ depFallback: [/^@radix-ui\//],
29
+ },
30
+ componentDir: { parentName: 'components', dirName: 'ui' },
31
+ tokenSource: { markerVars: ['--background', '--primary', '--radius'] },
32
+ },
33
+ // Phase 2's 'installed-package' shape — real component/prop types live in
34
+ // node_modules/<npmPackage>'s .d.ts, not in repo source (see
35
+ // installedPackageDiscoveryResolver.js). This registry entry is a
36
+ // convenience label only, never a gate: cli.js's scan-foreign accepts any
37
+ // raw npm package name too, registered here or not. "platform" is a
38
+ // hint for the tested-systems list/auto-detect output only — it never
39
+ // restricts which --platform value actually runs against the package.
40
+ //
41
+ // An entry declares its packages one of two ways, never both:
42
+ // `npmPackage: 'x'` for a system published as one entry package (every
43
+ // entry below but `atlaskit`), or `npmPackages: ['a', 'b']` for one
44
+ // distributed as many sibling packages with no umbrella barrel. Read them
45
+ // through systemPackages() rather than either field directly; that helper
46
+ // is what every consumer (auto-detect, the tested-systems list, cli.js's
47
+ // scan dispatch) normalises through.
48
+ //
49
+ // Having an umbrella is the thing to check before reaching for
50
+ // `npmPackages` — a system that has one should be registered by it. Adobe
51
+ // React Spectrum looked like the multi-package case and is not: live
52
+ // probing on 2026-08-27 found `@adobe/react-spectrum` enumerating all 101
53
+ // components, so it would be registered single-string. What that probe did
54
+ // establish is that the two import styles are mutually blind — the
55
+ // umbrella scored 3/101 against umbrella-style imports and 0/101 against
56
+ // `@react-spectrum/button`-style ones, and the siblings scored the reverse.
57
+ // Listing an umbrella *and* its siblings together would therefore
58
+ // double-count the shared catalog (101 + 6 + 3 for 101 real components) and
59
+ // deflate the percentage, so `npmPackages` is for systems with no umbrella
60
+ // to choose, never a way to cover both import styles at once.
61
+ mui: {
62
+ id: 'mui',
63
+ label: 'MUI',
64
+ distribution: 'installed-package',
65
+ npmPackage: '@mui/material',
66
+ platform: 'web',
67
+ },
68
+ // The following twelve entries were live-verified against real npm installs
69
+ // 2026-08-25 (ADOPTION_APP_PLAN.md §10 decision #25, "broader 12-system
70
+ // sweep") — five needed real adapter fixes (Radix, Mantine, NativeBase,
71
+ // Chakra UI v3, @atlaskit/button), the rest came back clean. Restyle is
72
+ // registered despite its `used: 0` coverage gap — since root-caused as
73
+ // KNOWN_DISTRIBUTION_PATTERNS #7 (runtime-factory-synthesized), a
74
+ // documented architectural non-goal rather than a bug — instead of being
75
+ // left out: the point of this list is "what's been tested," not "what's
76
+ // guaranteed clean."
77
+ chakra: {
78
+ id: 'chakra',
79
+ label: 'Chakra UI',
80
+ distribution: 'installed-package',
81
+ npmPackage: '@chakra-ui/react',
82
+ platform: 'web',
83
+ },
84
+ carbon: {
85
+ id: 'carbon',
86
+ label: 'Carbon Design System',
87
+ distribution: 'installed-package',
88
+ npmPackage: '@carbon/react',
89
+ platform: 'web',
90
+ },
91
+ antd: {
92
+ id: 'antd',
93
+ label: 'Ant Design',
94
+ distribution: 'installed-package',
95
+ npmPackage: 'antd',
96
+ platform: 'web',
97
+ },
98
+ // The one genuinely umbrella-less system registered here, and the reason
99
+ // `npmPackages` exists. Atlaskit publishes ~100 independent `@atlaskit/*`
100
+ // packages and no barrel over them: `@atlaskit/core` is a 404 and bare
101
+ // `atlaskit` is npm's 0.0.1-security placeholder (both checked 2026-08-27).
102
+ // Until then this entry named a single sibling and its label said so —
103
+ // "Atlassian (Atlaskit Button)" — which reported Atlaskit as a
104
+ // four-component system. Live-verified against a real four-package install
105
+ // the same day: the old single-sibling form said 1/4 used (25%), the list
106
+ // below says 3/13 (23.1%) across the four, which is the honest denominator.
107
+ //
108
+ // The list is a curated core rather than all ~100 — every name below was
109
+ // confirmed to resolve on npm before being added. Siblings a repo has not
110
+ // installed are not an error: they land in the scan's `unresolved` array
111
+ // and stay out of the coverage denominator, since a component that isn't
112
+ // installed is not one the repo declined to use.
113
+ atlaskit: {
114
+ id: 'atlaskit',
115
+ label: 'Atlassian Atlaskit',
116
+ distribution: 'installed-package',
117
+ npmPackages: [
118
+ '@atlaskit/button',
119
+ '@atlaskit/textfield',
120
+ '@atlaskit/checkbox',
121
+ '@atlaskit/radio',
122
+ '@atlaskit/select',
123
+ '@atlaskit/form',
124
+ '@atlaskit/toggle',
125
+ '@atlaskit/modal-dialog',
126
+ '@atlaskit/drawer',
127
+ '@atlaskit/banner',
128
+ '@atlaskit/flag',
129
+ '@atlaskit/tooltip',
130
+ '@atlaskit/lozenge',
131
+ '@atlaskit/badge',
132
+ '@atlaskit/tag',
133
+ '@atlaskit/avatar',
134
+ '@atlaskit/tabs',
135
+ '@atlaskit/menu',
136
+ '@atlaskit/dropdown-menu',
137
+ '@atlaskit/breadcrumbs',
138
+ '@atlaskit/spinner',
139
+ '@atlaskit/progress-bar',
140
+ '@atlaskit/calendar',
141
+ '@atlaskit/datetime-picker',
142
+ '@atlaskit/inline-edit',
143
+ ],
144
+ platform: 'web',
145
+ },
146
+ radix: {
147
+ id: 'radix',
148
+ label: 'Radix Primitives',
149
+ distribution: 'installed-package',
150
+ npmPackage: 'radix-ui',
151
+ platform: 'web',
152
+ },
153
+ mantine: {
154
+ id: 'mantine',
155
+ label: 'Mantine',
156
+ distribution: 'installed-package',
157
+ npmPackage: '@mantine/core',
158
+ platform: 'web',
159
+ },
160
+ fluentui: {
161
+ id: 'fluentui',
162
+ label: 'Fluent UI',
163
+ distribution: 'installed-package',
164
+ npmPackage: '@fluentui/react-components',
165
+ platform: 'web',
166
+ },
167
+ nativebase: {
168
+ id: 'nativebase',
169
+ label: 'NativeBase',
170
+ distribution: 'installed-package',
171
+ npmPackage: 'native-base',
172
+ platform: 'native',
173
+ },
174
+ tamagui: {
175
+ id: 'tamagui',
176
+ label: 'Tamagui',
177
+ distribution: 'installed-package',
178
+ npmPackage: 'tamagui',
179
+ platform: 'native',
180
+ },
181
+ rnPaper: {
182
+ id: 'rnPaper',
183
+ label: 'React Native Paper',
184
+ distribution: 'installed-package',
185
+ npmPackage: 'react-native-paper',
186
+ platform: 'native',
187
+ },
188
+ restyle: {
189
+ id: 'restyle',
190
+ label: 'Restyle (Shopify)',
191
+ distribution: 'installed-package',
192
+ npmPackage: '@shopify/restyle',
193
+ platform: 'native',
194
+ },
195
+ rnElements: {
196
+ id: 'rnElements',
197
+ label: 'React Native Elements',
198
+ distribution: 'installed-package',
199
+ npmPackage: 'react-native-elements',
200
+ platform: 'native',
201
+ },
202
+ // The following six were live-verified 2026-08-26 (ADOPTION_APP_PLAN.md
203
+ // §10 decision #25, Track C) — chosen for distribution-mechanic diversity
204
+ // rather than popularity, to find export shapes the popular-and-similar
205
+ // systems above could not surface. Five came back clean; primereact
206
+ // produced KNOWN_DISTRIBUTION_PATTERNS #8. Registered here after the fact:
207
+ // they were verified in that round but never added, so `scan-foreign`'s
208
+ // tested-systems list under-reported what had actually been tested.
209
+ reactAria: {
210
+ id: 'reactAria',
211
+ label: 'React Aria (Adobe)',
212
+ distribution: 'installed-package',
213
+ npmPackage: 'react-aria',
214
+ platform: 'web',
215
+ },
216
+ headlessui: {
217
+ id: 'headlessui',
218
+ label: 'Headless UI',
219
+ distribution: 'installed-package',
220
+ npmPackage: '@headlessui/react',
221
+ platform: 'web',
222
+ },
223
+ blueprint: {
224
+ id: 'blueprint',
225
+ label: 'Blueprint (Palantir)',
226
+ distribution: 'installed-package',
227
+ npmPackage: '@blueprintjs/core',
228
+ platform: 'web',
229
+ },
230
+ // Registered on the same "what's been tested" principle as Restyle above:
231
+ // primereact discovers 0 components because it has no root barrel at all
232
+ // (every component lives under a subpath like `primereact/button`), which
233
+ // is pattern #8 — the adapter now reports that honestly via
234
+ // unresolvedReason instead of a false `installed: false`.
235
+ primereact: {
236
+ id: 'primereact',
237
+ label: 'PrimeReact',
238
+ distribution: 'installed-package',
239
+ npmPackage: 'primereact',
240
+ platform: 'web',
241
+ },
242
+ gluestack: {
243
+ id: 'gluestack',
244
+ label: 'gluestack-ui',
245
+ distribution: 'installed-package',
246
+ npmPackage: '@gluestack-ui/themed',
247
+ platform: 'native',
248
+ },
249
+ uiKitten: {
250
+ id: 'uiKitten',
251
+ label: 'UI Kitten (Eva Design)',
252
+ distribution: 'installed-package',
253
+ npmPackage: '@ui-kitten/components',
254
+ platform: 'native',
255
+ },
256
+ // Live-verified 2026-08-27 while probing whether it needed `npmPackages`.
257
+ // It does not — see the umbrella discussion in the block comment above
258
+ // `mui`: `@adobe/react-spectrum` enumerates all 101 components on its own,
259
+ // so it is registered by the umbrella and nothing else. Adding its
260
+ // `@react-spectrum/*` siblings alongside would double-count the shared
261
+ // catalog rather than widen it.
262
+ //
263
+ // Known limitation, specific to this entry's shape rather than a bug:
264
+ // coverage sees one import style at a time. Against a fixture importing
265
+ // from the umbrella this scored 3/101; against the same components
266
+ // imported from `@react-spectrum/button`/`-textfield` it scored 0/101,
267
+ // while the siblings scored the reverse. Adobe's docs teach the umbrella
268
+ // import, so that is the style registered for — but a repo that mixes both
269
+ // under-reports, and nothing warns about it yet.
270
+ spectrum: {
271
+ id: 'spectrum',
272
+ label: 'React Spectrum (Adobe)',
273
+ distribution: 'installed-package',
274
+ npmPackage: '@adobe/react-spectrum',
275
+ platform: 'web',
276
+ },
277
+ // The two below were live-verified 2026-08-27 against real npm installs in
278
+ // a throwaway fixture repo (an App.jsx importing five components each),
279
+ // scanned with `scan-foreign … --platform=native`.
280
+ //
281
+ // react-native-ui-lib@9.1.2 came back clean: types at `src/index.d.ts`,
282
+ // 71 components discovered, all five fixture imports counted, no
283
+ // unresolved entries and no duplicates. Worth noting for the next system
284
+ // with the same shape: its barrel contains `export * from 'uilib-native'`,
285
+ // a wildcard re-export from a sibling package, and discovery follows it
286
+ // without help.
287
+ uiLib: {
288
+ id: 'uiLib',
289
+ label: 'React Native UI Lib (Wix)',
290
+ distribution: 'installed-package',
291
+ npmPackage: 'react-native-ui-lib',
292
+ platform: 'native',
293
+ },
294
+ // @ant-design/react-native@5.4.3: types at `lib/index.d.ts`, 41 components
295
+ // discovered, three of the five fixture imports counted. Registered with
296
+ // its gap known rather than omitted, same as Restyle and PrimeReact above.
297
+ // Four barrel exports (Checkbox, Collapse, Input, List) are missed because
298
+ // they are declared as `typeof Internal & { …statics }` intersections —
299
+ // pattern #9 in installedPackageDiscoveryResolver.js, root-caused by
300
+ // reading the package's own .d.ts rather than inferred. A fifth absent
301
+ // export, ActionSheet, is excluded *correctly*: it declares only imperative
302
+ // methods (showActionSheetWithOptions, close), not a component.
303
+ antdRn: {
304
+ id: 'antdRn',
305
+ label: 'Ant Design Mobile RN',
306
+ distribution: 'installed-package',
307
+ npmPackage: '@ant-design/react-native',
308
+ platform: 'native',
309
+ },
310
+ };
311
+
312
+ /**
313
+ * The npm packages an entry's types come from, normalised to an array so no
314
+ * consumer has to know which of the two declaration forms an entry used —
315
+ * `[]` for a copy-paste system, which has no npm package at all.
316
+ *
317
+ * Single-string `npmPackage` was the only form until 2026-08-27, which made
318
+ * a system with no umbrella package unregisterable rather than merely
319
+ * untested — and the `atlaskit` entry above is what that cost in practice:
320
+ * `@atlaskit/button` was named as "the" package, so a repo using twenty
321
+ * @atlaskit/* siblings was scored against one sibling's four components.
322
+ * Multi-package entries are scanned per package and aggregated — see
323
+ * installedSystemScan.js.
324
+ */
325
+ export function systemPackages(system) {
326
+ if (Array.isArray(system.npmPackages)) return system.npmPackages;
327
+ return system.npmPackage ? [system.npmPackage] : [];
328
+ }
329
+
330
+ /** The tested-systems list surfaced by `scan-foreign` with no args and
331
+ * consulted by the auto-detector — a plain array so both consumers can
332
+ * map/filter without reaching into object-key iteration order.
333
+ * `npmPackage` stays the single primary package (first, for display and for
334
+ * the one-package case); `npmPackages` carries the full set. */
335
+ export function listForeignSystems() {
336
+ return Object.values(FOREIGN_SYSTEMS).map((system) => {
337
+ const packages = systemPackages(system);
338
+ return {
339
+ id: system.id,
340
+ label: system.label,
341
+ distribution: system.distribution,
342
+ npmPackage: packages[0] ?? null,
343
+ npmPackages: packages,
344
+ platform: system.platform,
345
+ };
346
+ });
347
+ }
348
+
349
+ export function getForeignSystem(systemId) {
350
+ const system = FOREIGN_SYSTEMS[systemId];
351
+ if (!system) {
352
+ const known = Object.keys(FOREIGN_SYSTEMS).join(', ');
353
+ throw new Error(`Unknown foreign system "${systemId}" — known systems: ${known}`);
354
+ }
355
+ return system;
356
+ }