@astryxdesign/cli 0.6.4 → 0.6.5-canary.01972bc

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 (405) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +103 -95
  3. package/api/build/_adapter.d.mts +36 -2
  4. package/api/build/_adapter.mjs +41 -10
  5. package/api/build/build.doc.mjs +8 -3
  6. package/api/build/build.test.mjs +60 -2
  7. package/api/build/kit/kit.mjs +109 -26
  8. package/api/build/kit/rank.d.mts +24 -8
  9. package/api/build/kit/rank.mjs +277 -97
  10. package/api/build/kit/rank.test.mjs +231 -48
  11. package/api/component/_adapter.d.mts +25 -0
  12. package/api/component/_adapter.mjs +59 -5
  13. package/api/component/component.d.mts +6 -3
  14. package/api/component/component.doc.mjs +37 -17
  15. package/api/component/component.mjs +249 -9
  16. package/api/component/component.type.d.mts +25 -0
  17. package/api/component/component.type.mjs +44 -0
  18. package/api/discover/_adapter.d.mts +114 -6
  19. package/api/discover/_adapter.mjs +372 -17
  20. package/api/discover/_adapter.test.mjs +215 -0
  21. package/api/discover/_catalog-view.d.mts +115 -0
  22. package/api/discover/_catalog-view.mjs +203 -0
  23. package/api/discover/_catalog-view.test.mjs +128 -0
  24. package/api/discover/detail/detail.d.mts +18 -6
  25. package/api/discover/detail/detail.mjs +67 -13
  26. package/api/discover/detail/detail.test.mjs +85 -0
  27. package/api/discover/detail/item/item.d.mts +26 -0
  28. package/api/discover/detail/item/item.mjs +78 -0
  29. package/api/discover/detail/item/item.test.mjs +73 -0
  30. package/api/discover/discover.d.mts +3 -9
  31. package/api/discover/discover.doc.mjs +61 -18
  32. package/api/discover/discover.mjs +220 -36
  33. package/api/discover/discover.test.mjs +11 -2
  34. package/api/discover/discover.type.d.mts +147 -8
  35. package/api/discover/discover.type.mjs +102 -12
  36. package/api/discover/list/list.d.mts +20 -6
  37. package/api/discover/list/list.mjs +45 -12
  38. package/api/discover/list/list.test.mjs +46 -0
  39. package/api/discover/search/search.d.mts +18 -16
  40. package/api/discover/search/search.mjs +102 -56
  41. package/api/discover/search/search.test.mjs +144 -10
  42. package/api/docs/_adapter.d.mts +8 -3
  43. package/api/docs/_adapter.mjs +14 -6
  44. package/api/docs/docOverlays.test.mjs +27 -1
  45. package/api/docs/docs.doc.mjs +2 -2
  46. package/api/docs/docs.test.mjs +54 -18
  47. package/api/docs/integration-tree.test.mjs +17 -0
  48. package/api/docs/integrationDocs.test.mjs +27 -5
  49. package/api/doctor/doctor.d.mts +8 -3
  50. package/api/doctor/doctor.doc.mjs +17 -8
  51. package/api/doctor/doctor.mjs +90 -9
  52. package/api/doctor/doctor.test.mjs +122 -10
  53. package/api/doctor/doctor.type.d.mts +1 -1
  54. package/api/doctor/doctor.type.mjs +1 -1
  55. package/api/error.d.mts +22 -0
  56. package/api/error.mjs +42 -0
  57. package/api/gap-report/gap-report.doc.mjs +19 -10
  58. package/api/hook/hook.doc.mjs +6 -3
  59. package/api/index.d.mts +1 -0
  60. package/api/index.mjs +5 -3
  61. package/api/init/init.doc.mjs +17 -12
  62. package/api/integration/add-contribution.d.mts +2 -1
  63. package/api/integration/add-contribution.mjs +7 -3
  64. package/api/integration/add-contribution.test.mjs +3 -3
  65. package/api/integration/add-helpers.d.mts +5 -2
  66. package/api/integration/add-helpers.mjs +36 -9
  67. package/api/integration/add-theme.mjs +266 -23
  68. package/api/integration/add-theme.test.mjs +247 -0
  69. package/api/integration/authoring-checks.mjs +12 -9
  70. package/api/integration/authoring-checks.type.d.mts +8 -0
  71. package/api/integration/authoring-checks.type.mjs +7 -3
  72. package/api/integration/integration-authoring.type.d.mts +4 -1
  73. package/api/integration/integration-authoring.type.mjs +6 -1
  74. package/api/integration/integrationAdd.doc.mjs +6 -0
  75. package/api/integration/integrationAddTheme.doc.mjs +10 -0
  76. package/api/integration/integrationComponentConflicts.doc.mjs +1 -1
  77. package/api/integration/integrationDocConflicts.doc.mjs +1 -1
  78. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  79. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -1
  80. package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
  81. package/api/integration/pack-check.mjs +92 -10
  82. package/api/integration/pack-check.test.mjs +140 -1
  83. package/api/integration/pack-check.type.mjs +1 -1
  84. package/api/integration/validate-integration.d.mts +4 -2
  85. package/api/integration/validate-integration.mjs +7 -2
  86. package/api/integration/validate-integration.test.mjs +55 -0
  87. package/api/integration/validate-integration.type.d.mts +5 -0
  88. package/api/integration/validate-integration.type.mjs +5 -1
  89. package/api/integration/validateIntegration.doc.mjs +1 -1
  90. package/api/json/assertResponse.doc.mjs +1 -1
  91. package/api/json/isError.doc.mjs +1 -1
  92. package/api/layout/expand/expand.mjs +12 -7
  93. package/api/layout/expand/expand.receipt.test.mjs +74 -0
  94. package/api/layout/layout.type.d.mts +1 -0
  95. package/api/layout/layout.type.mjs +1 -0
  96. package/api/layout/layoutExpand.doc.mjs +1 -1
  97. package/api/search/search.d.mts +51 -1
  98. package/api/search/search.doc.mjs +2 -2
  99. package/api/search/search.mjs +299 -17
  100. package/api/search/search.test.mjs +216 -18
  101. package/api/swizzle/copy/copy.mjs +66 -3
  102. package/api/swizzle/swizzle.doc.mjs +11 -5
  103. package/api/template/copy/copy.mjs +15 -9
  104. package/api/template/copy/copy.receipt.test.mjs +77 -0
  105. package/api/template/copy/copy.test.mjs +9 -0
  106. package/api/template/show/show.mjs +15 -4
  107. package/api/template/show/show.test.mjs +76 -0
  108. package/api/template/template-integration.test.mjs +14 -0
  109. package/api/template/template.d.mts +1 -1
  110. package/api/template/template.doc.mjs +8 -3
  111. package/api/template/template.mjs +1 -0
  112. package/api/template/template.type.d.mts +2 -0
  113. package/api/template/template.type.mjs +2 -0
  114. package/api/theme/add/add.mjs +17 -25
  115. package/api/theme/add/add.rollback.test.mjs +158 -0
  116. package/api/theme/add/add.staging.test.mjs +40 -23
  117. package/api/theme/build/build.d.mts +24 -0
  118. package/api/theme/build/build.family.test.mjs +7 -12
  119. package/api/theme/build/build.mjs +243 -26
  120. package/api/theme/build/build.project-core.test.mjs +165 -0
  121. package/api/theme/build/build.rollback.test.mjs +148 -0
  122. package/api/theme/generateTonalPalette.doc.mjs +1 -2
  123. package/api/theme/listThemes.doc.mjs +1 -1
  124. package/api/theme/themeAdd.doc.mjs +9 -10
  125. package/api/theme/themeBuild.doc.mjs +13 -13
  126. package/api/theme/themeList.doc.mjs +1 -1
  127. package/api/theme/themeListAvailable.doc.mjs +2 -1
  128. package/api/theme/themePaletteGenerate.doc.mjs +15 -8
  129. package/api/theme/themeTargets.doc.mjs +3 -2
  130. package/api/theme/themeTemplate.doc.mjs +2 -1
  131. package/api/upgrade/run/files-changed.test.mjs +111 -0
  132. package/api/upgrade/run/run.mjs +25 -6
  133. package/api/upgrade/run/run.test.mjs +45 -1
  134. package/api/upgrade/upgrade.doc.mjs +24 -22
  135. package/api/upgrade/upgrade.type.d.mts +1 -0
  136. package/api/upgrade/upgrade.type.mjs +3 -2
  137. package/assets/codemods/__tests__/runner.test.mjs +3 -1
  138. package/assets/codemods/file-count.test.mjs +163 -0
  139. package/assets/codemods/integration-runner.mjs +3 -3
  140. package/assets/codemods/runner.mjs +5 -4
  141. package/assets/docs/README.md +4 -2
  142. package/assets/docs/browser-support.doc.mjs +11 -11
  143. package/assets/docs/color.doc.mjs +8 -2
  144. package/assets/docs/elevation.doc.mjs +6 -4
  145. package/assets/docs/getting-started.doc.mjs +5 -16
  146. package/assets/docs/icons.doc.mjs +3 -21
  147. package/assets/docs/illustrations.doc.mjs +7 -15
  148. package/assets/docs/internationalization.doc.mjs +7 -5
  149. package/assets/docs/layout.doc.dense.mjs +130 -82
  150. package/assets/docs/layout.doc.mjs +133 -77
  151. package/assets/docs/migration.doc.mjs +19 -21
  152. package/assets/docs/motion.doc.mjs +16 -3
  153. package/assets/docs/principles.doc.dense.mjs +5 -5
  154. package/assets/docs/principles.doc.mjs +8 -0
  155. package/assets/docs/principles.doc.zh.mjs +6 -6
  156. package/assets/docs/shape.doc.mjs +8 -3
  157. package/assets/docs/spacing.doc.mjs +7 -2
  158. package/assets/docs/styling-libraries.doc.mjs +6 -2
  159. package/assets/docs/styling.doc.mjs +19 -23
  160. package/assets/docs/theme.doc.dense.mjs +58 -18
  161. package/assets/docs/theme.doc.mjs +57 -47
  162. package/assets/docs/theme.doc.zh.mjs +9 -8
  163. package/assets/docs/tokens.doc.dense.mjs +2 -2
  164. package/assets/docs/tokens.doc.mjs +389 -8
  165. package/assets/docs/tokens.doc.zh.mjs +2 -2
  166. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  167. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  168. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  169. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  170. package/assets/docs/tree/block-template.doc.mjs +130 -0
  171. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  172. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  173. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  174. package/assets/docs/tree/checks.doc.mjs +119 -0
  175. package/assets/docs/tree/codemods.doc.mjs +147 -0
  176. package/assets/docs/tree/component-family.doc.mjs +113 -0
  177. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  178. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  179. package/assets/docs/tree/components.doc.mjs +23 -0
  180. package/assets/docs/tree/configuration.doc.mjs +23 -0
  181. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  182. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  183. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  184. package/assets/docs/tree/docs.doc.mjs +21 -0
  185. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  186. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  187. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  188. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  189. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  190. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  191. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  192. package/assets/docs/tree/help.doc.mjs +16 -0
  193. package/assets/docs/tree/integrations.doc.mjs +25 -451
  194. package/assets/docs/tree/links.doc.mjs +98 -0
  195. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  196. package/assets/docs/tree/page-template.doc.mjs +71 -0
  197. package/assets/docs/tree/publishing.doc.mjs +111 -0
  198. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  199. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  200. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  201. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  202. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  203. package/assets/docs/tree/ship.doc.mjs +16 -0
  204. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  205. package/assets/docs/tree/single-component.doc.mjs +165 -0
  206. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  207. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  208. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  209. package/assets/docs/tree/template-doc-overview.doc.mjs +121 -0
  210. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  211. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  212. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  213. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  214. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  215. package/assets/docs/tree/templates.doc.mjs +34 -0
  216. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  217. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  218. package/assets/docs/tree/themes.doc.mjs +39 -0
  219. package/assets/docs/tree/troubleshooting.doc.mjs +153 -0
  220. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  221. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  222. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  223. package/assets/docs/tree/versioning.doc.mjs +162 -0
  224. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  225. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  226. package/assets/docs/typography.doc.mjs +24 -4
  227. package/assets/docs/working-with-ai.doc.mjs +30 -22
  228. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  229. package/assets/templates/pages/ai-chat/template.doc.mjs +16 -1
  230. package/assets/templates/pages/ai-chat-landing/template.doc.mjs +9 -1
  231. package/assets/templates/pages/blank/template.doc.mjs +3 -1
  232. package/assets/templates/pages/canvas-editor/template.doc.mjs +9 -1
  233. package/assets/templates/pages/centered-hero/template.doc.mjs +3 -1
  234. package/assets/templates/pages/checkout-wizard/template.doc.mjs +1 -0
  235. package/assets/templates/pages/classic-gallery/template.doc.mjs +3 -1
  236. package/assets/templates/pages/contact-form/template.doc.mjs +16 -1
  237. package/assets/templates/pages/dashboard/template.doc.mjs +15 -1
  238. package/assets/templates/pages/dashboard-alert-rail/template.doc.mjs +23 -1
  239. package/assets/templates/pages/dashboard-cohort-funnel/template.doc.mjs +10 -1
  240. package/assets/templates/pages/dashboard-comparison/template.doc.mjs +9 -1
  241. package/assets/templates/pages/dashboard-composition/template.doc.mjs +10 -1
  242. package/assets/templates/pages/dashboard-progress/template.doc.mjs +17 -1
  243. package/assets/templates/pages/dashboard-scorecard/template.doc.mjs +2 -1
  244. package/assets/templates/pages/detail-page/template.doc.mjs +8 -0
  245. package/assets/templates/pages/documentation/template.doc.mjs +10 -1
  246. package/assets/templates/pages/documentation-design/template.doc.mjs +10 -1
  247. package/assets/templates/pages/documentation-technical/template.doc.mjs +10 -1
  248. package/assets/templates/pages/editor/template.doc.mjs +9 -1
  249. package/assets/templates/pages/file-explorer/template.doc.mjs +3 -1
  250. package/assets/templates/pages/form-two-column/template.doc.mjs +17 -1
  251. package/assets/templates/pages/form-wizard/template.doc.mjs +14 -1
  252. package/assets/templates/pages/form-wizard-dialog/template.doc.mjs +1 -0
  253. package/assets/templates/pages/gallery-hero/template.doc.mjs +10 -1
  254. package/assets/templates/pages/ide/template.doc.mjs +9 -1
  255. package/assets/templates/pages/incident-console/template.doc.mjs +10 -1
  256. package/assets/templates/pages/kanban-board/template.doc.mjs +11 -1
  257. package/assets/templates/pages/library/template.doc.mjs +15 -1
  258. package/assets/templates/pages/login/template.doc.mjs +10 -1
  259. package/assets/templates/pages/login-card/template.doc.mjs +11 -1
  260. package/assets/templates/pages/login-split/template.doc.mjs +10 -1
  261. package/assets/templates/pages/login-sso/template.doc.mjs +10 -1
  262. package/assets/templates/pages/messaging-shell/template.doc.mjs +11 -1
  263. package/assets/templates/pages/mixed-gallery/template.doc.mjs +10 -1
  264. package/assets/templates/pages/payment-form/template.doc.mjs +3 -1
  265. package/assets/templates/pages/product-detail/template.doc.mjs +9 -1
  266. package/assets/templates/pages/product-gallery/template.doc.mjs +10 -1
  267. package/assets/templates/pages/settings/template.doc.mjs +3 -1
  268. package/assets/templates/pages/settings-dialog/template.doc.mjs +9 -1
  269. package/assets/templates/pages/settings-sidebar/template.doc.mjs +9 -1
  270. package/assets/templates/pages/shell-nav/template.doc.mjs +10 -1
  271. package/assets/templates/pages/shell-side-nav/template.doc.mjs +14 -1
  272. package/assets/templates/pages/shell-top-nav/template.doc.mjs +11 -1
  273. package/assets/templates/pages/side-gallery/template.doc.mjs +3 -1
  274. package/assets/templates/pages/table/template.doc.mjs +11 -1
  275. package/assets/templates/pages/table-filter/template.doc.mjs +21 -1
  276. package/assets/templates/pages/table-grouped/template.doc.mjs +15 -1
  277. package/assets/templates/pages/table-inbox/template.doc.mjs +18 -6
  278. package/assets/templates/pages/table-page/template.doc.mjs +20 -1
  279. package/assets/templates/pages/table-tree/template.doc.mjs +14 -1
  280. package/assets/templates/pages/theme-showcase/template.doc.mjs +10 -1
  281. package/assets/templates/pages/work-item-detail/template.doc.mjs +10 -0
  282. package/assets/templates/themes/butter/icons.tsx +2 -0
  283. package/assets/templates/themes/chocolate/icons.tsx +2 -0
  284. package/assets/templates/themes/gothic/icons.tsx +2 -0
  285. package/assets/templates/themes/matcha/icons.tsx +2 -0
  286. package/assets/templates/themes/neutral/icons.tsx +2 -0
  287. package/assets/templates/themes/stone/icons.tsx +2 -0
  288. package/assets/templates/themes/y2k/icons.tsx +2 -0
  289. package/authoring/config/config.doc.mjs +9 -1
  290. package/authoring/config/parse.d.mts +2 -0
  291. package/authoring/config/parse.mjs +19 -0
  292. package/authoring/config/parse.test.mjs +8 -0
  293. package/authoring/config/type.ts +11 -0
  294. package/authoring/discover/discover.doc.d.mts +13 -0
  295. package/authoring/discover/discover.doc.mjs +138 -0
  296. package/authoring/discover/parse.d.mts +24 -0
  297. package/authoring/discover/parse.mjs +128 -0
  298. package/authoring/discover/parse.test.mjs +124 -0
  299. package/authoring/discover/type.ts +87 -0
  300. package/authoring/doctypes/_schema.d.mts +3 -2
  301. package/authoring/doctypes/_schema.mjs +6 -0
  302. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  303. package/authoring/doctypes/base/type.ts +4 -2
  304. package/authoring/doctypes/component/component.doc.mjs +6 -0
  305. package/authoring/doctypes/component/type.ts +8 -0
  306. package/authoring/doctypes/reference/reference.doc.mjs +7 -0
  307. package/authoring/doctypes/reference/type.ts +5 -0
  308. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  309. package/authoring/doctypes/template/parse.d.mts +2 -0
  310. package/authoring/doctypes/template/parse.mjs +1 -0
  311. package/authoring/doctypes/template/parse.test.mjs +21 -0
  312. package/authoring/doctypes/template/template.doc.mjs +7 -1
  313. package/authoring/doctypes/template/type.ts +12 -2
  314. package/authoring/index.d.mts +1 -0
  315. package/authoring/index.d.ts +10 -0
  316. package/authoring/index.mjs +1 -0
  317. package/authoring/integration/integration.doc.mjs +12 -10
  318. package/clients/cli/commands/component/index.mjs +152 -55
  319. package/clients/cli/commands/component-batch.test.mjs +341 -0
  320. package/clients/cli/commands/component-ownership.test.mjs +89 -0
  321. package/clients/cli/commands/component.doc.mjs +27 -9
  322. package/clients/cli/commands/discover.doc.mjs +53 -9
  323. package/clients/cli/commands/discover.mjs +393 -118
  324. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  325. package/clients/cli/commands/docs.doc.mjs +1 -1
  326. package/clients/cli/commands/docs.mjs +60 -17
  327. package/clients/cli/commands/docs.test.mjs +113 -24
  328. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
  329. package/clients/cli/commands/doctor-integration.test.mjs +53 -0
  330. package/clients/cli/commands/doctor.doc.mjs +3 -1
  331. package/clients/cli/commands/doctor.mjs +53 -9
  332. package/clients/cli/commands/gap-report.doc.mjs +10 -9
  333. package/clients/cli/commands/init.doc.mjs +9 -6
  334. package/clients/cli/commands/integration-add.doc.mjs +17 -7
  335. package/clients/cli/commands/integration-authoring.test.mjs +70 -9
  336. package/clients/cli/commands/integration-pack.doc.mjs +5 -9
  337. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  338. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  339. package/clients/cli/commands/integration.doc.mjs +4 -4
  340. package/clients/cli/commands/integration.mjs +76 -43
  341. package/clients/cli/commands/layout-expand.doc.mjs +3 -1
  342. package/clients/cli/commands/layout.expand-receipt.test.mjs +94 -0
  343. package/clients/cli/commands/layout.mjs +16 -0
  344. package/clients/cli/commands/manifest.doc.mjs +1 -1
  345. package/clients/cli/commands/search.doc.mjs +10 -3
  346. package/clients/cli/commands/search.mjs +21 -2
  347. package/clients/cli/commands/search.test.mjs +21 -4
  348. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  349. package/clients/cli/commands/template.copy-receipt.test.mjs +60 -0
  350. package/clients/cli/commands/template.doc.mjs +1 -1
  351. package/clients/cli/commands/template.mjs +19 -5
  352. package/clients/cli/commands/template.show-media.test.mjs +62 -0
  353. package/clients/cli/commands/text-json-parity.test.mjs +7 -1
  354. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  355. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
  356. package/clients/cli/commands/theme-palette.doc.mjs +1 -2
  357. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  358. package/clients/cli/commands/theme.doc.mjs +2 -1
  359. package/clients/cli/commands/upgrade.ascii-output.test.mjs +14 -0
  360. package/clients/cli/commands/upgrade.doc.mjs +62 -3
  361. package/clients/cli/commands/write-failure.test.mjs +175 -0
  362. package/clients/cli/index.mjs +28 -6
  363. package/clients/cli/lib/define-command.mjs +28 -4
  364. package/clients/cli/lib/define-command.test.mjs +54 -0
  365. package/clients/cli/lib/exit-codes.test.mjs +17 -1
  366. package/clients/cli/lib/json-shim.mjs +24 -14
  367. package/clients/cli/lib/manifest.mjs +48 -156
  368. package/clients/cli/lib/manifest.test.mjs +103 -9
  369. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  370. package/foundation/agent-docs/agent-docs.mjs +1 -1
  371. package/foundation/agent-docs/agent-docs.test.mjs +3 -2
  372. package/foundation/discovery/authoring-self-docs.mjs +1 -0
  373. package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
  374. package/foundation/discovery/cli-self-docs.mjs +16 -2
  375. package/foundation/discovery/cli-self-docs.test.mjs +20 -0
  376. package/foundation/discovery/docs-discovery.mjs +5 -1
  377. package/foundation/discovery/docs-discovery.test.mjs +21 -0
  378. package/foundation/discovery/docs-section-key.d.mts +1 -1
  379. package/foundation/discovery/docs-section-key.mjs +1 -1
  380. package/foundation/discovery/template-adapter.d.mts +14 -0
  381. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +37 -1
  382. package/foundation/discovery/template-adapter.mjs +21 -1
  383. package/foundation/doc-compiler/doc-loads.test.mjs +5 -4
  384. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  385. package/foundation/doc-compiler/tree.d.mts +4 -0
  386. package/foundation/doc-compiler/tree.mjs +6 -1
  387. package/foundation/doc-compiler/tree.test.mjs +65 -14
  388. package/foundation/integrations/cli-requirement.d.mts +75 -11
  389. package/foundation/integrations/cli-requirement.mjs +120 -23
  390. package/foundation/integrations/cli-requirement.test.mjs +141 -9
  391. package/foundation/integrations/contribution-inventory.mjs +1 -1
  392. package/foundation/integrations/integrations.d.mts +14 -1
  393. package/foundation/integrations/integrations.mjs +41 -1
  394. package/foundation/integrations/integrations.test.mjs +31 -0
  395. package/foundation/response/batch.type.d.mts +33 -0
  396. package/foundation/response/batch.type.mjs +34 -0
  397. package/foundation/response/error-codes.doc.mjs +6 -8
  398. package/foundation/response/error-codes.test.mjs +30 -5
  399. package/foundation/response/response-types.doc.d.mts +5 -4
  400. package/foundation/response/response-types.doc.mjs +49 -19
  401. package/foundation/response/response-types.doc.test.mjs +23 -0
  402. package/foundation/response/response.doc.mjs +11 -10
  403. package/package.json +9 -9
  404. package/assets/docs/tree/integrations.test.mjs +0 -62
  405. package/assets/docs/tree/writing-docs.doc.mjs +0 -286
@@ -13,6 +13,7 @@ vi.mock('../../../foundation/discovery/template-conflict-release.mjs', () => ({
13
13
  expandedTemplateConflictSchemaActive: () => true,
14
14
  }));
15
15
  import * as fs from 'node:fs';
16
+ import * as os from 'node:os';
16
17
  import * as path from 'node:path';
17
18
  import {Command} from 'commander';
18
19
  import {discoverCoreTemplates} from '../../../foundation/discovery/template-adapter.mjs';
@@ -344,6 +345,35 @@ describe('doctor integration — command', () => {
344
345
  expect(process.exitCode).toBe(1);
345
346
  });
346
347
 
348
+ it('components exits 1 when Core is missing, with no [ok] after the failure', async () => {
349
+ // Outside the repo, so nothing above the package resolves Core.
350
+ const outside = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-no-core-'));
351
+ const previousTmp = tmpDir;
352
+ tmpDir = outside;
353
+ try {
354
+ writeComponentIntegration('AcmeCarousel');
355
+ expect(findCoreDir(outside)).toBeNull();
356
+ process.chdir(outside);
357
+
358
+ await createProgram().parseAsync([
359
+ 'node',
360
+ 'astryx',
361
+ 'doctor',
362
+ 'integration',
363
+ 'components',
364
+ ]);
365
+
366
+ const printed = logCalls.join('\n');
367
+ expect(printed).toContain('core_not_found');
368
+ expect(printed).not.toContain('[ok]');
369
+ expect(process.exitCode).toBe(1);
370
+ } finally {
371
+ tmpDir = previousTmp;
372
+ process.chdir(previousCwd);
373
+ fs.rmSync(outside, {recursive: true, force: true});
374
+ }
375
+ });
376
+
347
377
  it('components warns with the exact package-qualified command', async () => {
348
378
  const coreDir = findCoreDir(tmpDir);
349
379
  expect(coreDir).not.toBeNull();
@@ -433,6 +463,29 @@ describe('doctor integration — command', () => {
433
463
  expect(process.exitCode).toBeUndefined();
434
464
  });
435
465
 
466
+ it('docs exits 1 for a placement that hides a guide, with no [ok] after the failure', async () => {
467
+ writeDocIntegration({name: 'deploying'});
468
+ fs.writeFileSync(
469
+ path.join(tmpDir, 'docs', 'deploying.doc.mjs'),
470
+ "export default {type: 'generic', name: 'deploying', title: 'Deploying', description: 'Deploy.', placement: {parent: 'namespace:nope', slot: 'guides'}, sections: [{title: 'Deploy', content: [{type: 'prose', text: 'Deploy.'}]}]};\n",
471
+ );
472
+ process.chdir(tmpDir);
473
+
474
+ await createProgram().parseAsync([
475
+ 'node',
476
+ 'astryx',
477
+ 'doctor',
478
+ 'integration',
479
+ 'docs',
480
+ ]);
481
+
482
+ const printed = logCalls.join('\n');
483
+ expect(printed).toContain('[fail]');
484
+ expect(printed).toContain('invalid_doc_graph');
485
+ expect(printed).not.toContain('[ok]');
486
+ expect(process.exitCode).toBe(1);
487
+ });
488
+
436
489
  it('docs exits 1 for an accidental same-name Core topic', async () => {
437
490
  const [coreTopic] = Object.keys(discoverBuiltinTopics());
438
491
  writeDocIntegration({name: coreTopic});
@@ -16,7 +16,9 @@ export const doc = {
16
16
  summary: 'Diagnose Astryx projects and integration packages',
17
17
  description:
18
18
  'Runs read-only project health diagnostics by default: Node version, @astryxdesign/core ' +
19
- 'install and version alignment, themes, config, agent docs, and package manager. ' +
19
+ 'install and version alignment, themes, config, integrations (linked without a config entry, ' +
20
+ 'provider identity, contribution issues), agent docs, core peer dependencies, package manager, ' +
21
+ "and the docs the CLI reads. It writes nothing, but loading astryx.config runs that file's code. " +
20
22
  'The `integration` subcommands provide authoring checks for one integration package.',
21
23
  fn: 'doctor',
22
24
  subcommands: ['integration'],
@@ -36,6 +36,8 @@ import {doc as integrationTemplateConflictsFn} from '../../../api/integration/in
36
36
  import {doc as integrationComponentConflictsFn} from '../../../api/integration/integrationComponentConflicts.doc.mjs';
37
37
  import {doc as integrationDocConflictsFn} from '../../../api/integration/integrationDocConflicts.doc.mjs';
38
38
  import {NO_RESULT_SET} from '../../../foundation/debug/index.mjs';
39
+ import {cliError} from '../lib/cli-error.mjs';
40
+ import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
39
41
 
40
42
  const STATUS = {
41
43
  pass: '[ok]',
@@ -181,8 +183,10 @@ function printComponentConflicts(data) {
181
183
  ),
182
184
  ...issueBlocks(data.issues),
183
185
  ];
186
+ // An [ok] after a failed check reads as a pass: say nothing it could not check.
187
+ const failed = data.issues.some(issue => issue.severity === 'error');
184
188
  if (data.conflicts.length === 0) {
185
- output.push(text('[ok] No component names conflict with Core.'));
189
+ if (!failed) output.push(text('[ok] No component names conflict with Core.'));
186
190
  } else {
187
191
  output.push(
188
192
  records(data.conflicts, {
@@ -224,7 +228,9 @@ function printDocConflicts(data) {
224
228
  );
225
229
  }
226
230
  if (data.findings.length === 0) {
227
- output.push(text('[ok] No doc topics overlap with Core.'));
231
+ if (!data.issues.some(issue => issue.severity === 'error')) {
232
+ output.push(text('[ok] No doc topics overlap with Core.'));
233
+ }
228
234
  } else {
229
235
  output.push(
230
236
  records(data.findings, {
@@ -252,10 +258,10 @@ async function runProjectDoctor(program) {
252
258
  async function runIntegrationValidation(program, pkg) {
253
259
  const result = await validateIntegration(pkg);
254
260
  if (program.opts().json) jsonOut(result);
255
- else if (result.data.name === null) {
261
+ else if (!result.data.validated) {
256
262
  emit(
257
263
  text(
258
- 'No astryx.integration.* found next to package.json. ' +
264
+ 'Nothing was validated: no astryx.integration.* found next to package.json. ' +
259
265
  'To validate an installed integration: astryx doctor integration validate <package>',
260
266
  ),
261
267
  );
@@ -278,10 +284,10 @@ async function runAuthoringCheck(program, pkg, kind) {
278
284
  : await integrationDocConflicts(pkg);
279
285
 
280
286
  if (program.opts().json) jsonOut(result);
281
- else if (result.data.name === null) {
287
+ else if (!result.data.validated) {
282
288
  emit(
283
289
  text(
284
- 'No astryx.integration.* found next to package.json. ' +
290
+ 'Nothing was checked: no astryx.integration.* found next to package.json. ' +
285
291
  `To check an installed integration: astryx doctor integration ${kind} <package>`,
286
292
  ),
287
293
  );
@@ -315,19 +321,57 @@ async function runAuthoringCheck(program, pkg, kind) {
315
321
  return NO_RESULT_SET;
316
322
  }
317
323
 
324
+ /**
325
+ * The first word after a command group, which names a subcommand it does not
326
+ * have, or null.
327
+ * @param {import('commander').Command | undefined} invoked
328
+ * @returns {string | null}
329
+ */
330
+ function unknownWord(invoked) {
331
+ const word = (invoked?.args ?? []).find(arg => !String(arg).startsWith('-'));
332
+ return word == null ? null : String(word);
333
+ }
334
+
335
+ /**
336
+ * Report an unknown subcommand, in text as in JSON, with the ones the group has.
337
+ * @param {import('commander').Command} group
338
+ * @param {string} label the group's full name
339
+ * @param {string} word
340
+ */
341
+ function unknownSubcommand(group, label, word) {
342
+ return cliError(`unknown subcommand '${label} ${word}'`, {
343
+ suggestions: group.commands.map(child => ({
344
+ name: child.name(),
345
+ reason: 'available subcommand',
346
+ })),
347
+ code: ERROR_CODES.ERR_UNKNOWN_SUBCOMMAND,
348
+ });
349
+ }
350
+
318
351
  /**
319
352
  * Register `astryx doctor` and its integration-authoring leaves.
320
353
  * @param {import('commander').Command} program
321
354
  */
322
355
  export function registerDoctor(program) {
323
- const doctorCmd = defineCommand(program, doctorCommand, {
356
+ /** @type {import('commander').Command} */
357
+ let doctorCmd;
358
+ doctorCmd = defineCommand(program, doctorCommand, {
324
359
  fn: doctorFn,
325
- action: async () => runProjectDoctor(program),
360
+ // `doctor integrations` is a mistyped subcommand, not a project check.
361
+ action: async (options, invoked) => {
362
+ const word = unknownWord(invoked);
363
+ if (word != null) return unknownSubcommand(doctorCmd, 'doctor', word);
364
+ return runProjectDoctor(program);
365
+ },
326
366
  });
327
367
  /** @type {import('commander').Command} */
328
368
  let integrationCmd;
329
369
  integrationCmd = defineCommand(doctorCmd, doctorIntegrationGroup, {
330
- action: () => {
370
+ action: (options, invoked) => {
371
+ const word = unknownWord(invoked);
372
+ if (word != null) {
373
+ return unknownSubcommand(integrationCmd, 'doctor integration', word);
374
+ }
331
375
  integrationCmd.outputHelp();
332
376
  return NO_RESULT_SET;
333
377
  },
@@ -11,9 +11,12 @@ export const doc = {
11
11
  name: 'gap-report',
12
12
  displayName: 'astryx gap-report',
13
13
  namespace: 'cli/commands',
14
- summary: 'Route a design-system gap to its owning package',
14
+ summary: 'Report a missing component or feature to the package that owns it',
15
15
  description:
16
- 'Reports a missing component, variant, layout, styling, accessibility, API, or documentation capability. The command selects an explicit package first, then a unique component owner, then Core. The report fans out to every effective handler: project config first, then each loaded integration in config order. Public handlers require --confirm-public per handler; internal handlers always run. A handler failure is isolated and does not prevent later handlers.',
16
+ 'Reports a missing component, variant, layout, styling, accessibility, API, or documentation capability to the package that owns it: the --package you name, else the one package that provides the component, else Core. ' +
17
+ 'Every configured handler receives the report: the project config handler first, then each integration handler in config order. Public handlers run only with --confirm-public; internal handlers always run. A failing handler does not stop the others. ' +
18
+ "With no handler it files a GitHub issue for the owning package, only with --confirm-public (without it nothing is sent), or returns the package's issues URL when that is not on GitHub. " +
19
+ 'The report records whether an agent or a person ran it.',
17
20
  fn: 'gapReport',
18
21
  args: [
19
22
  {
@@ -45,12 +48,14 @@ export const doc = {
45
48
  {
46
49
  flag: '--package <pkg>',
47
50
  param: 'options.package',
48
- description: 'Route to a specific loaded package',
51
+ description:
52
+ 'Package that owns the gap: @astryxdesign/core or a loaded integration. Overrides automatic routing; needed when more than one package provides the component',
49
53
  },
50
54
  {
51
55
  flag: '--confirm-public',
52
56
  param: 'options.confirmPublic',
53
- description: 'Consent to public handlers or GitHub issue creation',
57
+ description:
58
+ 'Allow public delivery: public handlers run, and with no handler it files a GitHub issue with your gh login',
54
59
  },
55
60
  {
56
61
  flag: '--list-categories',
@@ -62,13 +67,9 @@ export const doc = {
62
67
  examples: [
63
68
  {label: 'List categories', cli: 'astryx gap-report --list-categories'},
64
69
  {
65
- label: 'Route an agent report',
70
+ label: 'Prepare a report (nothing public happens without --confirm-public)',
66
71
  cli: "astryx gap-report Button --category missing_variant --reason 'Need a compact size'",
67
72
  },
68
- {
69
- label: 'Confirm public filing',
70
- cli: "astryx gap-report Button --category docs_gap --reason 'Missing keyboard example' --confirm-public",
71
- },
72
73
  ],
73
74
  exitCodes: [
74
75
  {
@@ -18,21 +18,22 @@ export const doc = {
18
18
  'Non-interactive project setup (no prompts, so it behaves the same for humans, ' +
19
19
  'agents, and CI). By default it installs the AGENTS.md/CLAUDE.md agent-docs, ' +
20
20
  'including guidance from configured integrations, and prints getting-started ' +
21
- 'guidance; features/--all add theme and page-building ' +
22
- 'guidance and write an annotated theme template.',
21
+ "steps. --features and --all print only the chosen features' guidance (no " +
22
+ 'getting-started steps); the theme feature also writes an annotated theme template.',
23
23
  fn: 'init',
24
24
  options: [
25
25
  {
26
26
  flag: '--features <list>',
27
27
  param: 'options.features',
28
28
  description:
29
- 'Comma-separated features to install (agents, theme, template). An unknown feature exits 1 with ERR_UNKNOWN_FEATURE. ' +
30
- 'Ignored with --all or --remove-agents',
29
+ 'Comma-separated features: agents (agent docs), theme (writes theme.template.ts), template (prints the page-building commands; writes no file). ' +
30
+ 'An unknown feature exits 1 with ERR_UNKNOWN_FEATURE. Ignored with --all or --remove-agents',
31
31
  },
32
32
  {
33
33
  flag: '--all',
34
34
  param: 'options.all',
35
- description: 'Install all features (agents, theme, template); overrides --features',
35
+ description:
36
+ 'Install all features (agents, theme, template); overrides --features. Prints their guidance instead of the getting-started steps',
36
37
  },
37
38
  {
38
39
  flag: '--remove-agents',
@@ -47,7 +48,9 @@ export const doc = {
47
48
  param: 'options.agent',
48
49
  choices: ['claude', 'cursor', 'codex', 'hermes', 'muse', 'all'],
49
50
  description:
50
- 'Target AI tool for agent docs: claude, cursor, codex, hermes, muse, all. An unknown tool exits 1 with ERR_UNKNOWN_AGENT. ' +
51
+ 'Target AI tool for agent docs: claude (CLAUDE.md or .claude/CLAUDE.md, else creates .claude/CLAUDE.md), cursor (.cursorrules if present, else AGENTS.md), ' +
52
+ 'codex and muse (AGENTS.md), hermes (.hermes.md or HERMES.md if present, else AGENTS.md), all (every existing agent doc, else AGENTS.md and .claude/CLAUDE.md). ' +
53
+ 'An unknown tool exits 1 with ERR_UNKNOWN_AGENT. ' +
51
54
  'Used only when agent docs are installed (the default, --all, or --features agents); --agent-docs-path takes precedence',
52
55
  },
53
56
  {
@@ -8,7 +8,7 @@ export const doc = {
8
8
  namespace: 'cli/commands',
9
9
  summary: 'Add one working contribution to an integration package',
10
10
  description:
11
- 'Writes the complete minimum shape the selected contribution needs, creates the integration manifest on first use, declares the root only after a valid contribution exists, and verifies the result through the same discovery contract the packed-package check uses.',
11
+ 'Writes the files one contribution needs, creates the integration manifest on first use, and declares a root only after a contribution the CLI can read exists behind it. A component or template import also needs an `exports` entry: add writes one only when package.json already has an `exports` map, so start a new package with `"exports": {}`. See {@link generic:quick-start}.',
12
12
  fn: 'integrationAdd',
13
13
  args: [
14
14
  {
@@ -56,14 +56,24 @@ export const doc = {
56
56
  description:
57
57
  "Namespace of this package to place the doc in, as a guide in its `guides` slot; writes the namespace doc when it is missing, and declares the CLI that reads it as an optional `@astryxdesign/cli` peer. Only valid for doc, and not with --replaces or --extends",
58
58
  },
59
+ {
60
+ flag: '--from <theme>',
61
+ param: 'options.from',
62
+ description:
63
+ 'Existing theme slug to fork as a starting point instead of a blank scaffold; the new theme copies the base and has no link back. Only valid for theme',
64
+ },
59
65
  {
60
66
  flag: '--to <version>',
61
67
  param: 'options.to',
62
68
  description:
63
- 'Exact semver the codemod migrates to (e.g. 1.2.0); required for codemod and only valid there',
69
+ 'Exact semver of the @astryxdesign/core version whose upgrade runs the codemod (e.g. 0.7.0); required for codemod and only valid there',
64
70
  },
65
71
  ],
66
72
  examples: [
73
+ {
74
+ label: 'Preview',
75
+ cli: 'astryx integration add component AcmeWidget --dry-run --json',
76
+ },
67
77
  {
68
78
  label: 'Add a component',
69
79
  cli: 'astryx integration add component AcmeWidget',
@@ -71,7 +81,7 @@ export const doc = {
71
81
  {label: 'Add a doc topic', cli: 'astryx integration add doc deploying'},
72
82
  {
73
83
  label: 'Add a page template',
74
- cli: 'astryx integration add template dashboard',
84
+ cli: 'astryx integration add template acme-dashboard',
75
85
  },
76
86
  {
77
87
  label: 'Add a block template',
@@ -87,7 +97,7 @@ export const doc = {
87
97
  },
88
98
  {
89
99
  label: 'Add a guide to the package\'s own docs section',
90
- cli: 'astryx integration add doc deploying --parent acme',
100
+ cli: 'astryx integration add doc releasing --parent acme',
91
101
  },
92
102
  {
93
103
  label: 'Add a codemod',
@@ -99,8 +109,8 @@ export const doc = {
99
109
  },
100
110
  {label: 'Add a source theme', cli: 'astryx integration add theme ocean'},
101
111
  {
102
- label: 'Preview',
103
- cli: 'astryx integration add component AcmeWidget --dry-run --json',
112
+ label: 'Fork an existing theme',
113
+ cli: 'astryx integration add theme ocean --from neutral',
104
114
  },
105
115
  ],
106
116
  exitCodes: [
@@ -110,5 +120,5 @@ export const doc = {
110
120
  when: 'the kind, name, options, package, or target files are invalid or conflict',
111
121
  },
112
122
  ],
113
- related: ['integration pack', 'doctor integration validate', 'theme add'],
123
+ related: ['integration verify', 'doctor integration validate', 'theme add'],
114
124
  };
@@ -127,10 +127,7 @@ describe('integration authoring CLI', () => {
127
127
  );
128
128
  expect(added.status).toBe(0);
129
129
 
130
- const checked = await runCli(
131
- ['integration', 'pack', '--check', '--json'],
132
- tmpDir,
133
- );
130
+ const checked = await runCli(['integration', 'verify', '--json'], tmpDir);
134
131
  // Without an exports map, the extensionless import cannot resolve —
135
132
  // pack-check must fail, not false-green.
136
133
  expect(checked.status).not.toBe(0);
@@ -150,13 +147,77 @@ describe('integration authoring CLI', () => {
150
147
  );
151
148
  });
152
149
 
153
- it('requires the explicit --check gate on pack', async () => {
154
- const result = await runCli(['integration', 'pack', '--json'], tmpDir);
155
- expect(result.status).not.toBe(0);
156
- expect(parseEnvelope(result.stdout)).toMatchObject({
150
+ it('keeps `integration pack --check` as a deprecated alias of `integration verify`', async () => {
151
+ // The old spelling runs the same check: the same JSON, the same exit code.
152
+ const verify = await runCli(['integration', 'verify', '--json'], tmpDir);
153
+ const old = await runCli(
154
+ ['integration', 'pack', '--check', '--json'],
155
+ tmpDir,
156
+ );
157
+ expect(old.status).toBe(verify.status);
158
+ const verifyEnvelope = parseEnvelope(verify.stdout);
159
+ const oldEnvelope = parseEnvelope(old.stdout);
160
+ expect(oldEnvelope.type).toBe('integration.pack-check');
161
+ expect(oldEnvelope.type).toBe(verifyEnvelope.type);
162
+ expect(oldEnvelope.data.packable).toBe(verifyEnvelope.data.packable);
163
+ expect(oldEnvelope.data.issues).toEqual(verifyEnvelope.data.issues);
164
+ // The global flag may come first, as agents usually write it.
165
+ const lead = await runCli(
166
+ ['--json', 'integration', 'pack', '--check'],
167
+ tmpDir,
168
+ );
169
+ expect(parseEnvelope(lead.stdout).type).toBe('integration.pack-check');
170
+ // In text, it says to use the new name, on stderr, so stdout is the same.
171
+ const text = await runCli(['integration', 'pack', '--check'], tmpDir);
172
+ const verifyText = await runCli(['integration', 'verify'], tmpDir);
173
+ expect(text.status).toBe(verifyText.status);
174
+ expect(text.stdout).toBe(verifyText.stdout);
175
+ expect(text.stderr).toContain('`integration pack --check` is deprecated');
176
+ expect(text.stderr).toContain('astryx integration verify');
177
+ // Without --check it fails, as it did, and points only at the new name:
178
+ // suggesting `--check` would send people to the deprecated spelling.
179
+ const bare = await runCli(['integration', 'pack'], tmpDir);
180
+ expect(bare.status).not.toBe(0);
181
+ expect(bare.stderr).toContain(
182
+ '`integration pack` is now `integration verify`',
183
+ );
184
+ expect(bare.stderr).toContain('astryx integration verify');
185
+ expect(bare.stderr).toContain('npm pack');
186
+ expect(bare.stderr).not.toContain('--check');
187
+ const bareJson = await runCli(['--json', 'integration', 'pack'], tmpDir);
188
+ expect(parseEnvelope(bareJson.stdout)).toMatchObject({
157
189
  code: 'ERR_INVALID_ARGUMENT',
158
- error: 'Pass --check to verify the integration tarball.',
190
+ error: expect.stringContaining('astryx integration verify'),
191
+ });
192
+ // Help lists it, marked deprecated: nothing is hidden.
193
+ const help = await runCli(['integration', '--help'], tmpDir);
194
+ expect(help.stdout).toMatch(
195
+ /pack .*Deprecated: the old name of `integration verify`/,
196
+ );
197
+ // `verify` itself takes no --check.
198
+ const flag = await runCli(['integration', 'verify', '--check'], tmpDir);
199
+ expect(flag.status).not.toBe(0);
200
+ expect(flag.stderr).toContain("unknown option '--check'");
201
+ // An unknown subcommand with a flag names the subcommand, in text and JSON.
202
+ const unknown = await runCli(['integration', 'bogus', '--check'], tmpDir);
203
+ expect(unknown.status).not.toBe(0);
204
+ expect(unknown.stderr).toContain("unknown subcommand 'integration bogus'");
205
+ expect(unknown.stderr).toMatch(/verify\s+\(available subcommand\)/);
206
+ const unknownJson = await runCli(
207
+ ['integration', 'bogus', '--check', '--json'],
208
+ tmpDir,
209
+ );
210
+ expect(parseEnvelope(unknownJson.stdout)).toMatchObject({
211
+ code: 'ERR_UNKNOWN_SUBCOMMAND',
212
+ error: "unknown subcommand 'integration bogus'",
213
+ suggestions: expect.arrayContaining([
214
+ expect.objectContaining({name: 'verify'}),
215
+ ]),
159
216
  });
217
+ // A flag alone is an unknown option, not an unknown subcommand.
218
+ const flagOnly = await runCli(['integration', '--bogus'], tmpDir);
219
+ expect(flagOnly.status).not.toBe(0);
220
+ expect(flagOnly.stderr).toContain("unknown option '--bogus'");
160
221
  });
161
222
 
162
223
  it('refuses kind-specific options on another kind', async () => {
@@ -6,22 +6,18 @@ export const doc = {
6
6
  name: 'integration pack',
7
7
  displayName: 'astryx integration pack',
8
8
  namespace: 'cli/commands',
9
- summary: 'Prove the packed integration is what consumers receive',
9
+ summary: 'Deprecated: the old name of `integration verify`',
10
10
  description:
11
- 'Runs the package lifecycle, packs with npm, checks every required contribution file against the real tarball, extracts it into a scratch consumer, and compares the local and packed contribution inventories through one shared contract.',
11
+ '`astryx integration pack --check` is the name this check had before {@link command:integration verify}. It still runs the same check, with the same output, JSON, and exit codes, and prints a note that names `integration verify`. It will be removed in a later release.',
12
12
  fn: 'integrationPackCheck',
13
13
  options: [
14
14
  {
15
15
  flag: '--check',
16
- description: 'Run the packed-package verification gate',
16
+ description: 'Run the check. Required, as before.',
17
17
  },
18
18
  ],
19
19
  examples: [
20
- {label: 'Verify before publishing', cli: 'astryx integration pack --check'},
21
- {
22
- label: 'Machine-readable result',
23
- cli: 'astryx integration pack --check --json',
24
- },
20
+ {label: 'The old spelling', cli: 'astryx integration pack --check'},
25
21
  ],
26
22
  exitCodes: [
27
23
  {code: 0, when: 'the packed package exposes the same valid contributions'},
@@ -30,5 +26,5 @@ export const doc = {
30
26
  when: '--check is omitted or the tarball is incomplete or invalid',
31
27
  },
32
28
  ],
33
- related: ['integration add', 'doctor integration validate'],
29
+ related: ['integration verify'],
34
30
  };
@@ -214,7 +214,7 @@ export const oceanTheme = defineTheme({
214
214
  ]);
215
215
 
216
216
  const checked = await runCli(
217
- ['integration', 'pack', '--check', '--json'],
217
+ ['integration', 'verify', '--json'],
218
218
  providerDir,
219
219
  );
220
220
  expect(checked.status, checked.stderr).toBe(0);
@@ -0,0 +1,22 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('@astryxdesign/cli/authoring').CommandDoc} */
4
+ export const doc = {
5
+ type: 'command',
6
+ name: 'integration verify',
7
+ displayName: 'astryx integration verify',
8
+ namespace: 'cli/commands',
9
+ summary: 'Check the package the way npm will publish it, before you publish',
10
+ description:
11
+ 'Packs the package with npm, unpacks the tarball into a temporary app without installing its dependencies, and checks that the app sees the same components, templates, themes, docs, and codemods as the package, that every public import resolves, and that the package declares a CLI new enough to read it. It publishes nothing and leaves no tarball behind. It runs the package\'s own pack lifecycle scripts, as `npm pack` does.',
12
+ fn: 'integrationPackCheck',
13
+ examples: [
14
+ {label: 'Check before publishing', cli: 'astryx integration verify'},
15
+ {label: 'Machine-readable result', cli: 'astryx integration verify --json'},
16
+ ],
17
+ exitCodes: [
18
+ {code: 0, when: 'the packed package exposes the same valid contributions'},
19
+ {code: 1, when: 'the tarball is incomplete or invalid'},
20
+ ],
21
+ related: ['integration add', 'doctor integration validate'],
22
+ };
@@ -8,16 +8,16 @@ export const doc = {
8
8
  namespace: 'cli/commands',
9
9
  summary: 'Author and verify an Astryx integration package',
10
10
  description:
11
- 'Add contributions that are valid on arrival, then prove the packed package exposes the same contributions a consumer will receive.',
12
- subcommands: ['add', 'pack'],
11
+ 'Add contributions to your package, then check the packed package the way an app receives it. The guides start at {@link namespace:integrations}.',
12
+ subcommands: ['add', 'verify', 'pack'],
13
13
  examples: [
14
14
  {
15
15
  label: 'Add a component',
16
16
  cli: 'astryx integration add component AcmeWidget',
17
17
  },
18
18
  {
19
- label: 'Check the package tarball',
20
- cli: 'astryx integration pack --check',
19
+ label: 'Check the package before publishing',
20
+ cli: 'astryx integration verify',
21
21
  },
22
22
  ],
23
23
  exitCodes: [