roast-my-design-system 7.3.2 → 7.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roast-my-design-system",
3
- "version": "7.3.2",
3
+ "version": "7.3.3",
4
4
  "mcpName": "io.github.gregkozakiewicz/roast-my-design-system",
5
5
  "description": "Your AI can write the UI. This makes sure it writes your UI. A deterministic scanner scores your design system 0-100 against 34 public repos, reads React and web components (Stencil, Lit), hands you a copy-paste fix prompt for each top finding, writes rules for Claude, Cursor, Copilot and Windsurf with --apply, and runs as a local MCP server with --mcp.",
6
6
  "keywords": [
@@ -1852,8 +1852,8 @@
1852
1852
  },
1853
1853
  "slices": {
1854
1854
  "shadcn": {
1855
- "builtAt": "2026-09-12T00:06:00.881Z",
1856
- "repoCount": 17,
1855
+ "builtAt": "2026-09-12T19:02:27.297Z",
1856
+ "repoCount": 16,
1857
1857
  "note": "every repo in the fleet the scanner reads as shadcn; the \"cleaner than\" line on a shadcn repo reads against these",
1858
1858
  "stats": {
1859
1859
  "colors": {
@@ -1867,7 +1867,6 @@
1867
1867
  56,
1868
1868
  66,
1869
1869
  115,
1870
- 118,
1871
1870
  132,
1872
1871
  174,
1873
1872
  187,
@@ -1876,10 +1875,10 @@
1876
1875
  310,
1877
1876
  1030
1878
1877
  ],
1879
- "p25": 41,
1880
- "median": 115,
1881
- "p75": 187,
1882
- "p90": 283
1878
+ "p25": 39,
1879
+ "median": 91,
1880
+ "p75": 204,
1881
+ "p90": 288
1883
1882
  },
1884
1883
  "greys": {
1885
1884
  "values": [
@@ -1893,7 +1892,6 @@
1893
1892
  12,
1894
1893
  14,
1895
1894
  16,
1896
- 22,
1897
1895
  33,
1898
1896
  38,
1899
1897
  51,
@@ -1902,9 +1900,9 @@
1902
1900
  111
1903
1901
  ],
1904
1902
  "p25": 4,
1905
- "median": 14,
1906
- "p75": 38,
1907
- "p90": 58
1903
+ "median": 13,
1904
+ "p75": 41,
1905
+ "p90": 59
1908
1906
  },
1909
1907
  "spacing": {
1910
1908
  "values": [
@@ -1920,16 +1918,15 @@
1920
1918
  34,
1921
1919
  40,
1922
1920
  45,
1923
- 49,
1924
1921
  59,
1925
1922
  66,
1926
1923
  120,
1927
1924
  220
1928
1925
  ],
1929
1926
  "p25": 11,
1930
- "median": 32,
1927
+ "median": 29,
1931
1928
  "p75": 49,
1932
- "p90": 88
1929
+ "p90": 93
1933
1930
  },
1934
1931
  "typefaces": {
1935
1932
  "values": [
@@ -1945,7 +1942,6 @@
1945
1942
  3,
1946
1943
  3,
1947
1944
  3,
1948
- 3,
1949
1945
  5,
1950
1946
  6,
1951
1947
  8,
@@ -1953,7 +1949,7 @@
1953
1949
  ],
1954
1950
  "p25": 2,
1955
1951
  "median": 3,
1956
- "p75": 3,
1952
+ "p75": 4,
1957
1953
  "p90": 7
1958
1954
  },
1959
1955
  "fontSizes": {
@@ -1971,14 +1967,13 @@
1971
1967
  27,
1972
1968
  27,
1973
1969
  42,
1974
- 43,
1975
1970
  49,
1976
1971
  49,
1977
1972
  79
1978
1973
  ],
1979
1974
  "p25": 12,
1980
1975
  "median": 21,
1981
- "p75": 42,
1976
+ "p75": 31,
1982
1977
  "p90": 49
1983
1978
  },
1984
1979
  "radii": {
@@ -1997,13 +1992,12 @@
1997
1992
  20,
1998
1993
  21,
1999
1994
  26,
2000
- 28,
2001
1995
  34,
2002
1996
  50
2003
1997
  ],
2004
1998
  "p25": 11,
2005
1999
  "median": 14,
2006
- "p75": 21,
2000
+ "p75": 20,
2007
2001
  "p90": 30
2008
2002
  },
2009
2003
  "shadows": {
@@ -2015,7 +2009,6 @@
2015
2009
  0,
2016
2010
  0,
2017
2011
  0,
2018
- 0,
2019
2012
  1,
2020
2013
  1,
2021
2014
  2,
@@ -2028,7 +2021,7 @@
2028
2021
  ],
2029
2022
  "p25": 0,
2030
2023
  "median": 1,
2031
- "p75": 4,
2024
+ "p75": 5,
2032
2025
  "p90": 10
2033
2026
  },
2034
2027
  "exactDuplicates": {
@@ -2042,7 +2035,6 @@
2042
2035
  17,
2043
2036
  20,
2044
2037
  21,
2045
- 23,
2046
2038
  25,
2047
2039
  61,
2048
2040
  65,
@@ -2051,10 +2043,10 @@
2051
2043
  134,
2052
2044
  288
2053
2045
  ],
2054
- "p25": 14,
2046
+ "p25": 11,
2055
2047
  "median": 21,
2056
- "p75": 65,
2057
- "p90": 116
2048
+ "p75": 74,
2049
+ "p90": 119
2058
2050
  },
2059
2051
  "inlineStyles": {
2060
2052
  "values": [
@@ -2068,7 +2060,6 @@
2068
2060
  42,
2069
2061
  47,
2070
2062
  47,
2071
- 49,
2072
2063
  58,
2073
2064
  74,
2074
2065
  79,
@@ -2076,10 +2067,10 @@
2076
2067
  120,
2077
2068
  263
2078
2069
  ],
2079
- "p25": 11,
2080
- "median": 47,
2081
- "p75": 74,
2082
- "p90": 118
2070
+ "p25": 10,
2071
+ "median": 45,
2072
+ "p75": 75,
2073
+ "p90": 119
2083
2074
  },
2084
2075
  "arbitrary": {
2085
2076
  "values": [
@@ -2097,14 +2088,13 @@
2097
2088
  385,
2098
2089
  386,
2099
2090
  614,
2100
- 622,
2101
2091
  1625,
2102
2092
  1673
2103
2093
  ],
2104
2094
  "p25": 101,
2105
- "median": 169,
2106
- "p75": 386,
2107
- "p90": 1023
2095
+ "median": 166,
2096
+ "p75": 385,
2097
+ "p90": 1120
2108
2098
  },
2109
2099
  "nearPairs": {
2110
2100
  "values": [
@@ -2118,7 +2108,6 @@
2118
2108
  8,
2119
2109
  10,
2120
2110
  11,
2121
- 15,
2122
2111
  16,
2123
2112
  18,
2124
2113
  18,
@@ -2127,7 +2116,7 @@
2127
2116
  59
2128
2117
  ],
2129
2118
  "p25": 1,
2130
- "median": 10,
2119
+ "median": 9,
2131
2120
  "p75": 18,
2132
2121
  "p90": 21
2133
2122
  },
@@ -2140,7 +2129,6 @@
2140
2129
  0,
2141
2130
  0,
2142
2131
  1,
2143
- 1,
2144
2132
  2,
2145
2133
  9,
2146
2134
  9,
@@ -2152,9 +2140,9 @@
2152
2140
  157
2153
2141
  ],
2154
2142
  "p25": 0,
2155
- "median": 2,
2143
+ "median": 6,
2156
2144
  "p75": 42,
2157
- "p90": 70
2145
+ "p90": 74
2158
2146
  },
2159
2147
  "neverImported": {
2160
2148
  "values": [
@@ -2166,7 +2154,6 @@
2166
2154
  2,
2167
2155
  5,
2168
2156
  13,
2169
- 16,
2170
2157
  19,
2171
2158
  23,
2172
2159
  26,
@@ -2178,8 +2165,8 @@
2178
2165
  ],
2179
2166
  "p25": 1,
2180
2167
  "median": 16,
2181
- "p75": 30,
2182
- "p90": 96
2168
+ "p75": 34,
2169
+ "p90": 97
2183
2170
  },
2184
2171
  "components": {
2185
2172
  "values": [
@@ -2198,13 +2185,12 @@
2198
2185
  1204,
2199
2186
  1453,
2200
2187
  1494,
2201
- 1594,
2202
2188
  3630
2203
2189
  ],
2204
- "p25": 316,
2205
- "median": 911,
2206
- "p75": 1204,
2207
- "p90": 1534
2190
+ "p25": 305,
2191
+ "median": 861,
2192
+ "p75": 1154,
2193
+ "p90": 1474
2208
2194
  },
2209
2195
  "paintTin": {
2210
2196
  "values": [
@@ -2223,13 +2209,12 @@
2223
2209
  100,
2224
2210
  183,
2225
2211
  296,
2226
- 491,
2227
- 658
2212
+ 491
2228
2213
  ],
2229
2214
  "p25": 22,
2230
- "median": 57,
2231
- "p75": 100,
2232
- "p90": 374
2215
+ "median": 50,
2216
+ "p75": 75,
2217
+ "p90": 240
2233
2218
  },
2234
2219
  "doorOverrides": {
2235
2220
  "values": [
@@ -2247,14 +2232,13 @@
2247
2232
  26,
2248
2233
  28,
2249
2234
  31,
2250
- 40,
2251
2235
  44,
2252
2236
  55
2253
2237
  ],
2254
2238
  "p25": 13,
2255
2239
  "median": 17,
2256
- "p75": 28,
2257
- "p90": 42
2240
+ "p75": 27,
2241
+ "p90": 38
2258
2242
  }
2259
2243
  },
2260
2244
  "repos": [
@@ -2420,33 +2404,6 @@
2420
2404
  "doorOverrides": 22
2421
2405
  }
2422
2406
  },
2423
- {
2424
- "repo": "dubinc/dub",
2425
- "confidence": "medium",
2426
- "style": null,
2427
- "baseColor": null,
2428
- "tailwind": null,
2429
- "codeFiles": 4160,
2430
- "ownFiles": 1389,
2431
- "metrics": {
2432
- "colors": 118,
2433
- "greys": 22,
2434
- "spacing": 49,
2435
- "typefaces": 3,
2436
- "fontSizes": 43,
2437
- "radii": 28,
2438
- "shadows": 0,
2439
- "exactDuplicates": 23,
2440
- "inlineStyles": 49,
2441
- "arbitrary": 622,
2442
- "nearPairs": 15,
2443
- "important": 1,
2444
- "neverImported": 16,
2445
- "components": 1594,
2446
- "paintTin": 658,
2447
- "doorOverrides": 40
2448
- }
2449
- },
2450
2407
  {
2451
2408
  "repo": "formbricks/formbricks",
2452
2409
  "confidence": "high",
@@ -1,7 +1,7 @@
1
1
  // Single version constant for the engine — imported by diagnose (report
2
2
  // footer) and rules (generated-by line). This is the bump spot that used to
3
3
  // live as a const inside diagnose/index.mjs.
4
- export const VERSION = '7.3.2';
4
+ export const VERSION = '7.3.3';
5
5
  // The shape of harvest.json and summary.json. Bumped only when a field is
6
6
  // renamed, removed or changes meaning; a new field is not a new schema. A
7
7
  // tool comparing two scans compares like with like by this number, not by VERSION.
@@ -93,6 +93,25 @@ function resolveAlias(root, wsRoot, alias) {
93
93
  return null;
94
94
  }
95
95
 
96
+ /**
97
+ * The theme contract is the real signature of a shadcn install: the named
98
+ * variables (background, foreground, primary, muted, border, ring...) defined
99
+ * in a stylesheet. Door names and Radix imports are not enough. dubinc/dub
100
+ * has 12 catalogue-named files on Radix and cva, no components.json and 0 of
101
+ * these variables: its own token system, a shadcn ancestry, not a shadcn
102
+ * install. It was read as one from 7.2.0 to 7.3.2 (2026-09-13).
103
+ */
104
+ const CONTRACT_ROWS = ['background', 'foreground', 'primary', 'muted', 'border', 'ring', 'accent', 'card', 'popover', 'destructive'];
105
+ function themeContract(root, files) {
106
+ const seen = new Set();
107
+ for (const f of (files.styles ?? []).slice(0, 60)) {
108
+ const css = read(join(root, f));
109
+ for (const r of CONTRACT_ROWS) if (!seen.has(r) && new RegExp(`--${r}\\s*:`).test(css)) seen.add(r);
110
+ if (seen.size === CONTRACT_ROWS.length) break;
111
+ }
112
+ return seen.size;
113
+ }
114
+
96
115
  /** Rows declared under a selector in a CSS text: name -> value. */
97
116
  function rowsUnder(css, selector) {
98
117
  const out = new Map();
@@ -209,11 +228,14 @@ export default {
209
228
  else { const i = installs.find((x) => x.uiDir === s.dir); i.catalogueNames = Math.max(i.catalogueNames, s.catalogueNames); }
210
229
  }
211
230
 
212
- // 3. the decision: a marker plus a folder, or a folder that is plainly the
213
- // catalogue by name (8+). Same bar the profiler used for vendoredUi.
231
+ // 3. the decision. With components.json: the CLI's own marker plus a
232
+ // catalogue folder. Without it: a catalogue by name AND the theme contract
233
+ // in a stylesheet (5 or more of shadcn's named variables); names and
234
+ // Radix alone describe half the React world.
235
+ const contract = themeContract(root, files);
214
236
  const withConfigAndDir = installs.filter((i) => i.config && i.uiDir);
215
237
  const byName = installs.filter((i) => i.catalogueNames >= 8);
216
- if (!withConfigAndDir.length && !byName.length) return null;
238
+ if (!withConfigAndDir.length && !(byName.length && contract >= 5)) return null;
217
239
 
218
240
  installs.sort((a, b) => b.catalogueNames - a.catalogueNames || (b.config ? 1 : 0) - (a.config ? 1 : 0));
219
241
  const primary = installs[0];
@@ -229,6 +251,7 @@ export default {
229
251
  if (i.config) evidence.push(`components.json in ${dirname(i.config) === '.' ? 'the root' : dirname(i.config)}${i.uiDir ? `, ${i.catalogueNames} catalogue component${i.catalogueNames === 1 ? '' : 's'} in ${i.uiDir}` : ', no catalogue folder found through its alias'}`);
230
252
  else evidence.push(`${i.catalogueNames} catalogue components in ${i.uiDir}, no components.json`);
231
253
  }
254
+ evidence.push(contract ? `${contract} of shadcn's ${CONTRACT_ROWS.length} theme variables defined` : 'no shadcn theme variables found in any stylesheet');
232
255
  if (kit?.style) evidence.push(`style ${kit.style}${kit.baseColor ? `, base colour ${kit.baseColor}` : ''}${kit.tailwind ? `, Tailwind ${kit.tailwind}` : ''}`);
233
256
 
234
257
  // 4. write the facts every consumer reads