@design-ai/cli 4.55.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 (529) hide show
  1. package/.claude-plugin/plugin.json +164 -0
  2. package/AGENTS.ko.md +126 -0
  3. package/AGENTS.md +182 -0
  4. package/CHANGELOG.md +6883 -0
  5. package/CLAUDE.md +39 -0
  6. package/LICENSE +21 -0
  7. package/README.ko.md +245 -0
  8. package/README.md +277 -0
  9. package/agents/README.md +14 -0
  10. package/agents/a11y-reviewer.md +121 -0
  11. package/agents/component-architect.md +57 -0
  12. package/agents/design-critic.md +46 -0
  13. package/agents/token-extractor.md +63 -0
  14. package/cli/bin/design-ai-mcp.mjs +6 -0
  15. package/cli/bin/design-ai.mjs +40 -0
  16. package/cli/commands/audit.mjs +111 -0
  17. package/cli/commands/check.mjs +226 -0
  18. package/cli/commands/doctor.mjs +141 -0
  19. package/cli/commands/examples.mjs +58 -0
  20. package/cli/commands/help.mjs +271 -0
  21. package/cli/commands/install.mjs +161 -0
  22. package/cli/commands/learn.mjs +1871 -0
  23. package/cli/commands/list.mjs +143 -0
  24. package/cli/commands/mcp.mjs +27 -0
  25. package/cli/commands/pack.mjs +211 -0
  26. package/cli/commands/prompt.mjs +199 -0
  27. package/cli/commands/route.mjs +247 -0
  28. package/cli/commands/search.mjs +60 -0
  29. package/cli/commands/show.mjs +52 -0
  30. package/cli/commands/site.mjs +558 -0
  31. package/cli/commands/status.mjs +161 -0
  32. package/cli/commands/uninstall.mjs +119 -0
  33. package/cli/commands/update.mjs +184 -0
  34. package/cli/commands/version.mjs +94 -0
  35. package/cli/commands/workspace.mjs +176 -0
  36. package/cli/lib/brief.mjs +52 -0
  37. package/cli/lib/check.mjs +642 -0
  38. package/cli/lib/dispatch.mjs +109 -0
  39. package/cli/lib/doctor.mjs +505 -0
  40. package/cli/lib/examples.mjs +258 -0
  41. package/cli/lib/exec.mjs +63 -0
  42. package/cli/lib/help-flags.mjs +5 -0
  43. package/cli/lib/learn.mjs +3694 -0
  44. package/cli/lib/log.mjs +47 -0
  45. package/cli/lib/mcp-server.mjs +426 -0
  46. package/cli/lib/output.mjs +101 -0
  47. package/cli/lib/pack.mjs +599 -0
  48. package/cli/lib/paths.mjs +63 -0
  49. package/cli/lib/prompt.mjs +603 -0
  50. package/cli/lib/route.mjs +740 -0
  51. package/cli/lib/search.mjs +158 -0
  52. package/cli/lib/show.mjs +161 -0
  53. package/cli/lib/signals.mjs +2337 -0
  54. package/cli/lib/site.mjs +6617 -0
  55. package/cli/lib/skill-proposals.mjs +2046 -0
  56. package/cli/lib/suggest.mjs +66 -0
  57. package/cli/lib/workspace.mjs +1056 -0
  58. package/commands/README.md +25 -0
  59. package/commands/component-spec.md +34 -0
  60. package/commands/conversational.md +44 -0
  61. package/commands/design-from-brief.md +141 -0
  62. package/commands/design-review.md +62 -0
  63. package/commands/document-from-brief.md +47 -0
  64. package/commands/extract-tokens.md +38 -0
  65. package/commands/game-ui.md +40 -0
  66. package/commands/illustration.md +37 -0
  67. package/commands/iterate.md +167 -0
  68. package/commands/motion-design.md +54 -0
  69. package/commands/palette-from-brand.md +50 -0
  70. package/commands/print.md +49 -0
  71. package/commands/slide-deck.md +46 -0
  72. package/commands/spatial.md +47 -0
  73. package/commands/stability-review.md +74 -0
  74. package/commands/video.md +42 -0
  75. package/commands/website-improvement.md +77 -0
  76. package/docs/AGENT-DEVELOPMENT.md +658 -0
  77. package/docs/AI-LEARNING.md +429 -0
  78. package/docs/AIDER-INTEGRATION.md +224 -0
  79. package/docs/ARCHITECTURE.ko.md +183 -0
  80. package/docs/ARCHITECTURE.md +105 -0
  81. package/docs/CODEX-INTEGRATION.md +311 -0
  82. package/docs/COMPANY-WEBSITE-DOGFOOD.ko.md +144 -0
  83. package/docs/COMPANY-WEBSITE-DOGFOOD.md +150 -0
  84. package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.ko.md +153 -0
  85. package/docs/COMPANY-WEBSITE-INTAKE-TEMPLATE.md +154 -0
  86. package/docs/CONTRIBUTING.ko.md +203 -0
  87. package/docs/CONTRIBUTING.md +242 -0
  88. package/docs/CURSOR-INTEGRATION.md +220 -0
  89. package/docs/DISTRIBUTION.ko.md +248 -0
  90. package/docs/DISTRIBUTION.md +253 -0
  91. package/docs/DOGFOOD-FINDINGS.md +180 -0
  92. package/docs/DOGFOOD-V4-FINDINGS.md +139 -0
  93. package/docs/DOGFOOD-V4-MKDOCS-FINDINGS.md +233 -0
  94. package/docs/DOGFOOD-V4-NPM-FINDINGS.md +157 -0
  95. package/docs/DOGFOOD-V4-VSCODE-FINDINGS.md +135 -0
  96. package/docs/FIGMA-INTEGRATION.md +222 -0
  97. package/docs/MCP-INTEGRATION.md +243 -0
  98. package/docs/MIGRATION-v4.md +121 -0
  99. package/docs/PLUGIN-PACKAGING.md +240 -0
  100. package/docs/PRODUCT-READINESS.md +66 -0
  101. package/docs/QUICKSTART.ko.md +178 -0
  102. package/docs/QUICKSTART.md +179 -0
  103. package/docs/RELEASE-CHECKLIST.md +292 -0
  104. package/docs/ROADMAP.md +19495 -0
  105. package/docs/SESSION-LOG.md +940 -0
  106. package/docs/TOKEN-SYNC.md +237 -0
  107. package/docs/USING.ko.md +206 -0
  108. package/docs/USING.md +218 -0
  109. package/docs/WEBSITE-IMPROVEMENT.ko.md +75 -0
  110. package/docs/WEBSITE-IMPROVEMENT.md +89 -0
  111. package/docs/announcements/README.md +56 -0
  112. package/docs/announcements/dev-to-korea.md +206 -0
  113. package/docs/announcements/hashnode-post.ko.md +232 -0
  114. package/docs/announcements/okky-post.ko.md +158 -0
  115. package/docs/announcements/press-kit.md +101 -0
  116. package/docs/announcements/reddit-r-korea.md +196 -0
  117. package/docs/announcements/show-hn.md +114 -0
  118. package/docs/announcements/twitter-thread.md +255 -0
  119. package/docs/external-status.md +34 -0
  120. package/docs/integrations/aider-walkthrough.ko.md +275 -0
  121. package/docs/integrations/aider-walkthrough.md +274 -0
  122. package/docs/integrations/codex-walkthrough.ko.md +297 -0
  123. package/docs/integrations/codex-walkthrough.md +297 -0
  124. package/docs/integrations/cursor-walkthrough.ko.md +281 -0
  125. package/docs/integrations/cursor-walkthrough.md +284 -0
  126. package/docs/integrations/design-ai-mcp-server.md +169 -0
  127. package/docs/integrations/figma-mcp.md +149 -0
  128. package/docs/integrations/github-mcp.md +178 -0
  129. package/docs/integrations/linear-mcp.md +215 -0
  130. package/docs/integrations/notion-mcp.md +174 -0
  131. package/docs/integrations/sdk-walkthrough.ko.md +375 -0
  132. package/docs/integrations/sdk-walkthrough.md +375 -0
  133. package/docs/integrations/slack-mcp.md +208 -0
  134. package/docs/integrations/vscode-walkthrough.ko.md +202 -0
  135. package/docs/integrations/vscode-walkthrough.md +205 -0
  136. package/docs/requirements.txt +16 -0
  137. package/docs/site-overrides/extra.css +83 -0
  138. package/docs/site-overrides/favicon.svg +4 -0
  139. package/docs/site-overrides/logo.svg +10 -0
  140. package/docs/site-overrides/main.html +18 -0
  141. package/docs/website-console/app.js +2540 -0
  142. package/docs/website-console/index.html +24 -0
  143. package/docs/website-console/styles.css +975 -0
  144. package/examples/README.md +252 -0
  145. package/examples/cases/dogfood-v4-korean-hr-onboarding.md +356 -0
  146. package/examples/component-accordion-actions.md +153 -0
  147. package/examples/component-accordion-details.md +147 -0
  148. package/examples/component-accordion-summary.md +180 -0
  149. package/examples/component-accordion.md +229 -0
  150. package/examples/component-account-card.md +284 -0
  151. package/examples/component-address-input.md +260 -0
  152. package/examples/component-affix.md +190 -0
  153. package/examples/component-alert-dialog.md +210 -0
  154. package/examples/component-alert-title.md +77 -0
  155. package/examples/component-alert.md +192 -0
  156. package/examples/component-amount-input.md +278 -0
  157. package/examples/component-anchor.md +198 -0
  158. package/examples/component-app-bar.md +249 -0
  159. package/examples/component-aspect-ratio.md +156 -0
  160. package/examples/component-auto-complete.md +199 -0
  161. package/examples/component-avatar-group.md +170 -0
  162. package/examples/component-avatar.md +191 -0
  163. package/examples/component-back-top.md +123 -0
  164. package/examples/component-backdrop.md +148 -0
  165. package/examples/component-badge.md +181 -0
  166. package/examples/component-banner.md +237 -0
  167. package/examples/component-biometric-gate.md +281 -0
  168. package/examples/component-blockquote.md +153 -0
  169. package/examples/component-border-beam.md +207 -0
  170. package/examples/component-bottom-navigation.md +226 -0
  171. package/examples/component-box.md +112 -0
  172. package/examples/component-breadcrumb.md +222 -0
  173. package/examples/component-button-base.md +190 -0
  174. package/examples/component-button-group.md +117 -0
  175. package/examples/component-button.md +213 -0
  176. package/examples/component-calendar.md +280 -0
  177. package/examples/component-callout.md +131 -0
  178. package/examples/component-card-actions.md +101 -0
  179. package/examples/component-card-content.md +90 -0
  180. package/examples/component-card-header.md +122 -0
  181. package/examples/component-card-media.md +79 -0
  182. package/examples/component-card.md +233 -0
  183. package/examples/component-carousel.md +266 -0
  184. package/examples/component-cascader.md +135 -0
  185. package/examples/component-category-picker.md +271 -0
  186. package/examples/component-chart.md +237 -0
  187. package/examples/component-chat-interface.md +399 -0
  188. package/examples/component-checkbox.md +149 -0
  189. package/examples/component-click-away-listener.md +87 -0
  190. package/examples/component-code.md +213 -0
  191. package/examples/component-collapsible.md +219 -0
  192. package/examples/component-color-picker.md +110 -0
  193. package/examples/component-combobox.md +267 -0
  194. package/examples/component-command.md +299 -0
  195. package/examples/component-config-provider.md +190 -0
  196. package/examples/component-context-menu.md +179 -0
  197. package/examples/component-css-baseline.md +148 -0
  198. package/examples/component-date-picker.md +249 -0
  199. package/examples/component-descriptions.md +242 -0
  200. package/examples/component-dialog-actions.md +111 -0
  201. package/examples/component-dialog-content-text.md +76 -0
  202. package/examples/component-dialog-content.md +105 -0
  203. package/examples/component-dialog-title.md +104 -0
  204. package/examples/component-dialog.md +176 -0
  205. package/examples/component-divider.md +182 -0
  206. package/examples/component-doc-page.md +217 -0
  207. package/examples/component-drawer.md +257 -0
  208. package/examples/component-dropdown.md +220 -0
  209. package/examples/component-email-layout.md +253 -0
  210. package/examples/component-empty-state.md +269 -0
  211. package/examples/component-empty.md +172 -0
  212. package/examples/component-fade.md +87 -0
  213. package/examples/component-feature-grid.md +201 -0
  214. package/examples/component-field.md +266 -0
  215. package/examples/component-filled-input.md +114 -0
  216. package/examples/component-flex.md +117 -0
  217. package/examples/component-float-button.md +214 -0
  218. package/examples/component-form-control-label.md +134 -0
  219. package/examples/component-form-control.md +113 -0
  220. package/examples/component-form-controls.md +251 -0
  221. package/examples/component-form-group.md +86 -0
  222. package/examples/component-form-helper-text.md +95 -0
  223. package/examples/component-form-label.md +98 -0
  224. package/examples/component-form.md +291 -0
  225. package/examples/component-game-hud.md +362 -0
  226. package/examples/component-game-menu.md +327 -0
  227. package/examples/component-grid.md +140 -0
  228. package/examples/component-grow.md +79 -0
  229. package/examples/component-hero-block.md +252 -0
  230. package/examples/component-hover-card.md +211 -0
  231. package/examples/component-icon-button.md +142 -0
  232. package/examples/component-icon.md +102 -0
  233. package/examples/component-illustration.md +280 -0
  234. package/examples/component-image-list.md +107 -0
  235. package/examples/component-image.md +282 -0
  236. package/examples/component-input-adornment.md +101 -0
  237. package/examples/component-input-base.md +134 -0
  238. package/examples/component-input-number.md +141 -0
  239. package/examples/component-input-otp.md +271 -0
  240. package/examples/component-input.md +213 -0
  241. package/examples/component-item.md +243 -0
  242. package/examples/component-kbd.md +197 -0
  243. package/examples/component-krw-amount.md +219 -0
  244. package/examples/component-label.md +118 -0
  245. package/examples/component-layout.md +217 -0
  246. package/examples/component-link.md +223 -0
  247. package/examples/component-list-item-avatar.md +72 -0
  248. package/examples/component-list-item-button.md +139 -0
  249. package/examples/component-list-item-icon.md +82 -0
  250. package/examples/component-list-item-text.md +98 -0
  251. package/examples/component-list-item.md +116 -0
  252. package/examples/component-list-subheader.md +70 -0
  253. package/examples/component-list.md +198 -0
  254. package/examples/component-loading-button.md +125 -0
  255. package/examples/component-loading-sequence.md +254 -0
  256. package/examples/component-lottie-player.md +279 -0
  257. package/examples/component-masonry.md +191 -0
  258. package/examples/component-mentions.md +189 -0
  259. package/examples/component-menu-item.md +102 -0
  260. package/examples/component-menu-list.md +98 -0
  261. package/examples/component-menu.md +139 -0
  262. package/examples/component-menubar.md +259 -0
  263. package/examples/component-message.md +162 -0
  264. package/examples/component-mobile-stepper.md +155 -0
  265. package/examples/component-modal.md +220 -0
  266. package/examples/component-navigation-menu.md +295 -0
  267. package/examples/component-notification.md +166 -0
  268. package/examples/component-otp-countdown.md +245 -0
  269. package/examples/component-outlined-input.md +145 -0
  270. package/examples/component-page-transition.md +281 -0
  271. package/examples/component-pagination.md +226 -0
  272. package/examples/component-paper.md +199 -0
  273. package/examples/component-pass-auth.md +265 -0
  274. package/examples/component-payment-brand-button.md +253 -0
  275. package/examples/component-payment-method-selector.md +272 -0
  276. package/examples/component-payment-receipt.md +277 -0
  277. package/examples/component-popconfirm.md +144 -0
  278. package/examples/component-popover.md +239 -0
  279. package/examples/component-popper.md +129 -0
  280. package/examples/component-pricing-cards.md +247 -0
  281. package/examples/component-progress.md +195 -0
  282. package/examples/component-qr-code.md +201 -0
  283. package/examples/component-radio.md +167 -0
  284. package/examples/component-rate.md +202 -0
  285. package/examples/component-resizable.md +163 -0
  286. package/examples/component-result.md +270 -0
  287. package/examples/component-scroll-area.md +199 -0
  288. package/examples/component-scroll-reveal.md +320 -0
  289. package/examples/component-segmented.md +178 -0
  290. package/examples/component-select.md +258 -0
  291. package/examples/component-separator.md +177 -0
  292. package/examples/component-sheet.md +277 -0
  293. package/examples/component-sidebar.md +257 -0
  294. package/examples/component-skeleton.md +178 -0
  295. package/examples/component-slide.md +89 -0
  296. package/examples/component-slider.md +208 -0
  297. package/examples/component-snackbar-content.md +92 -0
  298. package/examples/component-snackbar.md +121 -0
  299. package/examples/component-sonner.md +165 -0
  300. package/examples/component-space.md +125 -0
  301. package/examples/component-spatial-locomotion.md +373 -0
  302. package/examples/component-spatial-panel.md +330 -0
  303. package/examples/component-speed-dial-action.md +78 -0
  304. package/examples/component-speed-dial.md +177 -0
  305. package/examples/component-spin.md +173 -0
  306. package/examples/component-spinner.md +204 -0
  307. package/examples/component-splitter.md +210 -0
  308. package/examples/component-stack.md +130 -0
  309. package/examples/component-statistic.md +282 -0
  310. package/examples/component-step-button.md +157 -0
  311. package/examples/component-step-connector.md +157 -0
  312. package/examples/component-step-content.md +121 -0
  313. package/examples/component-step-icon.md +115 -0
  314. package/examples/component-step-label.md +101 -0
  315. package/examples/component-step.md +84 -0
  316. package/examples/component-steps.md +264 -0
  317. package/examples/component-stock-chart.md +251 -0
  318. package/examples/component-swipeable-drawer.md +149 -0
  319. package/examples/component-switch.md +99 -0
  320. package/examples/component-tab-scroll-button.md +180 -0
  321. package/examples/component-tab.md +120 -0
  322. package/examples/component-table-body.md +82 -0
  323. package/examples/component-table-cell.md +118 -0
  324. package/examples/component-table-container.md +75 -0
  325. package/examples/component-table-footer.md +72 -0
  326. package/examples/component-table-head.md +78 -0
  327. package/examples/component-table-pagination.md +137 -0
  328. package/examples/component-table-row.md +113 -0
  329. package/examples/component-table-sort-label.md +109 -0
  330. package/examples/component-table.md +202 -0
  331. package/examples/component-tabs.md +184 -0
  332. package/examples/component-tag-badge.md +309 -0
  333. package/examples/component-tag.md +102 -0
  334. package/examples/component-testimonial-carousel.md +218 -0
  335. package/examples/component-textarea-autosize.md +114 -0
  336. package/examples/component-textarea.md +173 -0
  337. package/examples/component-time-picker.md +205 -0
  338. package/examples/component-timeline.md +170 -0
  339. package/examples/component-toast.md +224 -0
  340. package/examples/component-toggle-button.md +129 -0
  341. package/examples/component-toggle.md +220 -0
  342. package/examples/component-toolbar.md +104 -0
  343. package/examples/component-tooltip.md +178 -0
  344. package/examples/component-tour.md +176 -0
  345. package/examples/component-transaction-list-item.md +243 -0
  346. package/examples/component-transfer.md +156 -0
  347. package/examples/component-tree-select.md +202 -0
  348. package/examples/component-tree.md +297 -0
  349. package/examples/component-typography.md +215 -0
  350. package/examples/component-upload.md +295 -0
  351. package/examples/component-video-hero.md +409 -0
  352. package/examples/component-video-player.md +340 -0
  353. package/examples/component-voice-input.md +408 -0
  354. package/examples/component-watermark.md +217 -0
  355. package/examples/component-zoom.md +92 -0
  356. package/examples/doc-explanation-example.md +196 -0
  357. package/examples/doc-how-to-example.md +205 -0
  358. package/examples/doc-tutorial-example.md +162 -0
  359. package/examples/dogfood-korean-fintech-system.md +433 -0
  360. package/examples/email-transactional-example.md +259 -0
  361. package/examples/palette-saas-violet.md +235 -0
  362. package/examples/print-business-card-spec.md +205 -0
  363. package/examples/print-packaging-spec.md +285 -0
  364. package/examples/report-example.md +228 -0
  365. package/examples/slide-deck-example.md +237 -0
  366. package/examples/website-improvement-report.md +128 -0
  367. package/examples/website-improvement-workspace.json +126 -0
  368. package/install.sh +189 -0
  369. package/knowledge/COVERAGE.md +740 -0
  370. package/knowledge/PRINCIPLES.md +108 -0
  371. package/knowledge/a11y/contrast.md +70 -0
  372. package/knowledge/a11y/keyboard-and-focus.md +108 -0
  373. package/knowledge/colors/color-theory.md +90 -0
  374. package/knowledge/colors/mui-palette-structure.md +105 -0
  375. package/knowledge/colors/palettes-by-product-type.md +876 -0
  376. package/knowledge/components/INDEX.md +231 -0
  377. package/knowledge/components/index.json +1470 -0
  378. package/knowledge/components/shadcn-registry.md +159 -0
  379. package/knowledge/conversational/ai-chat-interfaces.md +323 -0
  380. package/knowledge/conversational/chatbot-design.md +312 -0
  381. package/knowledge/conversational/conversational-ui-fundamentals.md +299 -0
  382. package/knowledge/conversational/korean-voice-conventions.md +281 -0
  383. package/knowledge/conversational/voice-ui-patterns.md +297 -0
  384. package/knowledge/design-tokens/ant-design.md +124 -0
  385. package/knowledge/design-tokens/material-3.md +235 -0
  386. package/knowledge/design-tokens/polaris-and-carbon.md +231 -0
  387. package/knowledge/design-tokens/tailwind-v4.md +284 -0
  388. package/knowledge/game-ui/game-accessibility.md +317 -0
  389. package/knowledge/game-ui/game-ui-fundamentals.md +281 -0
  390. package/knowledge/game-ui/hud-design.md +324 -0
  391. package/knowledge/game-ui/korean-gaming-conventions.md +312 -0
  392. package/knowledge/game-ui/menu-systems.md +388 -0
  393. package/knowledge/i18n/korean-app-store-visual.md +223 -0
  394. package/knowledge/i18n/korean-document-style.md +301 -0
  395. package/knowledge/i18n/korean-payments.md +211 -0
  396. package/knowledge/i18n/korean-product-conventions.md +96 -0
  397. package/knowledge/i18n/korean-publishing.md +139 -0
  398. package/knowledge/i18n/korean-typography.md +123 -0
  399. package/knowledge/icons/curated-sets.md +225 -0
  400. package/knowledge/illustration/hero-illustrations.md +234 -0
  401. package/knowledge/illustration/illustration-systems.md +221 -0
  402. package/knowledge/illustration/mascot-design.md +208 -0
  403. package/knowledge/illustration/spot-illustrations.md +246 -0
  404. package/knowledge/illustration/svg-optimization.md +308 -0
  405. package/knowledge/layout/spacing-and-grid.md +119 -0
  406. package/knowledge/motion/app-loading-sequences.md +277 -0
  407. package/knowledge/motion/choreography-depth.md +297 -0
  408. package/knowledge/motion/marketing-motion.md +223 -0
  409. package/knowledge/motion/micro-interactions.md +266 -0
  410. package/knowledge/motion/motion-tools.md +281 -0
  411. package/knowledge/motion/principles.md +126 -0
  412. package/knowledge/patterns/auth-flow-design.md +316 -0
  413. package/knowledge/patterns/b2b-onboarding-flows.md +182 -0
  414. package/knowledge/patterns/brand-identity.md +238 -0
  415. package/knowledge/patterns/brand-references.md +97 -0
  416. package/knowledge/patterns/chart-color-encoding.md +269 -0
  417. package/knowledge/patterns/chart-types.md +344 -0
  418. package/knowledge/patterns/dashboard-composition.md +299 -0
  419. package/knowledge/patterns/design-system-qa.md +356 -0
  420. package/knowledge/patterns/document-typography.md +248 -0
  421. package/knowledge/patterns/email-design.md +338 -0
  422. package/knowledge/patterns/empty-states.md +263 -0
  423. package/knowledge/patterns/error-states.md +318 -0
  424. package/knowledge/patterns/form-design.md +237 -0
  425. package/knowledge/patterns/information-architecture.md +341 -0
  426. package/knowledge/patterns/landing-hero-design.md +283 -0
  427. package/knowledge/patterns/landing-page-patterns.md +681 -0
  428. package/knowledge/patterns/list-and-feed.md +371 -0
  429. package/knowledge/patterns/mobile-navigation.md +278 -0
  430. package/knowledge/patterns/money-and-amount.md +301 -0
  431. package/knowledge/patterns/onboarding.md +300 -0
  432. package/knowledge/patterns/pricing-page-design.md +261 -0
  433. package/knowledge/patterns/realtime-data.md +280 -0
  434. package/knowledge/patterns/report-design.md +330 -0
  435. package/knowledge/patterns/search-ux.md +373 -0
  436. package/knowledge/patterns/settings-page.md +325 -0
  437. package/knowledge/patterns/slide-deck-design.md +316 -0
  438. package/knowledge/patterns/styles-catalog.md +2599 -0
  439. package/knowledge/patterns/technical-writing.md +306 -0
  440. package/knowledge/patterns/ui-reasoning.md +1853 -0
  441. package/knowledge/patterns/ux-guidelines.md +1454 -0
  442. package/knowledge/platforms/react-native.md +395 -0
  443. package/knowledge/print/brochures-and-flyers.md +276 -0
  444. package/knowledge/print/korean-print-conventions.md +284 -0
  445. package/knowledge/print/packaging.md +321 -0
  446. package/knowledge/print/print-fundamentals.md +238 -0
  447. package/knowledge/print/signage-and-posters.md +235 -0
  448. package/knowledge/print/stationery.md +262 -0
  449. package/knowledge/spatial/ar-patterns.md +253 -0
  450. package/knowledge/spatial/comfort-and-accessibility.md +245 -0
  451. package/knowledge/spatial/spatial-design-fundamentals.md +346 -0
  452. package/knowledge/spatial/spatial-ui-elements.md +343 -0
  453. package/knowledge/spatial/vr-patterns.md +302 -0
  454. package/knowledge/typography/font-pairings.md +332 -0
  455. package/knowledge/typography/mui-type-scale.md +57 -0
  456. package/knowledge/typography/type-scale-fundamentals.md +105 -0
  457. package/knowledge/video/in-product-video.md +277 -0
  458. package/knowledge/video/korean-video-conventions.md +247 -0
  459. package/knowledge/video/marketing-video.md +258 -0
  460. package/knowledge/video/social-and-short-form.md +257 -0
  461. package/knowledge/video/video-fundamentals.md +296 -0
  462. package/package.json +106 -0
  463. package/skills/README.md +39 -0
  464. package/skills/color-palette/PLAYBOOK.md +175 -0
  465. package/skills/color-palette/SKILL.md +6 -0
  466. package/skills/color-palette/TEMPLATE.md +103 -0
  467. package/skills/component-spec-writer/PLAYBOOK.md +169 -0
  468. package/skills/component-spec-writer/SKILL.md +6 -0
  469. package/skills/component-spec-writer/TEMPLATE.md +115 -0
  470. package/skills/conversational-ui-designer/PLAYBOOK.md +231 -0
  471. package/skills/conversational-ui-designer/SKILL.md +6 -0
  472. package/skills/design-broadcast/PLAYBOOK.md +146 -0
  473. package/skills/design-broadcast/SKILL.md +6 -0
  474. package/skills/design-critique/PLAYBOOK.md +137 -0
  475. package/skills/design-critique/SKILL.md +6 -0
  476. package/skills/design-pr-review/PLAYBOOK.md +171 -0
  477. package/skills/design-pr-review/SKILL.md +6 -0
  478. package/skills/design-system-builder/PLAYBOOK.md +218 -0
  479. package/skills/design-system-builder/SKILL.md +6 -0
  480. package/skills/design-system-qa/PLAYBOOK.md +163 -0
  481. package/skills/design-system-qa/SKILL.md +6 -0
  482. package/skills/document-author/PLAYBOOK.md +167 -0
  483. package/skills/document-author/SKILL.md +6 -0
  484. package/skills/figma-token-sync/PLAYBOOK.md +149 -0
  485. package/skills/figma-token-sync/SKILL.md +6 -0
  486. package/skills/game-ui-designer/PLAYBOOK.md +209 -0
  487. package/skills/game-ui-designer/SKILL.md +6 -0
  488. package/skills/handoff-spec/PLAYBOOK.md +170 -0
  489. package/skills/handoff-spec/SKILL.md +6 -0
  490. package/skills/illustration-designer/PLAYBOOK.md +166 -0
  491. package/skills/illustration-designer/SKILL.md +6 -0
  492. package/skills/motion-designer/PLAYBOOK.md +223 -0
  493. package/skills/motion-designer/SKILL.md +6 -0
  494. package/skills/print-designer/PLAYBOOK.md +209 -0
  495. package/skills/print-designer/SKILL.md +6 -0
  496. package/skills/slide-deck-author/PLAYBOOK.md +198 -0
  497. package/skills/slide-deck-author/SKILL.md +6 -0
  498. package/skills/spatial-designer/PLAYBOOK.md +238 -0
  499. package/skills/spatial-designer/SKILL.md +6 -0
  500. package/skills/ux-audit/PLAYBOOK.md +142 -0
  501. package/skills/ux-audit/SKILL.md +6 -0
  502. package/skills/video-designer/PLAYBOOK.md +240 -0
  503. package/skills/video-designer/SKILL.md +6 -0
  504. package/skills/website-improvement/PLAYBOOK.md +118 -0
  505. package/skills/website-improvement/SKILL.md +6 -0
  506. package/skills/website-improvement/TEMPLATE.md +103 -0
  507. package/tools/audit/changelog-generate.py +176 -0
  508. package/tools/audit/check-coverage.py +483 -0
  509. package/tools/audit/doctor_assertions.py +256 -0
  510. package/tools/audit/example-qa.py +108 -0
  511. package/tools/audit/frontmatter-check.py +199 -0
  512. package/tools/audit/integration-check.py +95 -0
  513. package/tools/audit/korean-copy-check.py +161 -0
  514. package/tools/audit/link-check.py +146 -0
  515. package/tools/audit/local-ci.py +558 -0
  516. package/tools/audit/package-contents.py +723 -0
  517. package/tools/audit/package-smoke.py +22443 -0
  518. package/tools/audit/raw-hex-check.py +252 -0
  519. package/tools/audit/registry-smoke.py +8188 -0
  520. package/tools/audit/release-metadata.py +9832 -0
  521. package/tools/audit/run-all.py +351 -0
  522. package/tools/audit/smoke_assertions.py +12742 -0
  523. package/tools/audit/stability-review.py +332 -0
  524. package/tools/audit/stale-check.py +156 -0
  525. package/tools/migrations/add-version-frontmatter.py +132 -0
  526. package/tools/migrations/bump-last-updated.py +131 -0
  527. package/tools/migrations/promote-stability.py +172 -0
  528. package/tools/preview/README.md +58 -0
  529. package/tools/preview/render-tokens.py +454 -0
@@ -0,0 +1,740 @@
1
+ // Deterministic task routing for `design-ai route`.
2
+
3
+ import {
4
+ existsSync,
5
+ readFileSync,
6
+ } from "node:fs";
7
+ import path from "node:path";
8
+
9
+ import { parseBriefSourceFlag } from "./brief.mjs";
10
+ import { suggestNearest, unknownOptionMessage } from "./suggest.mjs";
11
+
12
+ function exists(p) {
13
+ try {
14
+ return existsSync(p);
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ const COMMON_KNOWLEDGE = [
21
+ "knowledge/PRINCIPLES.md",
22
+ ];
23
+ const ROUTE_OPTIONS = [
24
+ "-h",
25
+ "--help",
26
+ "--json",
27
+ "--list",
28
+ "--explain",
29
+ "--eval-template",
30
+ "--eval",
31
+ "--strict",
32
+ "--from-file",
33
+ "--stdin",
34
+ "--limit",
35
+ ];
36
+ const ROUTE_EVAL_VERSION = 1;
37
+ const ROUTE_EVAL_DEFAULT_LIMIT = 3;
38
+ const CONFIDENCE_ORDER = {
39
+ low: 1,
40
+ medium: 2,
41
+ high: 3,
42
+ };
43
+
44
+ export const ROUTES = [
45
+ {
46
+ id: "design-review",
47
+ label: "Design review",
48
+ command: "commands/design-review.md",
49
+ skills: ["skills/ux-audit/SKILL.md", "skills/design-critique/SKILL.md"],
50
+ agents: ["agents/a11y-reviewer.md", "agents/design-critic.md"],
51
+ knowledge: [
52
+ "knowledge/patterns/ux-guidelines.md",
53
+ "knowledge/a11y/contrast.md",
54
+ "knowledge/a11y/keyboard-and-focus.md",
55
+ ],
56
+ keywords: ["audit", "review", "critique", "figma", "screenshot", "ux", "a11y", "accessibility", "리뷰", "감사", "평가", "비평", "접근성", "스크린샷"],
57
+ },
58
+ {
59
+ id: "website-improvement",
60
+ label: "Website improvement",
61
+ command: "commands/website-improvement.md",
62
+ skills: ["skills/website-improvement/SKILL.md", "skills/ux-audit/SKILL.md", "skills/handoff-spec/SKILL.md"],
63
+ agents: ["agents/a11y-reviewer.md", "agents/design-critic.md"],
64
+ knowledge: [
65
+ "knowledge/patterns/ux-guidelines.md",
66
+ "knowledge/a11y/contrast.md",
67
+ "knowledge/a11y/keyboard-and-focus.md",
68
+ "knowledge/layout/spacing-and-grid.md",
69
+ "knowledge/patterns/report-design.md",
70
+ "docs/MCP-INTEGRATION.md",
71
+ "docs/WEBSITE-IMPROVEMENT.md",
72
+ ],
73
+ keywords: ["website", "webpage", "homepage", "landing", "seo", "performance", "lighthouse", "core web vitals", "mcp", "refactor plan", "handoff report", "site profile", "웹사이트", "홈페이지", "랜딩", "성능", "검색엔진", "개선", "리팩터"],
74
+ },
75
+ {
76
+ id: "design-from-brief",
77
+ label: "Design system from brief",
78
+ command: "commands/design-from-brief.md",
79
+ skills: ["skills/color-palette/SKILL.md", "skills/design-system-builder/SKILL.md", "skills/handoff-spec/SKILL.md"],
80
+ knowledge: [
81
+ "knowledge/patterns/ui-reasoning.md",
82
+ "knowledge/patterns/styles-catalog.md",
83
+ "knowledge/layout/spacing-and-grid.md",
84
+ "knowledge/typography/type-scale-fundamentals.md",
85
+ ],
86
+ keywords: ["brief", "design system", "brand", "tokens", "foundation", "app", "product", "startup", "서비스", "브랜드", "디자인 시스템", "토큰", "앱", "프로덕트"],
87
+ },
88
+ {
89
+ id: "component-spec",
90
+ label: "Component spec",
91
+ command: "commands/component-spec.md",
92
+ skills: ["skills/component-spec-writer/SKILL.md"],
93
+ agents: ["agents/component-architect.md", "agents/a11y-reviewer.md"],
94
+ knowledge: [
95
+ "knowledge/components/INDEX.md",
96
+ "knowledge/components/shadcn-registry.md",
97
+ "knowledge/a11y/keyboard-and-focus.md",
98
+ ],
99
+ keywords: ["component", "button", "input", "modal", "dialog", "table", "form", "dropdown", "select", "spec", "api", "props", "컴포넌트", "버튼", "입력", "모달", "폼", "테이블", "스펙"],
100
+ },
101
+ {
102
+ id: "palette-from-brand",
103
+ label: "Palette from brand",
104
+ command: "commands/palette-from-brand.md",
105
+ skills: ["skills/color-palette/SKILL.md"],
106
+ knowledge: [
107
+ "knowledge/colors/color-theory.md",
108
+ "knowledge/a11y/contrast.md",
109
+ "knowledge/design-tokens/tailwind-v4.md",
110
+ ],
111
+ keywords: ["color", "palette", "theme", "dark mode", "hex", "oklch", "색", "색상", "컬러", "팔레트", "다크모드"],
112
+ },
113
+ {
114
+ id: "motion-design",
115
+ label: "Motion design",
116
+ command: "commands/motion-design.md",
117
+ skills: ["skills/motion-designer/SKILL.md"],
118
+ knowledge: [
119
+ "knowledge/motion/principles.md",
120
+ "knowledge/motion/micro-interactions.md",
121
+ "knowledge/motion/choreography-depth.md",
122
+ ],
123
+ keywords: ["motion", "animation", "transition", "framer", "gsap", "lottie", "모션", "애니메이션", "전환", "인터랙션"],
124
+ },
125
+ {
126
+ id: "illustration",
127
+ label: "Illustration",
128
+ command: "commands/illustration.md",
129
+ skills: ["skills/illustration-designer/SKILL.md"],
130
+ knowledge: [
131
+ "knowledge/illustration/illustration-systems.md",
132
+ "knowledge/illustration/spot-illustrations.md",
133
+ "knowledge/illustration/mascot-design.md",
134
+ ],
135
+ keywords: ["illustration", "mascot", "svg", "empty state", "hero art", "일러스트", "마스코트", "캐릭터", "빈 상태"],
136
+ },
137
+ {
138
+ id: "print",
139
+ label: "Print design",
140
+ command: "commands/print.md",
141
+ skills: ["skills/print-designer/SKILL.md"],
142
+ knowledge: [
143
+ "knowledge/print/print-fundamentals.md",
144
+ "knowledge/print/stationery.md",
145
+ "knowledge/print/packaging.md",
146
+ ],
147
+ keywords: ["print", "business card", "brochure", "packaging", "poster", "cmyk", "bleed", "인쇄", "명함", "브로셔", "패키지", "포스터"],
148
+ },
149
+ {
150
+ id: "video",
151
+ label: "Video design",
152
+ command: "commands/video.md",
153
+ skills: ["skills/video-designer/SKILL.md"],
154
+ knowledge: [
155
+ "knowledge/video/video-fundamentals.md",
156
+ "knowledge/video/marketing-video.md",
157
+ "knowledge/video/social-and-short-form.md",
158
+ ],
159
+ keywords: ["video", "reels", "shorts", "tiktok", "caption", "subtitles", "영상", "비디오", "릴스", "쇼츠", "자막"],
160
+ },
161
+ {
162
+ id: "game-ui",
163
+ label: "Game UI",
164
+ command: "commands/game-ui.md",
165
+ skills: ["skills/game-ui-designer/SKILL.md"],
166
+ knowledge: [
167
+ "knowledge/game-ui/game-ui-fundamentals.md",
168
+ "knowledge/game-ui/hud-design.md",
169
+ "knowledge/game-ui/menu-systems.md",
170
+ ],
171
+ keywords: ["game", "hud", "inventory", "gacha", "cooldown", "게임", "인벤토리", "확률", "뽑기"],
172
+ },
173
+ {
174
+ id: "conversational",
175
+ label: "Conversational UI",
176
+ command: "commands/conversational.md",
177
+ skills: ["skills/conversational-ui-designer/SKILL.md"],
178
+ knowledge: [
179
+ "knowledge/conversational/ai-chat-interfaces.md",
180
+ "knowledge/conversational/chatbot-design.md",
181
+ "knowledge/conversational/korean-voice-conventions.md",
182
+ ],
183
+ keywords: ["chatbot", "voice", "assistant", "ai chat", "conversation", "챗봇", "대화", "음성", "어시스턴트"],
184
+ },
185
+ {
186
+ id: "spatial",
187
+ label: "Spatial design",
188
+ command: "commands/spatial.md",
189
+ skills: ["skills/spatial-designer/SKILL.md"],
190
+ knowledge: [
191
+ "knowledge/spatial/spatial-design-fundamentals.md",
192
+ "knowledge/spatial/vr-patterns.md",
193
+ "knowledge/spatial/ar-patterns.md",
194
+ ],
195
+ keywords: ["spatial", "vr", "ar", "xr", "vision pro", "webxr", "immersive", "공간", "증강현실", "가상현실"],
196
+ },
197
+ {
198
+ id: "document-from-brief",
199
+ label: "Documentation",
200
+ command: "commands/document-from-brief.md",
201
+ skills: ["skills/document-author/SKILL.md"],
202
+ knowledge: [
203
+ "knowledge/patterns/information-architecture.md",
204
+ "knowledge/patterns/technical-writing.md",
205
+ "knowledge/patterns/document-typography.md",
206
+ ],
207
+ keywords: ["documentation", "docs", "guide", "manual", "readme", "diataxis", "문서", "가이드", "매뉴얼", "기술문서"],
208
+ },
209
+ {
210
+ id: "slide-deck",
211
+ label: "Slide deck",
212
+ command: "commands/slide-deck.md",
213
+ skills: ["skills/slide-deck-author/SKILL.md"],
214
+ knowledge: [
215
+ "knowledge/patterns/slide-deck-design.md",
216
+ "knowledge/patterns/report-design.md",
217
+ ],
218
+ keywords: ["slide", "deck", "presentation", "pitch", "ppt", "슬라이드", "발표", "제안서", "피치덱"],
219
+ },
220
+ {
221
+ id: "handoff-spec",
222
+ label: "Design handoff",
223
+ command: null,
224
+ skills: ["skills/handoff-spec/SKILL.md"],
225
+ knowledge: [
226
+ "knowledge/patterns/technical-writing.md",
227
+ "knowledge/design-tokens/ant-design.md",
228
+ ],
229
+ keywords: ["handoff", "engineering", "developer", "implementation spec", "dev spec", "핸드오프", "개발 전달", "개발자"],
230
+ },
231
+ {
232
+ id: "design-system-qa",
233
+ label: "Design system QA",
234
+ command: null,
235
+ skills: ["skills/design-system-qa/SKILL.md"],
236
+ knowledge: [
237
+ "knowledge/patterns/design-system-qa.md",
238
+ "knowledge/a11y/keyboard-and-focus.md",
239
+ ],
240
+ keywords: ["qa", "test", "regression", "visual regression", "storybook", "contract", "테스트", "회귀", "품질"],
241
+ },
242
+ {
243
+ id: "figma-token-sync",
244
+ label: "Figma token sync",
245
+ command: null,
246
+ skills: ["skills/figma-token-sync/SKILL.md"],
247
+ knowledge: [
248
+ "knowledge/design-tokens/ant-design.md",
249
+ "knowledge/design-tokens/tailwind-v4.md",
250
+ ],
251
+ keywords: ["figma token", "token sync", "variables", "figma variables", "피그마 토큰", "토큰 동기화", "변수"],
252
+ },
253
+ {
254
+ id: "design-pr-review",
255
+ label: "Design PR review",
256
+ command: null,
257
+ skills: ["skills/design-pr-review/SKILL.md"],
258
+ knowledge: [
259
+ "knowledge/patterns/design-system-qa.md",
260
+ "knowledge/a11y/contrast.md",
261
+ ],
262
+ keywords: ["pull request", "pr", "github", "diff", "code review", "깃허브", "코드 리뷰", "PR"],
263
+ },
264
+ {
265
+ id: "stability-review",
266
+ label: "Stability review",
267
+ command: "commands/stability-review.md",
268
+ skills: [],
269
+ knowledge: [
270
+ "docs/RELEASE-CHECKLIST.md",
271
+ "docs/CONTRIBUTING.md",
272
+ ],
273
+ keywords: ["release", "stability", "stale", "quarterly", "launch", "릴리스", "안정화", "오래된", "출시"],
274
+ },
275
+ ];
276
+
277
+ export function routeIds() {
278
+ return ROUTES.map((route) => route.id);
279
+ }
280
+
281
+ export function suggestRouteId(routeId, ids = routeIds()) {
282
+ return suggestNearest(routeId, ids);
283
+ }
284
+
285
+ export function unknownRouteIdMessage(routeId, ids = routeIds()) {
286
+ const suggestion = suggestRouteId(routeId, ids);
287
+ const lines = [`Unknown route id: ${routeId}.`];
288
+ if (suggestion) lines.push(`Did you mean \`${suggestion}\`?`);
289
+ lines.push(`Available routes: ${ids.join(", ")}`);
290
+ return lines.join("\n");
291
+ }
292
+
293
+ export function assertKnownRouteId(routeId, { allowEmpty = true } = {}) {
294
+ if (!routeId && allowEmpty) return;
295
+ if (ROUTES.some((route) => route.id === routeId)) return;
296
+ throw new Error(unknownRouteIdMessage(routeId));
297
+ }
298
+
299
+ export function parseRouteArgs(args) {
300
+ const out = {
301
+ briefParts: [],
302
+ fromFile: "",
303
+ stdin: false,
304
+ list: false,
305
+ explain: false,
306
+ evalTemplate: false,
307
+ eval: false,
308
+ strict: false,
309
+ limit: 3,
310
+ json: false,
311
+ help: false,
312
+ };
313
+
314
+ for (let i = 0; i < args.length; i += 1) {
315
+ const arg = args[i];
316
+ out.index = i;
317
+ if (arg === "-h" || arg === "--help") {
318
+ out.help = true;
319
+ } else if (arg === "--json") {
320
+ out.json = true;
321
+ } else if (arg === "--list") {
322
+ out.list = true;
323
+ } else if (arg === "--explain") {
324
+ out.explain = true;
325
+ } else if (arg === "--eval-template") {
326
+ out.evalTemplate = true;
327
+ } else if (arg === "--eval") {
328
+ out.eval = true;
329
+ } else if (arg === "--strict") {
330
+ out.strict = true;
331
+ } else if (parseBriefSourceFlag(args, out)) {
332
+ i = out.index;
333
+ } else if (arg === "--limit") {
334
+ const limit = Number(args[i + 1]);
335
+ if (!Number.isInteger(limit) || limit < 1 || limit > 10) {
336
+ throw new Error("--limit expects an integer from 1 to 10");
337
+ }
338
+ out.limit = limit;
339
+ i += 1;
340
+ } else if (arg.startsWith("--")) {
341
+ throw new Error(unknownOptionMessage("route", arg, ROUTE_OPTIONS));
342
+ } else {
343
+ out.briefParts.push(arg);
344
+ }
345
+ }
346
+
347
+ if (out.eval && out.evalTemplate) {
348
+ throw new Error("Choose either --eval-template or --eval, not both");
349
+ }
350
+ if (out.strict && !out.eval) {
351
+ throw new Error("--strict can only be used with --eval");
352
+ }
353
+ if (out.evalTemplate && (out.fromFile || out.stdin || out.list || out.briefParts.length > 0)) {
354
+ throw new Error("--eval-template cannot be combined with a brief, --from-file, --stdin, or --list");
355
+ }
356
+ if (out.eval && (!out.fromFile && !out.stdin)) {
357
+ throw new Error("--eval requires --from-file or --stdin");
358
+ }
359
+ if (out.eval && (out.briefParts.length > 0 || out.list)) {
360
+ throw new Error("--eval cannot be combined with an inline brief or --list");
361
+ }
362
+
363
+ return {
364
+ ...out,
365
+ index: undefined,
366
+ brief: out.briefParts.join(" ").trim(),
367
+ };
368
+ }
369
+
370
+ function keywordHits(text, keywords) {
371
+ const lower = text.toLowerCase();
372
+ return keywords.filter((keyword) => keywordMatches(lower, keyword));
373
+ }
374
+
375
+ function escapeRegExp(value) {
376
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
377
+ }
378
+
379
+ function keywordMatches(lowerText, keyword) {
380
+ const lowerKeyword = keyword.toLowerCase();
381
+ const isSimpleLatin = /^[a-z0-9+#.]+$/.test(lowerKeyword);
382
+
383
+ if (isSimpleLatin) {
384
+ const pattern = new RegExp(`(^|[^a-z0-9])${escapeRegExp(lowerKeyword)}($|[^a-z0-9])`);
385
+ return pattern.test(lowerText);
386
+ }
387
+
388
+ return lowerText.includes(lowerKeyword);
389
+ }
390
+
391
+ function confidence(score) {
392
+ if (score >= 4) return "high";
393
+ if (score >= 2) return "medium";
394
+ return "low";
395
+ }
396
+
397
+ function pathStatus(sourceRoot, paths) {
398
+ return paths.map((relPath) => ({
399
+ path: relPath,
400
+ exists: exists(path.join(sourceRoot, relPath)),
401
+ }));
402
+ }
403
+
404
+ function countAvailable(entries) {
405
+ return entries.filter((entry) => entry.exists).length;
406
+ }
407
+
408
+ function referenceCoverage({ command, skills, agents, knowledge }) {
409
+ const commandTotal = command ? 1 : 0;
410
+ const commandAvailable = command?.exists ? 1 : 0;
411
+ const sections = {
412
+ command: { available: commandAvailable, total: commandTotal },
413
+ skills: { available: countAvailable(skills), total: skills.length },
414
+ agents: { available: countAvailable(agents), total: agents.length },
415
+ knowledge: { available: countAvailable(knowledge), total: knowledge.length },
416
+ };
417
+ const total = Object.values(sections).reduce(
418
+ (acc, section) => ({
419
+ available: acc.available + section.available,
420
+ total: acc.total + section.total,
421
+ }),
422
+ { available: 0, total: 0 },
423
+ );
424
+
425
+ return {
426
+ ...sections,
427
+ total,
428
+ };
429
+ }
430
+
431
+ function missingReferences({ command, skills, agents, knowledge }) {
432
+ return [
433
+ ...(command ? [command] : []),
434
+ ...skills,
435
+ ...agents,
436
+ ...knowledge,
437
+ ].filter((entry) => !entry.exists).map((entry) => entry.path);
438
+ }
439
+
440
+ function explanationSummary({ hits, forced, fallback, catalog }) {
441
+ if (forced) return "Route selected explicitly with --route.";
442
+ if (fallback) return "No route keywords matched; using the default design-from-brief workflow.";
443
+ if (catalog) return "Catalog listing; no task brief was scored.";
444
+ return `Matched ${hits.length} keyword${hits.length === 1 ? "" : "s"}: ${hits.join(", ")}.`;
445
+ }
446
+
447
+ function routeExplanation({ hits, command, skills, agents, knowledge, forced = false, fallback = false, catalog = false }) {
448
+ const coverage = referenceCoverage({ command, skills, agents, knowledge });
449
+ return {
450
+ summary: explanationSummary({ hits, forced, fallback, catalog }),
451
+ scoreBreakdown: [
452
+ { label: "keyword matches", value: hits.length },
453
+ ],
454
+ referenceCoverage: coverage,
455
+ missingReferences: missingReferences({ command, skills, agents, knowledge }),
456
+ };
457
+ }
458
+
459
+ function routeToResult(route, sourceRoot, hits, options = {}) {
460
+ const command = route.command
461
+ ? { path: route.command, exists: exists(path.join(sourceRoot, route.command)) }
462
+ : null;
463
+ const skills = pathStatus(sourceRoot, route.skills || []);
464
+ const agents = pathStatus(sourceRoot, route.agents || []);
465
+ const knowledge = pathStatus(sourceRoot, [...COMMON_KNOWLEDGE, ...(route.knowledge || [])]);
466
+ const forced = Boolean(options.forced);
467
+ const fallback = Boolean(options.fallback);
468
+ const catalog = Boolean(options.catalog);
469
+
470
+ return {
471
+ id: route.id,
472
+ label: route.label,
473
+ score: hits.length,
474
+ confidence: confidence(hits.length),
475
+ matchedKeywords: hits,
476
+ command,
477
+ skills,
478
+ agents,
479
+ knowledge,
480
+ keywords: route.keywords,
481
+ explanation: routeExplanation({ hits, command, skills, agents, knowledge, forced, fallback, catalog }),
482
+ ...(forced ? { forced: true } : {}),
483
+ ...(fallback ? { fallback: true } : {}),
484
+ };
485
+ }
486
+
487
+ export function routeCatalog({ sourceRoot }) {
488
+ return ROUTES.map((route) => ({
489
+ ...routeToResult(route, sourceRoot, [], { catalog: true }),
490
+ confidence: "catalog",
491
+ }));
492
+ }
493
+
494
+ export function routeById({ routeId, sourceRoot }) {
495
+ assertKnownRouteId(routeId, { allowEmpty: false });
496
+ const route = ROUTES.find((item) => item.id === routeId);
497
+
498
+ return {
499
+ ...routeToResult(route, sourceRoot, [], { forced: true }),
500
+ confidence: "forced",
501
+ };
502
+ }
503
+
504
+ function fallbackResult(sourceRoot) {
505
+ const route = ROUTES.find((item) => item.id === "design-from-brief");
506
+ return {
507
+ ...routeToResult(route, sourceRoot, [], { fallback: true }),
508
+ confidence: "low",
509
+ };
510
+ }
511
+
512
+ export function routeBrief({ brief, sourceRoot, limit = 3 }) {
513
+ const normalized = brief.trim();
514
+ if (!normalized) return [];
515
+
516
+ const scored = ROUTES
517
+ .map((route) => ({ route, hits: keywordHits(normalized, route.keywords) }))
518
+ .filter((item) => item.hits.length > 0)
519
+ .sort((a, b) => {
520
+ if (b.hits.length !== a.hits.length) return b.hits.length - a.hits.length;
521
+ return a.route.label.localeCompare(b.route.label);
522
+ })
523
+ .slice(0, limit)
524
+ .map((item) => routeToResult(item.route, sourceRoot, item.hits));
525
+
526
+ if (scored.length > 0) return scored;
527
+ return [fallbackResult(sourceRoot)];
528
+ }
529
+
530
+ function isoTimestamp(now = new Date()) {
531
+ return (now instanceof Date ? now : new Date(now)).toISOString();
532
+ }
533
+
534
+ export function buildRouteEvalTemplate({ sourceRoot, generatedAt = new Date() } = {}) {
535
+ return {
536
+ version: ROUTE_EVAL_VERSION,
537
+ generatedAt: isoTimestamp(generatedAt),
538
+ sourceRouteVersion: sourceRoot ? readRouteManifestVersion(sourceRoot) : "unknown",
539
+ description: "Deterministic route-selection checkpoints for design-ai agent routing.",
540
+ cases: [
541
+ {
542
+ id: "design-review-a11y",
543
+ brief: "Audit and review a Figma signup flow for accessibility, keyboard focus, screen reader behavior, critique, and UX risk",
544
+ expectedRouteId: "design-review",
545
+ minConfidence: "high",
546
+ },
547
+ {
548
+ id: "website-improvement-control-tower",
549
+ brief: "Improve a website homepage with SEO, performance, MCP readiness, and a refactor plan",
550
+ expectedRouteId: "website-improvement",
551
+ minConfidence: "high",
552
+ },
553
+ {
554
+ id: "component-spec-contract",
555
+ brief: "Spec a Button component API with variants, props, states, and keyboard accessibility",
556
+ expectedRouteId: "component-spec",
557
+ minConfidence: "medium",
558
+ },
559
+ {
560
+ id: "learning-design-system-qa",
561
+ brief: "Audit our design system QA with visual regression, token contract tests, and accessibility coverage",
562
+ expectedRouteId: "design-system-qa",
563
+ minConfidence: "medium",
564
+ },
565
+ {
566
+ id: "korean-palette",
567
+ brief: "Generate a Korean SaaS color palette with semantic tokens, dark mode, and contrast ratios",
568
+ expectedRouteId: "palette-from-brand",
569
+ minConfidence: "medium",
570
+ },
571
+ {
572
+ id: "motion-spec",
573
+ brief: "Spec motion, animation, and transition behavior with duration, easing, choreography, Framer guidance, and reduced motion support",
574
+ expectedRouteId: "motion-design",
575
+ minConfidence: "high",
576
+ },
577
+ ],
578
+ };
579
+ }
580
+
581
+ function routeEvalStatus(counts) {
582
+ if (counts.fail > 0) return "fail";
583
+ if (counts.warn > 0) return "warn";
584
+ return "pass";
585
+ }
586
+
587
+ function normalizeRouteEvalPayload(evalText, source = "route-eval.json") {
588
+ let payload;
589
+ try {
590
+ payload = JSON.parse(evalText);
591
+ } catch (err) {
592
+ throw new Error(`Could not parse route eval JSON from ${source}: ${err.message}`);
593
+ }
594
+
595
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
596
+ throw new Error("Route eval payload must be a JSON object");
597
+ }
598
+ if (payload.version !== ROUTE_EVAL_VERSION) {
599
+ throw new Error(`Route eval payload version must be ${ROUTE_EVAL_VERSION}`);
600
+ }
601
+ if (!Array.isArray(payload.cases)) {
602
+ throw new Error("Route eval payload must include a cases array");
603
+ }
604
+
605
+ return payload;
606
+ }
607
+
608
+ function normalizeRouteEvalCase(rawCase, index) {
609
+ if (!rawCase || typeof rawCase !== "object" || Array.isArray(rawCase)) {
610
+ throw new Error(`Route eval case ${index + 1} must be a JSON object`);
611
+ }
612
+
613
+ const id = String(rawCase.id || `case-${index + 1}`).trim();
614
+ const brief = String(rawCase.brief || "").trim();
615
+ const expectedRouteId = String(rawCase.expectedRouteId || rawCase.expected || "").trim();
616
+ const minConfidence = String(rawCase.minConfidence || "").trim().toLowerCase();
617
+ const limit = rawCase.limit === undefined || rawCase.limit === null
618
+ ? ROUTE_EVAL_DEFAULT_LIMIT
619
+ : Number(rawCase.limit);
620
+
621
+ if (!id) throw new Error(`Route eval case ${index + 1} is missing id`);
622
+ if (!brief) throw new Error(`Route eval case ${id} is missing brief`);
623
+ if (!expectedRouteId) throw new Error(`Route eval case ${id} is missing expectedRouteId`);
624
+ if (minConfidence && !Object.hasOwn(CONFIDENCE_ORDER, minConfidence)) {
625
+ throw new Error(`Route eval case ${id} has invalid minConfidence: ${minConfidence}`);
626
+ }
627
+ if (!Number.isInteger(limit) || limit < 1 || limit > 10) {
628
+ throw new Error(`Route eval case ${id} limit must be an integer from 1 to 10`);
629
+ }
630
+
631
+ return {
632
+ id,
633
+ brief,
634
+ expectedRouteId,
635
+ minConfidence,
636
+ limit,
637
+ };
638
+ }
639
+
640
+ function evaluateRouteEvalCase(testCase, sourceRoot, defaultLimit) {
641
+ let expectedKnown = true;
642
+ try {
643
+ assertKnownRouteId(testCase.expectedRouteId, { allowEmpty: false });
644
+ } catch {
645
+ expectedKnown = false;
646
+ }
647
+
648
+ const limit = testCase.limit || defaultLimit || ROUTE_EVAL_DEFAULT_LIMIT;
649
+ const routes = routeBrief({
650
+ brief: testCase.brief,
651
+ sourceRoot,
652
+ limit,
653
+ });
654
+ const topRoute = routes[0] || null;
655
+ const expectedRank = routes.findIndex((route) => route.id === testCase.expectedRouteId);
656
+
657
+ let status = "pass";
658
+ let message = "Expected route selected.";
659
+
660
+ if (!expectedKnown) {
661
+ status = "fail";
662
+ message = `Expected route id is unknown: ${testCase.expectedRouteId}`;
663
+ } else if (!topRoute) {
664
+ status = "fail";
665
+ message = "No route recommendation was produced.";
666
+ } else if (topRoute.id !== testCase.expectedRouteId) {
667
+ status = "fail";
668
+ message = expectedRank >= 0
669
+ ? `Expected route appeared at rank ${expectedRank + 1}, but top route was ${topRoute.id}.`
670
+ : `Expected ${testCase.expectedRouteId}, but top route was ${topRoute.id}.`;
671
+ } else if (
672
+ testCase.minConfidence
673
+ && CONFIDENCE_ORDER[topRoute.confidence] < CONFIDENCE_ORDER[testCase.minConfidence]
674
+ ) {
675
+ status = "warn";
676
+ message = `Top route matched, but confidence ${topRoute.confidence} is below ${testCase.minConfidence}.`;
677
+ }
678
+
679
+ return {
680
+ id: testCase.id,
681
+ status,
682
+ message,
683
+ expectedRouteId: testCase.expectedRouteId,
684
+ topRouteId: topRoute?.id || "",
685
+ topConfidence: topRoute?.confidence || "",
686
+ topScore: topRoute?.score || 0,
687
+ expectedRank,
688
+ matchedKeywords: topRoute?.matchedKeywords || [],
689
+ brief: testCase.brief,
690
+ routes,
691
+ };
692
+ }
693
+
694
+ export function routeEvalReport({
695
+ evalText,
696
+ source = "route-eval.json",
697
+ sourceRoot,
698
+ limit = ROUTE_EVAL_DEFAULT_LIMIT,
699
+ generatedAt = new Date(),
700
+ }) {
701
+ const payload = normalizeRouteEvalPayload(evalText, source);
702
+ const normalizedCases = payload.cases.map((testCase, index) => normalizeRouteEvalCase(testCase, index));
703
+ const results = normalizedCases.map((testCase) => evaluateRouteEvalCase(testCase, sourceRoot, limit));
704
+ const counts = results.reduce(
705
+ (acc, result) => ({
706
+ ...acc,
707
+ [result.status]: acc[result.status] + 1,
708
+ }),
709
+ { pass: 0, warn: 0, fail: 0 },
710
+ );
711
+ const summary = {
712
+ total: results.length,
713
+ pass: counts.pass,
714
+ warn: counts.warn,
715
+ fail: counts.fail,
716
+ };
717
+
718
+ return {
719
+ version: readRouteManifestVersion(sourceRoot),
720
+ evalVersion: payload.version,
721
+ source,
722
+ generatedAt: isoTimestamp(generatedAt),
723
+ status: routeEvalStatus(counts),
724
+ summary,
725
+ cases: results,
726
+ };
727
+ }
728
+
729
+ export function readRouteManifestVersion(sourceRoot) {
730
+ try {
731
+ const manifest = JSON.parse(readFileSync(path.join(sourceRoot, ".claude-plugin", "plugin.json"), "utf8"));
732
+ return manifest.version || "unknown";
733
+ } catch {
734
+ return "unknown";
735
+ }
736
+ }
737
+
738
+ export function formatRouteJson(payload) {
739
+ return JSON.stringify(payload, null, 2);
740
+ }