@motion-proto/live-tokens 0.74.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +33 -38
  2. package/.claude/skills/live-tokens-create-component/SKILL copy.md +196 -0
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +198 -146
  4. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +95 -52
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +2 -2
  6. package/.claude/skills/live-tokens-create-component/references/linked-siblings.md +2 -2
  7. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +12 -12
  8. package/.claude/skills/live-tokens-create-component/references/token-naming.md +2 -1
  9. package/.claude/skills/live-tokens-create-page/SKILL.md +187 -0
  10. package/.claude/skills/live-tokens-create-page/references/interaction-sources.md +66 -0
  11. package/.claude/skills/live-tokens-create-page/references/layout-sources.md +87 -0
  12. package/.claude/skills/live-tokens-create-theme/SKILL.md +52 -48
  13. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
  14. package/.claude/skills/live-tokens-fix-findings/SKILL.md +69 -60
  15. package/.claude/skills/live-tokens-pick-component/SKILL.md +64 -79
  16. package/.claude/skills/live-tokens-set-colors/SKILL.md +47 -38
  17. package/.claude/skills/live-tokens-set-geometry/SKILL.md +58 -35
  18. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +5 -3
  19. package/.claude/skills/live-tokens-set-type/SKILL.md +30 -30
  20. package/CHANGELOG.md +138 -0
  21. package/README.md +17 -7
  22. package/bin/check-component.mjs +91 -19
  23. package/bin/check-page.mjs +102 -21
  24. package/bin/cli.mjs +87 -113
  25. package/bin/contractRunner.mjs +945 -0
  26. package/bin/create.mjs +1 -1
  27. package/bin/lib/catalogue.mjs +37 -30
  28. package/bin/lib/findings.mjs +46 -15
  29. package/bin/lib/report.mjs +3 -3
  30. package/bin/lib/tokenVocabulary.mjs +4 -4
  31. package/bin/migrate-routes.mjs +5 -5
  32. package/bin/migrate.mjs +4 -4
  33. package/bin/save-theme.mjs +8 -9
  34. package/bin/set-colors.mjs +9 -11
  35. package/bin/set-geometry.mjs +7 -7
  36. package/bin/set-type.mjs +5 -7
  37. package/bin/setup-claude.mjs +110 -0
  38. package/dist-plugin/{chunk-W6Y4BWFB.js → chunk-6WGFOJXO.js} +22 -0
  39. package/dist-plugin/{chunk-7VRTBGJT.js → chunk-PDNL4NC5.js} +9 -2
  40. package/dist-plugin/{chunk-V3YF6CGT.js → chunk-SWXRVZKT.js} +43 -1
  41. package/dist-plugin/{dataPaths-BhWzd5cL.d.cts → dataPaths-BpIK_Obx.d.cts} +1 -0
  42. package/dist-plugin/{dataPaths-BhWzd5cL.d.ts → dataPaths-BpIK_Obx.d.ts} +1 -0
  43. package/dist-plugin/index.cjs +310 -147
  44. package/dist-plugin/index.d.cts +1 -1
  45. package/dist-plugin/index.d.ts +1 -1
  46. package/dist-plugin/index.js +218 -122
  47. package/dist-plugin/migrateData/index.cjs +66 -2
  48. package/dist-plugin/migrateData/index.d.cts +1 -1
  49. package/dist-plugin/migrateData/index.d.ts +1 -1
  50. package/dist-plugin/migrateData/index.js +3 -3
  51. package/dist-plugin/setColors/index.cjs +61 -4
  52. package/dist-plugin/setColors/index.d.cts +1 -1
  53. package/dist-plugin/setColors/index.d.ts +1 -1
  54. package/dist-plugin/setColors/index.js +5 -5
  55. package/dist-plugin/setGeometry/index.cjs +107 -44
  56. package/dist-plugin/setGeometry/index.d.cts +5 -5
  57. package/dist-plugin/setGeometry/index.d.ts +5 -5
  58. package/dist-plugin/setGeometry/index.js +51 -45
  59. package/dist-plugin/setType/index.cjs +15 -0
  60. package/dist-plugin/setType/index.d.cts +1 -1
  61. package/dist-plugin/setType/index.d.ts +1 -1
  62. package/dist-plugin/setType/index.js +1 -1
  63. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  64. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  65. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  66. package/package.json +35 -8
  67. package/src/app/site.css +19 -9
  68. package/src/editor/bootstrap.ts +2 -0
  69. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +4 -4
  70. package/src/editor/component-editor/DialogEditor.svelte +4 -4
  71. package/src/editor/component-editor/MenuSelectEditor.svelte +4 -1
  72. package/src/editor/component-editor/SegmentedControlEditor.svelte +6 -1
  73. package/src/editor/component-editor/TabBarEditor.svelte +1 -1
  74. package/src/editor/component-editor/TableEditor.svelte +2 -2
  75. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +6 -3
  76. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +41 -20
  77. package/src/editor/core/components/adjustAliases.ts +59 -45
  78. package/src/editor/core/components/aliasKinds.ts +9 -5
  79. package/src/editor/core/preview/themePreview.ts +9 -2
  80. package/src/editor/core/sketch/sketchLayer.ts +22 -0
  81. package/src/editor/core/store/editorStore.ts +10 -1
  82. package/src/editor/core/themes/buildColors.ts +3 -3
  83. package/src/editor/core/themes/liveStateStream.ts +26 -0
  84. package/src/editor/core/themes/migrations/2026-09-07-stroke-role-renames.ts +52 -0
  85. package/src/editor/core/themes/migrations/index.ts +2 -0
  86. package/src/editor/core/themes/themeDocumentSync.ts +22 -11
  87. package/src/editor/core/themes/themeService.ts +9 -2
  88. package/src/editor/pages/ComponentEditorPage.svelte +17 -1
  89. package/src/editor/pages/liveTokensEditorHandle.ts +23 -0
  90. package/src/editor/skill-atlas/SkillAtlas.svelte +75 -573
  91. package/src/editor/skill-atlas/TreeCanvas.svelte +263 -0
  92. package/src/editor/skill-atlas/TreeNodeCard.svelte +136 -53
  93. package/src/editor/skill-atlas/edges.ts +31 -0
  94. package/src/editor/skill-atlas/skillSources.generated.ts +20 -19
  95. package/src/editor/skill-atlas/skillTrees.ts +19 -3840
  96. package/src/editor/skill-atlas/trees/check-compliance.ts +183 -0
  97. package/src/editor/skill-atlas/trees/create-component.ts +275 -0
  98. package/src/editor/skill-atlas/trees/create-page.ts +320 -0
  99. package/src/editor/skill-atlas/trees/create-theme.ts +255 -0
  100. package/src/editor/skill-atlas/trees/fix-findings.ts +469 -0
  101. package/src/editor/skill-atlas/trees/pick-component.ts +300 -0
  102. package/src/editor/skill-atlas/trees/set-colors.ts +148 -0
  103. package/src/editor/skill-atlas/trees/set-geometry.ts +136 -0
  104. package/src/editor/skill-atlas/trees/set-type.ts +142 -0
  105. package/src/editor/skill-atlas/types.ts +3 -4
  106. package/src/editor/skill-atlas/wireLayout.ts +287 -0
  107. package/src/live-tokens/data/themes/autumn.json +15 -15
  108. package/src/live-tokens/data/themes/halloween.json +15 -15
  109. package/src/live-tokens/data/themes/midnight-study.json +15 -15
  110. package/src/live-tokens/data/themes/ocean.json +15 -15
  111. package/src/live-tokens/data/themes/royal-velvet.json +15 -15
  112. package/src/live-tokens/data/themes/sketchy.json +15 -15
  113. package/src/live-tokens/data/themes/spring-meadow.json +15 -15
  114. package/src/live-tokens/data/themes/sunset.json +15 -15
  115. package/src/system/components/Badge.svelte +7 -0
  116. package/src/system/components/Button.svelte +7 -0
  117. package/src/system/components/Callout.svelte +10 -6
  118. package/src/system/components/Card.svelte +23 -4
  119. package/src/system/components/CodeSnippet.svelte +4 -3
  120. package/src/system/components/CollapsibleSection.svelte +23 -8
  121. package/src/system/components/CornerBadge.svelte +6 -0
  122. package/src/system/components/Dialog.svelte +13 -6
  123. package/src/system/components/IconButton.svelte +9 -0
  124. package/src/system/components/Image.svelte +8 -0
  125. package/src/system/components/ImageLightbox.svelte +6 -0
  126. package/src/system/components/InlineEditActions.svelte +7 -0
  127. package/src/system/components/Input.svelte +7 -0
  128. package/src/system/components/MenuSelect.svelte +7 -0
  129. package/src/system/components/Notification.svelte +7 -0
  130. package/src/system/components/Panel.svelte +6 -0
  131. package/src/system/components/ProgressBar.svelte +5 -0
  132. package/src/system/components/RadioButton.svelte +11 -5
  133. package/src/system/components/SectionDivider.svelte +8 -0
  134. package/src/system/components/SegmentedControl.svelte +6 -0
  135. package/src/system/components/SideNavigation.svelte +6 -0
  136. package/src/system/components/Slider.svelte +7 -4
  137. package/src/system/components/TabBar.svelte +15 -9
  138. package/src/system/components/Table.svelte +8 -3
  139. package/src/system/components/Toggle.svelte +4 -4
  140. package/src/system/components/Tooltip.svelte +6 -0
  141. package/src/testing-js/chunk-AO7EZHYV.js +776 -0
  142. package/src/testing-js/chunk-AO7EZHYV.js.map +1 -0
  143. package/src/testing-js/chunk-FAFOAWYL.js +39 -0
  144. package/src/testing-js/chunk-FAFOAWYL.js.map +1 -0
  145. package/src/testing-js/chunk-L73N4NSO.js +23 -0
  146. package/src/testing-js/chunk-L73N4NSO.js.map +1 -0
  147. package/src/testing-js/chunk-LXR3MN6N.js +3063 -0
  148. package/src/testing-js/chunk-LXR3MN6N.js.map +1 -0
  149. package/src/testing-js/chunk-ZMSX6CXR.js +53 -0
  150. package/src/testing-js/chunk-ZMSX6CXR.js.map +1 -0
  151. package/src/testing-js/component-alias.contract.js +81 -0
  152. package/src/testing-js/component-alias.contract.js.map +1 -0
  153. package/src/testing-js/component-editor.contract.js +62 -0
  154. package/src/testing-js/component-editor.contract.js.map +1 -0
  155. package/src/testing-js/component-render.contract.js +568 -0
  156. package/src/testing-js/component-render.contract.js.map +1 -0
  157. package/src/testing-js/index.d.ts +293 -0
  158. package/src/testing-js/index.js +222 -0
  159. package/src/testing-js/index.js.map +1 -0
  160. package/src/testing-js/registry.contract.js +39 -0
  161. package/src/testing-js/registry.contract.js.map +1 -0
  162. package/src/testing-js/vitest-BE6uGF31.d.ts +73 -0
  163. package/src/testing-js/vitest.d.ts +3 -0
  164. package/src/testing-js/vitest.js +13 -0
  165. package/src/testing-js/vitest.js.map +1 -0
  166. package/template/README.md +13 -0
  167. package/template/_gitignore +6 -0
  168. package/template/package.json +3 -1
  169. package/template/src/pages/Home.svelte +4 -18
  170. package/.claude/skills/live-tokens-build-page/SKILL.md +0 -103
  171. package/.claude/skills/live-tokens-build-page/references/layout-sources.md +0 -48
package/bin/cli.mjs CHANGED
@@ -4,26 +4,27 @@
4
4
  // create <dir> Scaffold a new app that depends on this package.
5
5
  // setup-claude [--force] Copy bundled Claude Code skills into ./.claude/skills/.
6
6
  // components [id] List every component the project has, shipped and its own, with props and tokens.
7
- // tokens [--family <name>] List every theme token by family, with its value.
7
+ // tokens [--scale <name>] List every design token by scale, with its value.
8
8
  // report The project as facts: tokens read, components used, findings by rule. Always exits 0.
9
9
  // check-component [id] Validate a component (or every authored one) against the create-component skill contract.
10
- // check-page [paths...] Validate pages against the build-page skill contract.
10
+ // check-page [paths...] Validate pages against the create-page skill contract.
11
11
  // set-colors <colors> Build the color identity from 10 OKLCH base colors, into the open buffer.
12
12
  // set-geometry <ops> Apply radius/padding/gap/border-width ops to the open buffer.
13
13
  // set-type <pairing> Bind Google Fonts families to the theme's font stacks.
14
14
  // save-theme <name> Compose the live state into themes/<slug>.json and open it.
15
15
  // migrate [...] Reconcile tokens.css, the data tree, and route references.
16
16
 
17
- import { cpSync, existsSync, mkdirSync, readdirSync, statSync, writeSync } from 'node:fs';
17
+ import { writeSync } from 'node:fs';
18
18
  import { dirname, join, resolve } from 'node:path';
19
19
  import { fileURLToPath } from 'node:url';
20
20
  import process from 'node:process';
21
- import { COMPONENT_RULES, checkComponent, discoverComponents, formatReport } from './check-component.mjs';
21
+ import { COMPONENT_RULES, COMPONENT_RULE_FIX, checkComponent, discoverComponents, formatReport } from './check-component.mjs';
22
22
  import { PAGE_RULES, checkPages, discoverPages } from './check-page.mjs';
23
23
  import { describeComponents, describeTokens, formatComponents, formatTokens } from './lib/catalogue.mjs';
24
24
  import { buildReport, formatReport as formatProjectReport } from './lib/report.mjs';
25
25
  import { loadVocabulary } from './lib/tokenVocabulary.mjs';
26
26
  import {
27
+ applyCoverageSeverity,
27
28
  applySeverity,
28
29
  countBySeverity,
29
30
  formatFindings,
@@ -39,6 +40,7 @@ import {
39
40
  } from './migrate.mjs';
40
41
  import { runMigrateRoutes, formatRouteResult } from './migrate-routes.mjs';
41
42
  import { runCreate, formatCreateResult } from './create.mjs';
43
+ import { runSetupClaude, formatSetupResult } from './setup-claude.mjs';
42
44
  import { runSetColors, formatSetColorsResult } from './set-colors.mjs';
43
45
  import { runSetGeometry, formatSetGeometryResult } from './set-geometry.mjs';
44
46
  import { runSetType, formatSetTypeResult } from './set-type.mjs';
@@ -48,27 +50,33 @@ const USAGE = `Usage: npx @motion-proto/live-tokens <command> [options]
48
50
 
49
51
  Commands:
50
52
  create <dir> [--force] Scaffold a new Svelte + Vite app wired up with
51
- live-tokens (editor, components, theme tokens)
53
+ live-tokens (editor, components, design tokens)
52
54
  setup-claude [--force] Install bundled Claude Code skills into ./.claude/skills/
53
55
  components [id] [--json] List every component the project has, shipped and
54
56
  its own (src/system/components plus any
55
- "componentDirs" in live-tokens.config.json), with
56
- the props each takes; with an id, that component's
57
- props, variants, tokens, and defaults
58
- tokens [--family <name>] [--json]
59
- List every theme token the project's tokens.css
60
- declares, by family, with its value
57
+ "componentDirs" in live-tokens.config.json). With
58
+ an id, that component's props, variants, tokens,
59
+ and defaults
60
+ tokens [--scale <name>] [--json]
61
+ List every design token the project's tokens.css
62
+ declares, by scale, with its value
61
63
  report [--json] The project as facts: pending migrations, tokens
62
64
  each component declares and reads, which page
63
65
  renders which component, and both checkers'
64
66
  findings by rule under the project's severities
65
- and under --strict. A reading, not a gate: always
66
- exits 0
67
- check-component [id] Validate <id>'s runtime, editor, and registration
68
- against the live-tokens-create-component contract
69
- check-page [paths...] Validate pages against the live-tokens-build-page
67
+ and under --strict. Always exits 0
68
+ check-component [id] [--tests]
69
+ Validate <id>'s runtime, editor, and registration
70
+ against the live-tokens-create-component contract.
71
+ --tests also runs the registry contract under
72
+ vitest and the component contract suites under
73
+ Playwright, reporting coverage by rule. Needs
74
+ @playwright/test, vitest, and happy-dom; a
75
+ missing one is a tests-not-installed finding
76
+ naming the install command
77
+ check-page [paths...] Validate pages against the live-tokens-create-page
70
78
  contract: catalogue components only, and every CSS
71
- value a theme token. Checks every page under src/
79
+ value a design token. Checks every page under src/
72
80
  when given no paths.
73
81
 
74
82
  check-component and check-page also accept:
@@ -84,44 +92,42 @@ check-component and check-page also accept:
84
92
  OKLCH base colors (see the live-tokens-set-colors
85
93
  skill) and enforce AA contrast on the derived text
86
94
  tokens. Reads the live colors and type and writes
87
- the result to the unsaved colors-and-type buffer,
88
- so save the open theme in the editor or run
89
- save-theme to keep it. Fonts and every override no
90
- palette owns carry forward. --dry-run prints the
91
- contrast report without writing.
95
+ the result to the colors-and-type buffer. Run
96
+ save-theme to keep it as a theme. Fonts and every
97
+ override no palette owns carry forward. --dry-run
98
+ prints the contrast report without writing.
92
99
  set-geometry <ops.json> [--dry-run]
93
100
  Move radius, padding, gap, and border-width
94
101
  aliases along their token scales (see the
95
102
  live-tokens-set-geometry skill). Reads each
96
103
  component's live config and writes the result to
97
- that component's unsaved buffer, so save the open
98
- theme in the editor to keep it. --dry-run prints
99
- the report without writing.
104
+ that component's buffer. Run save-theme to keep it
105
+ as a theme. --dry-run prints the report without
106
+ writing.
100
107
  set-type <pairing.json> [--dry-run] [--no-verify]
101
108
  Bind Google Fonts families to --font-display,
102
109
  --font-sans, --font-serif, --font-mono and
103
110
  --font-editorial (see
104
111
  the live-tokens-set-type skill). Each family is
105
112
  verified against the Google Fonts API and the URL
106
- is negotiated from the weights it actually has.
107
- Writes the result to the unsaved colors-and-type
108
- buffer, so save the open theme in the editor to
109
- keep it. --dry-run prints the report without
110
- writing; --no-verify skips the network and
111
- requires an explicit URL per family.
113
+ is negotiated from the weights it has. Writes the
114
+ result to the colors-and-type buffer. Run
115
+ save-theme to keep it as a theme. --dry-run prints
116
+ the report without writing. --no-verify skips the
117
+ network and requires an explicit URL per family.
112
118
  save-theme <name> [--no-activate] [--dry-run]
113
- Compose the live state (the unsaved buffers, the
114
- open theme under them, the shipped defaults under
115
- that) into themes/<slug>.json and open it, which
116
- clears the buffers. With no unsaved edits it saves
117
- a copy of the open theme under the new name.
118
- Opening never changes what your site ships; Adopt
119
- in the editor does that. --no-activate writes the
120
- theme and leaves the live state alone, so a set of
121
- themes comes off one starting look; --dry-run
122
- prints the report without writing.
119
+ Compose the live state (the buffers, the open
120
+ theme under them, the shipped defaults under that)
121
+ into themes/<slug>.json and load it, which clears
122
+ the buffers. With no buffer it saves a copy of the
123
+ open theme under the new name. Loading never
124
+ changes what the site ships. Adopt in the editor
125
+ does that. --no-activate writes the theme and does
126
+ not load it, so a set of themes comes off one
127
+ starting theme. --dry-run prints the report
128
+ without writing.
123
129
  migrate [--check] [--write] [--tokens <path>]
124
- Reconcile your project with the installed package:
130
+ Reconcile the project with the installed package:
125
131
  applies additive tokens.css migrations, moves a
126
132
  pre-0.48 data tree onto the current directory
127
133
  names, heals what the retired pointer files named,
@@ -177,14 +183,19 @@ if (command === 'create') {
177
183
  }
178
184
  }
179
185
 
180
- function reportChecks(label, findings, checked, rules, opts) {
181
- const resolved = applySeverity(findings, rules, opts, readChecksConfig(process.cwd()));
186
+ function reportChecks(label, findings, checked, rules, opts, { coverage, hardFailure, fixes } = {}) {
187
+ const checksConfig = readChecksConfig(process.cwd());
188
+ const resolved = applySeverity(findings, rules, opts, checksConfig, fixes ?? {});
189
+ const resolvedCoverage = coverage ? applyCoverageSeverity(coverage, rules, opts, checksConfig) : coverage;
182
190
  console.log(
183
191
  opts.json
184
- ? toJson(resolved, { label, checked })
192
+ ? toJson(resolved, { label, checked, coverage: resolvedCoverage })
185
193
  : formatFindings(resolved, { label, checked }),
186
194
  );
187
- process.exit(countBySeverity(resolved).errors === 0 ? 0 : 1);
195
+ // Decision 2: a missing tool or a setup failure under --tests is an error
196
+ // even if a project silenced its rule id, since silencing it would read as
197
+ // "the tests passed" rather than "the tests did not run".
198
+ process.exit(countBySeverity(resolved).errors === 0 && !hardFailure ? 0 : 1);
188
199
  }
189
200
 
190
201
  if (command === 'components') {
@@ -198,14 +209,14 @@ if (command === 'components') {
198
209
 
199
210
  if (command === 'tokens') {
200
211
  const opts = parseCheckFlags(rest);
201
- const at = opts.rest.indexOf('--family');
202
- const family = at >= 0 ? opts.rest[at + 1] : undefined;
212
+ const at = opts.rest.indexOf('--scale');
213
+ const scale = at >= 0 ? opts.rest[at + 1] : undefined;
203
214
  const desc = describeTokens(loadVocabulary());
204
- if (family && !desc.families.some((f) => f.family === family)) fail(formatTokens(desc, { family }));
215
+ if (scale && !desc.scales.some((s) => s.scale === scale)) fail(formatTokens(desc, { scale }));
205
216
  writeOut(
206
217
  opts.json
207
- ? JSON.stringify(family ? desc.families.find((f) => f.family === family) : desc, null, 2)
208
- : formatTokens(desc, { family }),
218
+ ? JSON.stringify(scale ? desc.scales.find((s) => s.scale === scale) : desc, null, 2)
219
+ : formatTokens(desc, { scale }),
209
220
  );
210
221
  process.exit(0);
211
222
  }
@@ -231,18 +242,28 @@ if (command === 'report') {
231
242
  if (command === 'check-component') {
232
243
  const opts = parseCheckFlags(rest);
233
244
  const ids = opts.rest.length > 0 ? [opts.rest[0]] : discoverComponents();
234
- if (ids.length === 0) {
245
+ if (ids.length === 0 && !opts.tests) {
235
246
  console.log('✓ check-component: no component authored under src/system/components yet.');
236
247
  process.exit(0);
237
248
  }
238
249
  const results = ids.map((id) => [id, checkComponent(id)]);
239
- if (ids.length === 1 && !opts.json && !opts.strict && opts.off.length + opts.warn.length + opts.error.length === 0) {
250
+ if (!opts.tests && ids.length === 1 && !opts.json && !opts.strict && opts.off.length + opts.warn.length + opts.error.length === 0) {
240
251
  const [id, result] = results[0];
241
252
  console.log(formatReport(id, result));
242
253
  process.exit(result.errors.length === 0 ? 0 : 1);
243
254
  }
244
- const label = ids.length === 1 ? `check-component ${ids[0]}` : 'check-component';
245
- reportChecks(label, results.flatMap(([, r]) => r.findings), ids.length, COMPONENT_RULES, opts);
255
+ const label = ids.length === 1 ? `check-component ${ids[0]}${opts.tests ? ' --tests' : ''}` : `check-component${opts.tests ? ' --tests' : ''}`;
256
+ if (!opts.tests) {
257
+ reportChecks(label, results.flatMap(([, r]) => r.findings), ids.length, COMPONENT_RULES, opts, { fixes: COMPONENT_RULE_FIX });
258
+ }
259
+ const { hasHardFailure, runContractTests } = await import('./contractRunner.mjs');
260
+ const testOutcome = await runContractTests(opts.rest[0], { root: process.cwd() });
261
+ const findings = [...results.flatMap(([, r]) => r.findings), ...testOutcome.findings];
262
+ reportChecks(label, findings, Math.max(ids.length, 1), COMPONENT_RULES, opts, {
263
+ fixes: COMPONENT_RULE_FIX,
264
+ coverage: testOutcome.coverage,
265
+ hardFailure: hasHardFailure(testOutcome.findings),
266
+ });
246
267
  }
247
268
 
248
269
  if (command === 'check-page') {
@@ -265,7 +286,7 @@ if (command === 'set-colors') {
265
286
  }
266
287
  if (rest.includes('--carry-from')) {
267
288
  fail(
268
- `set-colors has no --carry-from: it reads the live look and edits it in place, so a second theme ` +
289
+ `set-colors has no --carry-from: it reads the live theme and edits it in place, so a second theme ` +
269
290
  `already starts from the first. Run save-theme --no-activate between themes.`,
270
291
  );
271
292
  }
@@ -387,61 +408,14 @@ if (process.platform === 'win32') {
387
408
  fail('setup-claude is macOS/Linux only.');
388
409
  }
389
410
 
390
- const force = rest.includes('--force');
391
-
392
- const srcSkills = join(pkgRoot, '.claude', 'skills');
393
-
394
- if (!existsSync(srcSkills)) {
395
- fail(`No bundled skills found at ${srcSkills}. Is the package installed correctly?`);
396
- }
397
-
398
- const skills = readdirSync(srcSkills).filter((name) =>
399
- statSync(join(srcSkills, name)).isDirectory(),
400
- );
401
-
402
- if (skills.length === 0) {
403
- fail('No bundled skills to install.');
404
- }
405
-
406
- const destSkills = join(process.cwd(), '.claude', 'skills');
407
- mkdirSync(destSkills, { recursive: true });
408
-
409
- let installed = 0;
410
- let skipped = 0;
411
- for (const skill of skills) {
412
- const src = join(srcSkills, skill);
413
- const dest = join(destSkills, skill);
414
- if (existsSync(dest) && !force) {
415
- console.log(` skip ${skill} (already exists; pass --force to overwrite)`);
416
- skipped++;
417
- continue;
418
- }
419
- cpSync(src, dest, { recursive: true });
420
- console.log(` ok ${skill}`);
421
- installed++;
422
- }
423
-
424
- console.log(`\n${installed} installed, ${skipped} skipped → ${destSkills}`);
425
-
426
- const SAMPLE_PROMPTS = {
427
- 'live-tokens-build-page': 'build a pricing page using live-tokens components',
428
- 'live-tokens-pick-component': "what's the difference between TabBar and SegmentedControl?",
429
- 'live-tokens-create-component': 'author a new Toggle component for my live-tokens project',
430
- 'live-tokens-create-theme': 'make me a bright and cheerful theme',
431
- 'live-tokens-set-colors': 'give me a cooler palette, same fonts',
432
- 'live-tokens-set-type': 'pair some fonts for this theme',
433
- 'live-tokens-set-geometry': 'make the buttons pill shaped',
434
- 'live-tokens-fix-findings': 'make check:design pass',
435
- 'live-tokens-check-compliance': 'check this project against the design system',
436
- };
437
-
438
- const installedSamples = skills
439
- .map((s) => SAMPLE_PROMPTS[s] && [s, SAMPLE_PROMPTS[s]])
440
- .filter(Boolean);
441
-
442
- if (installedSamples.length > 0) {
443
- console.log(`\nIn Claude Code, prompts like these auto-trigger the matching skill:`);
444
- for (const [skill, prompt] of installedSamples) {
445
- console.log(` • "${prompt}"\n → ${skill}`);
446
- }
411
+ try {
412
+ const result = runSetupClaude({
413
+ pkgRoot,
414
+ cwd: process.cwd(),
415
+ force: rest.includes('--force'),
416
+ });
417
+ console.log(formatSetupResult(result));
418
+ process.exit(0);
419
+ } catch (err) {
420
+ fail(err instanceof Error ? err.message : String(err));
447
421
  }