@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2

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 (509) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +175 -154
  3. package/api/build/_adapter.d.mts +8 -0
  4. package/api/build/_adapter.mjs +12 -1
  5. package/api/build/build.doc.mjs +4 -0
  6. package/api/build/help/help.mjs +1 -1
  7. package/api/build/kit/kit.mjs +3 -11
  8. package/api/component/_adapter.d.mts +72 -1
  9. package/api/component/_adapter.mjs +212 -18
  10. package/api/component/component.doc.mjs +6 -1
  11. package/api/component/component.mjs +82 -15
  12. package/api/component/component.test.mjs +80 -0
  13. package/api/component/doc-links.test.mjs +386 -0
  14. package/api/component/integration-export-name.test.mjs +644 -0
  15. package/api/component/list/list.mjs +42 -4
  16. package/api/discover/_adapter.d.mts +132 -12
  17. package/api/discover/_adapter.mjs +488 -27
  18. package/api/discover/_adapter.test.mjs +599 -17
  19. package/api/discover/_catalog-view.d.mts +16 -5
  20. package/api/discover/_catalog-view.mjs +32 -8
  21. package/api/discover/detail/doc/doc.mjs +9 -1
  22. package/api/discover/discover.d.mts +11 -0
  23. package/api/discover/discover.doc.mjs +9 -7
  24. package/api/discover/discover.mjs +121 -19
  25. package/api/discover/discover.type.d.mts +20 -7
  26. package/api/discover/discover.type.mjs +17 -7
  27. package/api/discover/list/list.d.mts +4 -3
  28. package/api/discover/list/list.mjs +17 -10
  29. package/api/docs/_adapter.d.mts +74 -0
  30. package/api/docs/_adapter.mjs +553 -16
  31. package/api/docs/docs.doc.mjs +2 -1
  32. package/api/docs/docs.mjs +2 -1
  33. package/api/docs/docs.test.mjs +5 -2
  34. package/api/docs/integration-tree.test.mjs +22 -0
  35. package/api/docs/integrationDocs.test.mjs +124 -0
  36. package/api/docs/list/list.mjs +12 -2
  37. package/api/docs/reference-blocks.test.mjs +1 -3
  38. package/api/doctor/_adapter.d.mts +108 -0
  39. package/api/doctor/_adapter.mjs +223 -4
  40. package/api/doctor/doctor.d.mts +199 -0
  41. package/api/doctor/doctor.doc.mjs +3 -2
  42. package/api/doctor/doctor.mjs +530 -34
  43. package/api/doctor/doctor.test.mjs +180 -14
  44. package/api/doctor/release-checks.test.mjs +156 -0
  45. package/api/doctor/theme-checks.mjs +17 -4
  46. package/api/doctor/theme-checks.test.mjs +223 -7
  47. package/api/error.d.mts +10 -0
  48. package/api/error.mjs +25 -0
  49. package/api/gap-report/gap-report.d.mts +3 -0
  50. package/api/gap-report/gap-report.doc.mjs +11 -3
  51. package/api/gap-report/gap-report.mjs +219 -52
  52. package/api/gap-report/gap-report.test.mjs +233 -0
  53. package/api/gap-report/gap-report.type.d.mts +41 -0
  54. package/api/gap-report/gap-report.type.mjs +18 -0
  55. package/api/hook/_adapter.mjs +3 -11
  56. package/api/hook/hook.doc.mjs +4 -0
  57. package/api/hook/list/list.d.mts +1 -1
  58. package/api/index.d.mts +2 -0
  59. package/api/index.mjs +2 -0
  60. package/api/init/_adapter.d.mts +22 -0
  61. package/api/init/_adapter.mjs +59 -0
  62. package/api/init/init.d.mts +7 -5
  63. package/api/init/init.doc.mjs +28 -7
  64. package/api/init/init.mjs +28 -4
  65. package/api/init/init.type.d.mts +48 -3
  66. package/api/init/init.type.mjs +37 -3
  67. package/api/init/run/run.d.mts +1 -1
  68. package/api/init/run/run.mjs +17 -6
  69. package/api/init/user/user.d.mts +14 -0
  70. package/api/init/user/user.mjs +87 -0
  71. package/api/init/user/user.test.mjs +232 -0
  72. package/api/integration/_adapter.d.mts +45 -0
  73. package/api/integration/_adapter.mjs +112 -0
  74. package/api/integration/add-contribution.component-names.test.mjs +66 -0
  75. package/api/integration/add-contribution.mjs +8 -4
  76. package/api/integration/add-contribution.test.mjs +4 -2
  77. package/api/integration/authoring-checks.mjs +110 -6
  78. package/api/integration/authoring-checks.test.mjs +808 -0
  79. package/api/integration/authoring-checks.type.d.mts +143 -0
  80. package/api/integration/authoring-checks.type.mjs +74 -2
  81. package/api/integration/check/check.d.mts +96 -0
  82. package/api/integration/check/check.mjs +357 -0
  83. package/api/integration/check/check.test.mjs +489 -0
  84. package/api/integration/integration-check.type.d.mts +118 -0
  85. package/api/integration/integration-check.type.mjs +84 -0
  86. package/api/integration/integrationCheck.doc.d.mts +10 -0
  87. package/api/integration/integrationCheck.doc.mjs +73 -0
  88. package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
  89. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  90. package/api/integration/pack-check.mjs +364 -120
  91. package/api/integration/pack-check.test.mjs +730 -10
  92. package/api/integration/validate-integration-fixes.test.mjs +67 -0
  93. package/api/integration/validate-integration.d.mts +8 -0
  94. package/api/integration/validate-integration.mjs +63 -9
  95. package/api/integration/validate-integration.test.mjs +88 -8
  96. package/api/integration/validate-integration.type.d.mts +16 -0
  97. package/api/integration/validate-integration.type.mjs +14 -1
  98. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  99. package/api/integration/validateIntegration.doc.mjs +19 -3
  100. package/api/search/_adapter.d.mts +11 -0
  101. package/api/search/_adapter.mjs +25 -0
  102. package/api/search/search.d.mts +82 -13
  103. package/api/search/search.doc.mjs +8 -3
  104. package/api/search/search.domain-priority.test.mjs +108 -18
  105. package/api/search/search.integration-check.test.mjs +24 -0
  106. package/api/search/search.mjs +645 -64
  107. package/api/search/search.test.mjs +179 -1
  108. package/api/search/search.type.d.mts +14 -1
  109. package/api/search/search.type.mjs +6 -1
  110. package/api/swizzle/_adapter.mjs +2 -2
  111. package/api/swizzle/copy/copy.mjs +29 -15
  112. package/api/template/template-integration.test.mjs +1 -1
  113. package/api/template/template.test.mjs +120 -3
  114. package/api/theme/_adapter.d.mts +16 -0
  115. package/api/theme/_adapter.mjs +32 -5
  116. package/api/theme/build/build.d.mts +2 -1
  117. package/api/theme/build/build.family.test.mjs +64 -0
  118. package/api/theme/build/build.mjs +250 -38
  119. package/api/theme/build/build.packed-old-core.test.mjs +20 -3
  120. package/api/theme/build/font-warning.mjs +5 -3
  121. package/api/theme/build/font-warning.test.mjs +2 -1
  122. package/api/theme/remove/remove.test.mjs +2 -2
  123. package/api/theme/targets/targets.mjs +3 -10
  124. package/api/theme/themeBuild.doc.mjs +4 -4
  125. package/api/theme/themeTargets.doc.mjs +4 -0
  126. package/api/theme/use/use.test.mjs +1 -1
  127. package/api/upgrade/_adapter.d.mts +40 -2
  128. package/api/upgrade/_adapter.mjs +118 -5
  129. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  130. package/api/upgrade/run/run.mjs +35 -2
  131. package/api/upgrade/status/status.d.mts +21 -5
  132. package/api/upgrade/status/status.mjs +45 -8
  133. package/api/upgrade/upgrade.doc.mjs +6 -3
  134. package/api/upgrade/upgrade.mjs +5 -1
  135. package/api/upgrade/upgrade.type.d.mts +23 -0
  136. package/api/upgrade/upgrade.type.mjs +16 -1
  137. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  138. package/assets/codemods/registry.mjs +1 -0
  139. package/assets/codemods/runner.mjs +7 -1
  140. package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
  141. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  142. package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
  143. package/assets/discover/official-packages.json +367 -0
  144. package/assets/docs/README.md +10 -0
  145. package/assets/docs/author-a-theme.doc.mjs +3 -3
  146. package/assets/docs/browser-support.doc.mjs +1 -1
  147. package/assets/docs/getting-started.doc.mjs +26 -6
  148. package/assets/docs/styling-overview.doc.mjs +1 -1
  149. package/assets/docs/theme.doc.dense.mjs +1 -1
  150. package/assets/docs/theme.doc.mjs +2 -2
  151. package/assets/docs/theme.doc.zh.mjs +1 -1
  152. package/assets/docs/tree/add-a-component.doc.mjs +22 -2
  153. package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
  154. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  155. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  156. package/assets/docs/tree/block-template.doc.mjs +8 -20
  157. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  158. package/assets/docs/tree/building-blocks.doc.mjs +4 -0
  159. package/assets/docs/tree/check-the-props.doc.mjs +201 -0
  160. package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
  161. package/assets/docs/tree/checks.doc.mjs +32 -24
  162. package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
  163. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  164. package/assets/docs/tree/cli.doc.mjs +6 -0
  165. package/assets/docs/tree/codemods.doc.mjs +17 -7
  166. package/assets/docs/tree/commands.doc.mjs +7 -1
  167. package/assets/docs/tree/component-family.doc.mjs +8 -6
  168. package/assets/docs/tree/component-imports.doc.mjs +21 -3
  169. package/assets/docs/tree/components.doc.mjs +7 -1
  170. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  171. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  172. package/assets/docs/tree/configuration.doc.mjs +7 -3
  173. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  174. package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
  175. package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
  176. package/assets/docs/tree/docs.doc.mjs +9 -3
  177. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  178. package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
  179. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  180. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  181. package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
  182. package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
  183. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  184. package/assets/docs/tree/global.doc.mjs +131 -0
  185. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  186. package/assets/docs/tree/install-once.doc.mjs +105 -0
  187. package/assets/docs/tree/integrations.doc.mjs +13 -1
  188. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  189. package/assets/docs/tree/layout.doc.mjs +6 -6
  190. package/assets/docs/tree/links.doc.mjs +7 -6
  191. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  192. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  193. package/assets/docs/tree/migration.doc.mjs +0 -1
  194. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  195. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  196. package/assets/docs/tree/page-template.doc.mjs +4 -8
  197. package/assets/docs/tree/problems.doc.mjs +205 -0
  198. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  199. package/assets/docs/tree/publishing.doc.mjs +6 -6
  200. package/assets/docs/tree/quick-start.doc.mjs +53 -27
  201. package/assets/docs/tree/reference.doc.mjs +192 -0
  202. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  203. package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
  204. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  205. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  206. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  207. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  208. package/assets/docs/tree/single-component.doc.mjs +15 -6
  209. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  210. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  211. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  212. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  213. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  214. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  215. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  216. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  217. package/assets/docs/tree/templates.doc.mjs +7 -1
  218. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  219. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  220. package/assets/docs/tree/themes.doc.mjs +4 -0
  221. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  222. package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
  223. package/assets/docs/tree/type-scale.doc.mjs +3 -3
  224. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  225. package/assets/docs/tree/updates.doc.mjs +92 -0
  226. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  227. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
  228. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  229. package/assets/docs/tree/versioning.doc.mjs +10 -9
  230. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  231. package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
  232. package/assets/docs/use-a-theme.doc.mjs +2 -2
  233. package/assets/docs/working-with-ai.doc.mjs +66 -13
  234. package/assets/theme.template.ts +1 -1
  235. package/authoring/codemod/codemod.doc.mjs +7 -3
  236. package/authoring/config/config.doc.mjs +9 -6
  237. package/authoring/config/type.ts +4 -2
  238. package/authoring/debug/parse.d.mts +5 -5
  239. package/authoring/discover/discover.doc.mjs +7 -1
  240. package/authoring/doctypes/_schema.d.mts +8 -3
  241. package/authoring/doctypes/_schema.mjs +1 -0
  242. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  243. package/authoring/doctypes/command/command.doc.mjs +20 -12
  244. package/authoring/doctypes/command/type.ts +14 -0
  245. package/authoring/doctypes/component/component.doc.mjs +30 -27
  246. package/authoring/doctypes/component/type.ts +21 -8
  247. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  248. package/authoring/doctypes/function/function.doc.mjs +9 -8
  249. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  250. package/authoring/doctypes/hook/type.ts +4 -0
  251. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  252. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  253. package/authoring/doctypes/schema/schema.doc.mjs +9 -9
  254. package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
  255. package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
  256. package/authoring/doctypes/template/parse.d.mts +6 -2
  257. package/authoring/doctypes/template/parse.mjs +3 -1
  258. package/authoring/doctypes/template/template.doc.mjs +3 -3
  259. package/authoring/doctypes/template/type.ts +22 -0
  260. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  261. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  262. package/authoring/identity/identity.doc.mjs +3 -3
  263. package/authoring/index.d.ts +2 -0
  264. package/authoring/integration/integration.doc.mjs +30 -6
  265. package/authoring/integration/parse.test.mjs +21 -0
  266. package/authoring/integration/schema.d.mts +16 -3
  267. package/authoring/integration/schema.mjs +34 -2
  268. package/authoring/integration/type.ts +12 -0
  269. package/clients/cli/bin/astryx.mjs +20 -3
  270. package/clients/cli/cli-command.test.mjs +166 -0
  271. package/clients/cli/commands/blog.doc.mjs +1 -0
  272. package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
  273. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  274. package/clients/cli/commands/build-theme.mjs +26 -13
  275. package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
  276. package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
  277. package/clients/cli/commands/build.doc.mjs +1 -0
  278. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  279. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  280. package/clients/cli/commands/component.doc.mjs +1 -0
  281. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  282. package/clients/cli/commands/discover.doc.mjs +9 -1
  283. package/clients/cli/commands/discover.mjs +144 -93
  284. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  285. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  286. package/clients/cli/commands/docs.doc.mjs +1 -0
  287. package/clients/cli/commands/docs.mjs +49 -19
  288. package/clients/cli/commands/docs.test.mjs +2 -2
  289. package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
  290. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  291. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  292. package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
  293. package/clients/cli/commands/doctor-integration.test.mjs +888 -3
  294. package/clients/cli/commands/doctor.doc.mjs +12 -2
  295. package/clients/cli/commands/doctor.mjs +292 -7
  296. package/clients/cli/commands/doctor.test.mjs +10 -4
  297. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  298. package/clients/cli/commands/gap-report.mjs +24 -2
  299. package/clients/cli/commands/gap-report.test.mjs +79 -0
  300. package/clients/cli/commands/hook.doc.mjs +1 -0
  301. package/clients/cli/commands/init.behavior.test.mjs +5 -0
  302. package/clients/cli/commands/init.doc.mjs +29 -3
  303. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  304. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  305. package/clients/cli/commands/integration-check.doc.mjs +93 -0
  306. package/clients/cli/commands/integration-check.test.mjs +441 -0
  307. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  308. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  309. package/clients/cli/commands/integration.doc.mjs +6 -2
  310. package/clients/cli/commands/integration.mjs +119 -7
  311. package/clients/cli/commands/json-contract.test.mjs +11 -2
  312. package/clients/cli/commands/manifest.doc.mjs +1 -0
  313. package/clients/cli/commands/outside-project.test.mjs +774 -0
  314. package/clients/cli/commands/search.doc.mjs +1 -0
  315. package/clients/cli/commands/search.mjs +16 -11
  316. package/clients/cli/commands/search.test.mjs +429 -296
  317. package/clients/cli/commands/setup-nudge.test.mjs +102 -2
  318. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  319. package/clients/cli/commands/swizzle.mjs +5 -3
  320. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  321. package/clients/cli/commands/template.doc.mjs +1 -0
  322. package/clients/cli/commands/text-json-parity.test.mjs +5 -0
  323. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  324. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  325. package/clients/cli/commands/theme-build.doc.mjs +3 -2
  326. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  327. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  328. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  329. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  330. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  331. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  332. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  333. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  334. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  335. package/clients/cli/commands/upgrade.doc.mjs +22 -1
  336. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  337. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  338. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  339. package/clients/cli/index.mjs +112 -16
  340. package/clients/cli/lib/cli-error.mjs +4 -1
  341. package/clients/cli/lib/component-format.test.mjs +1 -1
  342. package/clients/cli/lib/define-command.mjs +2 -2
  343. package/clients/cli/lib/json-shim.mjs +3 -1
  344. package/clients/cli/lib/manifest.d.ts +9 -0
  345. package/clients/cli/lib/manifest.mjs +17 -1
  346. package/clients/cli/lib/manifest.test.mjs +25 -0
  347. package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
  348. package/foundation/agent-docs/agent-doc-state.mjs +66 -6
  349. package/foundation/agent-docs/agent-docs.d.mts +4 -3
  350. package/foundation/agent-docs/agent-docs.mjs +11 -9
  351. package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
  352. package/foundation/agent-docs/computer-agent-text.mjs +623 -0
  353. package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
  354. package/foundation/config/project.d.mts +35 -3
  355. package/foundation/config/project.mjs +226 -7
  356. package/foundation/config/project.test.mjs +66 -0
  357. package/foundation/config/theme-state.mjs +5 -4
  358. package/foundation/discovery/authoring-self-docs.mjs +2 -1
  359. package/foundation/discovery/cli-self-docs.mjs +20 -3
  360. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  361. package/foundation/discovery/component-discovery.d.mts +190 -10
  362. package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
  363. package/foundation/discovery/component-discovery.mjs +864 -56
  364. package/foundation/discovery/component-discovery.test.mjs +96 -0
  365. package/foundation/discovery/component-replacement.mjs +20 -1
  366. package/foundation/discovery/component-replacement.test.mjs +40 -0
  367. package/foundation/discovery/copied-passages.d.mts +216 -0
  368. package/foundation/discovery/copied-passages.mjs +720 -0
  369. package/foundation/discovery/copied-passages.test.mjs +124 -0
  370. package/foundation/discovery/doc-consistency.d.mts +34 -0
  371. package/foundation/discovery/doc-consistency.mjs +513 -0
  372. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  373. package/foundation/discovery/doc-fluff.d.mts +112 -0
  374. package/foundation/discovery/doc-fluff.mjs +328 -0
  375. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  376. package/foundation/discovery/doc-types.d.mts +157 -0
  377. package/foundation/discovery/doc-types.mjs +1231 -0
  378. package/foundation/discovery/doc-types.test.mjs +744 -0
  379. package/foundation/discovery/docs-discovery.d.mts +88 -0
  380. package/foundation/discovery/docs-discovery.mjs +83 -2
  381. package/foundation/discovery/integration-doc-files.d.mts +22 -0
  382. package/foundation/discovery/integration-doc-files.mjs +231 -0
  383. package/foundation/discovery/integration-doc-files.test.mjs +246 -0
  384. package/foundation/discovery/module-exports.d.mts +27 -0
  385. package/foundation/discovery/module-exports.mjs +356 -31
  386. package/foundation/discovery/module-exports.test.mjs +172 -0
  387. package/foundation/discovery/package-tsconfig.d.mts +14 -0
  388. package/foundation/discovery/package-tsconfig.mjs +228 -0
  389. package/foundation/discovery/package-tsconfig.test.mjs +210 -0
  390. package/foundation/discovery/project-typescript.d.mts +32 -0
  391. package/foundation/discovery/project-typescript.mjs +89 -0
  392. package/foundation/discovery/prop-drift.d.mts +297 -0
  393. package/foundation/discovery/prop-drift.mjs +2428 -0
  394. package/foundation/discovery/prop-drift.test.mjs +2337 -0
  395. package/foundation/discovery/runner-allowlist.d.mts +40 -0
  396. package/foundation/discovery/runner-allowlist.mjs +53 -0
  397. package/foundation/discovery/stray-pointers.d.mts +52 -0
  398. package/foundation/discovery/stray-pointers.mjs +293 -0
  399. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  400. package/foundation/discovery/template-adapter.mjs +74 -5
  401. package/foundation/discovery/template-needs.mjs +5 -2
  402. package/foundation/discovery/theme-imports.mjs +8 -4
  403. package/foundation/discovery/theme-imports.test.mjs +1 -1
  404. package/foundation/discovery/type-match.d.mts +53 -0
  405. package/foundation/discovery/type-match.mjs +660 -0
  406. package/foundation/discovery/type-match.test.mjs +169 -0
  407. package/foundation/discovery/type-text.d.mts +68 -0
  408. package/foundation/discovery/type-text.mjs +658 -0
  409. package/foundation/discovery/type-text.test.mjs +196 -0
  410. package/foundation/discovery/unresolved-references.d.mts +62 -0
  411. package/foundation/discovery/unresolved-references.mjs +790 -0
  412. package/foundation/discovery/unresolved-references.test.mjs +567 -0
  413. package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
  414. package/foundation/doc-compiler/inputs.mjs +27 -1
  415. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  416. package/foundation/doc-compiler/links.d.mts +41 -5
  417. package/foundation/doc-compiler/links.mjs +167 -28
  418. package/foundation/doc-compiler/links.test.mjs +97 -4
  419. package/foundation/doc-compiler/read.d.mts +1 -1
  420. package/foundation/doc-compiler/tree.mjs +30 -1
  421. package/foundation/doc-compiler/tree.test.mjs +8 -1
  422. package/foundation/env/cli-command.d.mts +83 -0
  423. package/foundation/env/cli-command.mjs +152 -0
  424. package/foundation/env/cli-command.test.mjs +129 -0
  425. package/foundation/env/node-version.test.mjs +15 -3
  426. package/foundation/env/package-manager.d.mts +93 -9
  427. package/foundation/env/package-manager.global.test.mjs +66 -0
  428. package/foundation/env/package-manager.mjs +184 -13
  429. package/foundation/env/package-manager.test.mjs +341 -15
  430. package/foundation/env/project-scope.d.mts +9 -0
  431. package/foundation/env/project-scope.mjs +33 -0
  432. package/foundation/env/search-path.d.mts +42 -0
  433. package/foundation/env/search-path.mjs +205 -0
  434. package/foundation/env/search-path.test.mjs +122 -0
  435. package/foundation/env/user-dirs.d.mts +39 -0
  436. package/foundation/env/user-dirs.mjs +93 -0
  437. package/foundation/env/user-dirs.test.mjs +72 -0
  438. package/foundation/env/user-settings.d.mts +46 -0
  439. package/foundation/env/user-settings.mjs +106 -0
  440. package/foundation/env/user-settings.test.mjs +64 -0
  441. package/foundation/fs/file-protection.mjs +15 -1
  442. package/foundation/fs/module-loader.d.mts +2 -1
  443. package/foundation/fs/module-loader.mjs +60 -4
  444. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  445. package/foundation/fs/module-loader.test.mjs +194 -0
  446. package/foundation/fs/path-compare.d.mts +33 -0
  447. package/foundation/fs/path-compare.mjs +73 -0
  448. package/foundation/fs/paths.d.mts +57 -1
  449. package/foundation/fs/paths.mjs +131 -3
  450. package/foundation/fs/paths.test.mjs +10 -1
  451. package/foundation/integrations/computer-integrations.d.mts +78 -0
  452. package/foundation/integrations/computer-integrations.mjs +316 -0
  453. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  454. package/foundation/integrations/contribution-inventory.d.mts +11 -0
  455. package/foundation/integrations/contribution-inventory.mjs +56 -3
  456. package/foundation/integrations/integration-warnings.mjs +3 -2
  457. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  458. package/foundation/integrations/integrations.d.mts +25 -1
  459. package/foundation/integrations/integrations.mjs +46 -3
  460. package/foundation/integrations/issue.ts +6 -0
  461. package/foundation/integrations/validate-contributions.d.mts +2 -0
  462. package/foundation/integrations/validate-contributions.mjs +41 -1
  463. package/foundation/release/agent-text-worker.d.mts +4 -0
  464. package/foundation/release/agent-text-worker.mjs +52 -0
  465. package/foundation/release/cache.d.mts +310 -0
  466. package/foundation/release/cache.mjs +1216 -0
  467. package/foundation/release/cache.test.mjs +920 -0
  468. package/foundation/release/choose.d.mts +207 -0
  469. package/foundation/release/choose.mjs +677 -0
  470. package/foundation/release/choose.test.mjs +427 -0
  471. package/foundation/release/core-worker.d.mts +4 -0
  472. package/foundation/release/core-worker.mjs +38 -0
  473. package/foundation/release/global-state.d.mts +259 -0
  474. package/foundation/release/global-state.mjs +472 -0
  475. package/foundation/release/global-state.test.mjs +381 -0
  476. package/foundation/release/handoff.d.mts +60 -0
  477. package/foundation/release/handoff.e2e.test.mjs +278 -0
  478. package/foundation/release/handoff.mjs +357 -0
  479. package/foundation/release/lock-lease.d.mts +23 -0
  480. package/foundation/release/lock-lease.mjs +80 -0
  481. package/foundation/release/notices.d.mts +253 -0
  482. package/foundation/release/notices.mjs +596 -0
  483. package/foundation/release/notices.test.mjs +565 -0
  484. package/foundation/release/npm-guard.d.mts +4 -0
  485. package/foundation/release/npm-guard.mjs +126 -0
  486. package/foundation/release/project.d.mts +141 -0
  487. package/foundation/release/project.mjs +466 -0
  488. package/foundation/release/project.test.mjs +288 -0
  489. package/foundation/release/refresh-worker.d.mts +4 -0
  490. package/foundation/release/refresh-worker.mjs +27 -0
  491. package/foundation/release/run-context.d.mts +47 -0
  492. package/foundation/release/run-context.mjs +149 -0
  493. package/foundation/release/update-notice-env.d.mts +28 -0
  494. package/foundation/release/update-notice-env.mjs +39 -0
  495. package/foundation/response/base.d.ts +26 -3
  496. package/foundation/response/error-codes.d.mts +3 -1
  497. package/foundation/response/error-codes.doc.mjs +12 -0
  498. package/foundation/response/error-codes.mjs +17 -0
  499. package/foundation/response/error-codes.test.mjs +2 -0
  500. package/foundation/response/json-contract.test.mjs +7 -2
  501. package/foundation/response/json.mjs +4 -1
  502. package/foundation/response/response-types.doc.mjs +22 -11
  503. package/foundation/response/response-types.doc.test.mjs +46 -0
  504. package/foundation/response/response.doc.mjs +3 -3
  505. package/foundation/xle/browser-imports.test.mjs +74 -0
  506. package/foundation/xle/registry.mjs +4 -0
  507. package/foundation/xle/registry.test.mjs +28 -0
  508. package/package.json +11 -11
  509. package/scripts/postinstall.mjs +24 -5
@@ -16,9 +16,24 @@ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
16
16
  import * as fs from 'node:fs';
17
17
  import * as path from 'node:path';
18
18
  import * as os from 'node:os';
19
- import {isAstryxInitialized} from '../../../foundation/agent-docs/agent-docs.mjs';
19
+ import {fileURLToPath} from 'node:url';
20
+ import {
21
+ isAstryxInitialized,
22
+ isAstryxPromptInReach,
23
+ } from '../../../foundation/agent-docs/agent-docs.mjs';
20
24
  import {runCli} from '../../../test-utils/run-cli.mjs';
21
25
 
26
+ /** This source checkout: the tests run the CLI from it. */
27
+ const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../..');
28
+
29
+ /** Is `dir` inside a git repository? The temp folder normally is not. */
30
+ function insideRepository(dir) {
31
+ for (let d = path.resolve(dir); ; d = path.dirname(d)) {
32
+ if (fs.existsSync(path.join(d, '.git'))) return true;
33
+ if (path.dirname(d) === d) return false;
34
+ }
35
+ }
36
+
22
37
  const MARKER = '<!-- ASTRYX:START -->';
23
38
  const NUDGE = /finish setup and install the Astryx agent prompt/;
24
39
 
@@ -61,8 +76,44 @@ describe('isAstryxInitialized — centralized setup check (one place)', () => {
61
76
  });
62
77
  });
63
78
 
79
+ // Agents read the agent docs between the repository root and the folder they
80
+ // work in, so a monorepo initialized at its root is set up in every package.
81
+ describe('isAstryxPromptInReach — up to the repository root', () => {
82
+ it('finds init\'s block at the repository root from a workspace package', () => {
83
+ fs.mkdirSync(path.join(tmp, '.git'));
84
+ write('AGENTS.md', MARKER);
85
+ write('packages/app/package.json', '{"name":"app"}');
86
+ expect(isAstryxPromptInReach(path.join(tmp, 'packages/app'))).toBe(true);
87
+ });
88
+
89
+ it('treats a worktree .git file as the repository root', () => {
90
+ write('.git', 'gitdir: /elsewhere\n');
91
+ write('CLAUDE.md', MARKER);
92
+ write('packages/app/package.json', '{"name":"app"}');
93
+ expect(isAstryxPromptInReach(path.join(tmp, 'packages/app'))).toBe(true);
94
+ });
95
+
96
+ it('does not look above the repository root', () => {
97
+ write('AGENTS.md', MARKER);
98
+ fs.mkdirSync(path.join(tmp, 'repo/.git'), {recursive: true});
99
+ write('repo/pkg/package.json', '{"name":"pkg"}');
100
+ expect(isAstryxPromptInReach(path.join(tmp, 'repo/pkg'))).toBe(false);
101
+ });
102
+
103
+ it.skipIf(insideRepository(os.tmpdir()))(
104
+ 'checks only the folder itself outside a repository',
105
+ () => {
106
+ write('AGENTS.md', MARKER);
107
+ write('pkg/package.json', '{"name":"pkg"}');
108
+ expect(isAstryxPromptInReach(tmp)).toBe(true);
109
+ expect(isAstryxPromptInReach(path.join(tmp, 'pkg'))).toBe(false);
110
+ },
111
+ );
112
+ });
113
+
64
114
  describe('enforcement layer 3 — per-command setup nudge', () => {
65
- const asProject = () => write('package.json', '{"name":"t"}');
115
+ const asProject = () =>
116
+ write('package.json', '{"name":"t","dependencies":{"@astryxdesign/core":"*"}}');
66
117
 
67
118
  it('nudges on stderr after a command when not set up', async () => {
68
119
  asProject();
@@ -70,6 +121,22 @@ describe('enforcement layer 3 — per-command setup nudge', () => {
70
121
  expect(r.stderr).toMatch(NUDGE);
71
122
  });
72
123
 
124
+ it("in a project with only Core of another release, names adding the CLI at Core's version first, as the daily hint does", async () => {
125
+ write(
126
+ 'package.json',
127
+ '{"name":"t","dependencies":{"@astryxdesign/core":"0.0.1"}}',
128
+ );
129
+ write(
130
+ 'node_modules/@astryxdesign/core/package.json',
131
+ '{"name":"@astryxdesign/core","version":"0.0.1"}',
132
+ );
133
+ write('package-lock.json', '{}');
134
+ const r = await runCli(['docs', 'tokens'], tmp);
135
+ expect(r.stderr).toContain(
136
+ 'Next step: run `npm install @astryxdesign/cli@0.0.1`, then `npx astryx init` to finish setup and install the Astryx agent prompt.',
137
+ );
138
+ });
139
+
73
140
  it('is suppressed in --json (machine mode stays clean), stdout valid JSON', async () => {
74
141
  asProject();
75
142
  const r = await runCli(['--json', 'docs', 'tokens'], tmp);
@@ -89,6 +156,11 @@ describe('enforcement layer 3 — per-command setup nudge', () => {
89
156
  expect((await runCli(['docs', 'tokens'], tmp)).stderr).not.toMatch(NUDGE);
90
157
  });
91
158
 
159
+ it('is quiet outside a project (a package.json that declares no Astryx package)', async () => {
160
+ write('package.json', '{"name":"t"}');
161
+ expect((await runCli(['docs', 'tokens'], tmp)).stderr).not.toMatch(NUDGE);
162
+ });
163
+
92
164
  it('is quiet in an integration package, which is not an app', async () => {
93
165
  asProject();
94
166
  write('astryx.integration.mjs', 'export default {};\n');
@@ -99,4 +171,32 @@ describe('enforcement layer 3 — per-command setup nudge', () => {
99
171
  asProject();
100
172
  expect((await runCli(['init'], tmp)).stderr).not.toMatch(NUDGE);
101
173
  });
174
+
175
+ it('is quiet in a workspace package when init\'s block is at the repository root', async () => {
176
+ fs.mkdirSync(path.join(tmp, '.git'));
177
+ write('AGENTS.md', MARKER);
178
+ write('packages/app/package.json', '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}');
179
+ const r = await runCli(['docs', 'tokens'], path.join(tmp, 'packages/app'));
180
+ expect(r.stderr).not.toMatch(NUDGE);
181
+ });
182
+
183
+ it('still nudges in a workspace package with no block up to the repository root', async () => {
184
+ fs.mkdirSync(path.join(tmp, '.git'));
185
+ write('AGENTS.md', 'project notes, no astryx block');
186
+ write('packages/app/package.json', '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}');
187
+ const r = await runCli(['docs', 'tokens'], path.join(tmp, 'packages/app'));
188
+ expect(r.stderr).toMatch(NUDGE);
189
+ });
190
+
191
+ // The tests run the CLI from this checkout, so a project inside it is the
192
+ // contributor flow. The same project in the temp folder nudges (above).
193
+ it('is quiet inside the source checkout the CLI runs from', async () => {
194
+ const inside = fs.mkdtempSync(path.join(REPO, '.astryx-setup-nudge-'));
195
+ try {
196
+ fs.writeFileSync(path.join(inside, 'package.json'), '{"name":"t","dependencies":{"@astryxdesign/core":"*"}}');
197
+ expect((await runCli(['docs', 'tokens'], inside)).stderr).not.toMatch(NUDGE);
198
+ } finally {
199
+ fs.rmSync(inside, {recursive: true, force: true});
200
+ }
201
+ });
102
202
  });
@@ -57,6 +57,7 @@ export const doc = {
57
57
  cli: 'astryx swizzle SideNav --package @astryxdesign/core',
58
58
  },
59
59
  ],
60
+ outsideProject: 'refuse',
60
61
  exitCodes: [
61
62
  {code: 0, when: 'success'},
62
63
  {
@@ -65,4 +66,10 @@ export const doc = {
65
66
  },
66
67
  ],
67
68
  related: ['component', 'discover', 'upgrade'],
69
+ notes: [
70
+ {
71
+ type: 'prose',
72
+ text: 'In global mode: outside a project, swizzle writes nothing and stops with `ERR_CORE_NOT_FOUND`: "Could not find @astryxdesign/core package. Make sure you are inside the design system monorepo or have @astryxdesign/core installed." In a project, the project\'s version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:problems}.',
73
+ },
74
+ ],
68
75
  };
@@ -91,14 +91,16 @@ export function registerSwizzle(program) {
91
91
  ),
92
92
  ];
93
93
 
94
- // StyleX build requirement — swizzled StyleX source renders unstyled with
95
- // no error unless the consumer's build runs a StyleX compiler.
94
+ // StyleX build requirement — swizzled StyleX source throws on import
95
+ // ("Unexpected 'stylex.create' call at runtime") unless the consumer's
96
+ // build runs a StyleX compiler, so the page does not render at all.
96
97
  if (usesStyleX) {
97
98
  out.push(
98
99
  text(
99
100
  [
100
101
  `${WARN} These components use StyleX and require a StyleX compiler in your build.`,
101
- ' Without one they render unstyled (no error). See setup per framework:',
102
+ ` Without one, importing them throws "Unexpected 'stylex.create' call at runtime"`,
103
+ ' and the page does not render. See setup per framework:',
102
104
  ` ${run} docs styling`,
103
105
  ' Next.js note: the StyleX Babel plugin disables SWC and breaks next/font -',
104
106
  ' use an SWC-based StyleX transform instead (covered in the guide).',
@@ -15,8 +15,16 @@ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
15
15
  import * as fs from 'node:fs';
16
16
  import * as path from 'node:path';
17
17
  import * as os from 'node:os';
18
+ import {createRequire} from 'node:module';
19
+ import {fileURLToPath} from 'node:url';
18
20
  import {runCli} from '../../../test-utils/run-cli.mjs';
19
21
 
22
+ /** The StyleX runtime that Core ships with, resolved the way Core resolves it. */
23
+ const CORE_PACKAGE = path.resolve(
24
+ path.dirname(fileURLToPath(import.meta.url)),
25
+ '../../../../core/package.json',
26
+ );
27
+
20
28
  /**
21
29
  * Build a fake @astryxdesign/core under <project>/node_modules with a single
22
30
  * swizzleable Button component (bare `Button.tsx`, no doc).
@@ -303,10 +311,19 @@ describe('swizzle — StyleX build setup note (#3373)', () => {
303
311
  const humanResult = await runCli(['swizzle', 'Styled', '-f'], project);
304
312
  expect(humanResult.code).toBe(0);
305
313
  expect(humanResult.stdout).toMatch(/StyleX compiler/i);
306
- expect(humanResult.stdout).toMatch(/unstyled/i);
314
+ expect(humanResult.stdout).toMatch(/importing them throws "Unexpected 'stylex\.create' call at runtime"/);
315
+ expect(humanResult.stdout).not.toMatch(/unstyled/i);
307
316
  expect(humanResult.stdout).toMatch(/next\/font/i);
308
317
  // The fixture has no `astryx` bin installed, so the note names the scoped package.
309
- expect(humanResult.stdout).toMatch(/@astryxdesign\/cli docs styling/);
318
+ expect(humanResult.stdout).toMatch(/@astryxdesign\/cli@\S+ docs styling/);
319
+ });
320
+
321
+ // The note quotes what StyleX does without a compiler; this keeps it true.
322
+ it('matches what the StyleX runtime does when styles are not compiled', () => {
323
+ const stylex = createRequire(CORE_PACKAGE)('@stylexjs/stylex');
324
+ expect(() => stylex.create({root: {color: 'red'}})).toThrow(
325
+ /Unexpected 'stylex\.create' call at runtime/,
326
+ );
310
327
  });
311
328
 
312
329
  it('does not print the StyleX note for components without StyleX', async () => {
@@ -102,6 +102,7 @@ export const doc = {
102
102
  cli: 'astryx template --cdn public/demo.html',
103
103
  },
104
104
  ],
105
+ outsideProject: 'same',
105
106
  exitCodes: [
106
107
  {
107
108
  code: 0,
@@ -341,6 +341,11 @@ const CASES = [
341
341
  args: ['doctor', 'integration', 'validate'],
342
342
  skipFieldChecks: true,
343
343
  },
344
+ {
345
+ name: 'integration check',
346
+ args: ['integration', 'check'],
347
+ skipFieldChecks: true,
348
+ },
344
349
  {
345
350
  name: 'doctor integration components',
346
351
  args: ['doctor', 'integration', 'components'],
@@ -20,7 +20,7 @@ beforeEach(() => {
20
20
  JSON.stringify({
21
21
  name: 'app',
22
22
  private: true,
23
- dependencies: {'@acme/themes': '^1.0.0'},
23
+ dependencies: {'@acme/themes': '^1.0.0', '@astryxdesign/core': '*'},
24
24
  }),
25
25
  );
26
26
  const packageDir = path.join(tmpDir, 'node_modules', '@acme', 'themes');
@@ -99,7 +99,7 @@ describe('theme add cleanup lifecycle', () => {
99
99
  change: {action: 'add', slug: 'ocean', changed: true},
100
100
  },
101
101
  });
102
- expect(payload.meta).toBeUndefined();
102
+ expect(Object.keys(payload.meta)).toEqual(['answeredBy']);
103
103
  });
104
104
 
105
105
  it('keeps --import as an accepted no-op with the same response', async () => {
@@ -151,7 +151,7 @@ describe('theme add cleanup lifecycle', () => {
151
151
  expect(result.status, result.stderr).toBe(0);
152
152
  const payload = JSON.parse(result.stdout);
153
153
  expect(payload).toMatchObject({type: 'theme.list'});
154
- expect(payload.meta).toBeUndefined();
154
+ expect(Object.keys(payload.meta)).toEqual(['answeredBy']);
155
155
  expect(payload.data.some(theme => theme.slug === 'broken')).toBe(false);
156
156
  expect(Object.keys(payload.data[0]).sort()).toEqual([
157
157
  'description',
@@ -11,7 +11,7 @@ export const doc = {
11
11
  summary:
12
12
  "Add a built theme to the app. To copy a theme's source as an editable fork, run `theme eject <slug> [path] [--overwrite]`.",
13
13
  description:
14
- "Records the theme in the generated app module and imports its built module and stylesheets. --import remains accepted as a compatibility no-op. To copy a theme's source as an editable fork, run `theme eject <slug> [path] [--overwrite]`. A bare command or --list delegates to themeListCopySources(), whose released JSON bytes stay unchanged while its text names the current add and eject commands; use --package when owners share a slug.",
14
+ "Records the theme in the generated app module and imports its built module and stylesheets. --import remains accepted as a compatibility no-op. To copy a theme's source as an editable fork, run `theme eject <slug> [path] [--overwrite]`. A bare command or --list delegates to themeListCopySources(), whose released JSON bytes stay unchanged while its text names the current add and eject commands; use --package when owners share a slug. Outside a project, a bare command or --list lists the available themes as in a new project; given a slug it writes nothing and fails, naming the app project it needs (ERR_THEME_INVALID), or with ERR_UNKNOWN_THEME when no theme has that slug.",
15
15
  fn: 'themeAdd',
16
16
  args: [{name: 'slug', param: 'slug', required: false}],
17
17
  options: [
@@ -38,6 +38,7 @@ export const doc = {
38
38
  cli: 'astryx theme add ocean --package @acme/themes',
39
39
  },
40
40
  ],
41
+ outsideProject: 'own',
41
42
  exitCodes: [
42
43
  {code: 0, when: 'the theme is listed or added'},
43
44
  {
@@ -46,4 +47,10 @@ export const doc = {
46
47
  },
47
48
  ],
48
49
  related: ['theme list', 'theme remove', 'theme use', 'theme eject'],
50
+ notes: [
51
+ {
52
+ type: 'prose',
53
+ text: 'In global mode: outside a project, theme add with no slug lists the themes available, as in a new project; with a slug it writes nothing and stops with `ERR_THEME_INVALID`: "No package.json found. Run this command inside an app project." In a project, the project\'s version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:problems}.',
54
+ },
55
+ ],
49
56
  };
@@ -30,7 +30,7 @@ export const doc = {
30
30
  {
31
31
  flag: '--family',
32
32
  description:
33
- 'Build the selected extension family into one keyed CSS, JS, and declaration set. Requires --family-key; refused with --out or --watch (ERR_THEME_INVALID)',
33
+ 'Build the selected extension family into one keyed CSS, JS, and declaration set, written beside the family root theme file, which must be inside the working directory to build (ERR_PATH_TRAVERSAL); --check only reads, so it compares outputs anywhere. Requires --family-key; refused with --out or --watch (ERR_THEME_INVALID)',
34
34
  },
35
35
  {
36
36
  flag: '--family-key <key>',
@@ -41,7 +41,7 @@ export const doc = {
41
41
  flag: '-o, --out <path>',
42
42
  param: 'options.out',
43
43
  description:
44
- 'Output CSS file path; the .js and .d.ts are written beside it (default: <theme name>.css next to the source). A relative path must stay inside the working directory. Single theme only: refused with more than one file or with --family (ERR_THEME_INVALID)',
44
+ 'Output CSS file path, relative or absolute; the .js and .d.ts are written beside it (default: <theme name>.css next to the source). A build writes only inside the working directory, the defaults beside the source too (ERR_PATH_TRAVERSAL); --check writes nothing, so it compares outputs anywhere and refuses only a relative path that escapes the working directory. Single theme only: refused with more than one file or with --family (ERR_THEME_INVALID)',
45
45
  },
46
46
  {
47
47
  flag: '--icons-specifier <specifier>',
@@ -83,6 +83,7 @@ export const doc = {
83
83
  cli: 'astryx theme build ./src/themes/ocean.ts --icons-specifier ./icons.mjs',
84
84
  },
85
85
  ],
86
+ outsideProject: 'same',
86
87
  exitCodes: [
87
88
  {
88
89
  code: 0,
@@ -36,6 +36,7 @@ export const doc = {
36
36
  cli: 'astryx theme eject ocean src/themes/my-ocean --package @acme/themes',
37
37
  },
38
38
  ],
39
+ outsideProject: 'same',
39
40
  exitCodes: [
40
41
  {code: 0, when: 'all source and descriptor files are written'},
41
42
  {
@@ -24,6 +24,12 @@ afterEach(() => {
24
24
 
25
25
  describe('astryx theme list', () => {
26
26
  it('lists bundled themes and points at import, eject, and discover', async () => {
27
+ // Inside a project; outside one there is no app to import into
28
+ // (outside-project.test.mjs).
29
+ fs.writeFileSync(
30
+ path.join(tmpDir, 'package.json'),
31
+ '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}',
32
+ );
27
33
  const {status, stdout} = await runCli(['theme', 'list'], {cwd: tmpDir});
28
34
 
29
35
  expect(status).toBe(0);
@@ -33,6 +33,7 @@ export const doc = {
33
33
  cli: 'astryx theme list --package @acme/themes',
34
34
  },
35
35
  ],
36
+ outsideProject: 'same',
36
37
  exitCodes: [
37
38
  {code: 0, when: 'success'},
38
39
  {
@@ -57,6 +57,7 @@ export const doc = {
57
57
  cli: 'astryx theme palette generate themes/ocean/palette.config.json --out themes/ocean/tokens/ocean.palette.ts --preview themes/ocean/tokens/ocean.palette.html',
58
58
  },
59
59
  ],
60
+ outsideProject: 'same',
60
61
  exitCodes: [
61
62
  {
62
63
  code: 0,
@@ -14,9 +14,16 @@ export const doc = {
14
14
  fn: 'themeRemove',
15
15
  args: [{name: 'slug', param: 'slug', required: true}],
16
16
  examples: [{label: 'Remove an added theme', cli: 'astryx theme remove ocean'}],
17
+ outsideProject: 'refuse',
17
18
  exitCodes: [
18
19
  {code: 0, when: 'the module is regenerated without the theme'},
19
20
  {code: 1, when: 'the theme is not added, is the default, or state is invalid'},
20
21
  ],
21
22
  related: ['theme add', 'theme use', 'theme list'],
23
+ notes: [
24
+ {
25
+ type: 'prose',
26
+ text: "In global mode: outside a project, theme remove writes nothing and stops with `ERR_THEME_INVALID`: \"No package.json found. Run this command inside an app project.\" In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:problems}.",
27
+ },
28
+ ],
22
29
  };
@@ -30,6 +30,7 @@ export const doc = {
30
30
  {label: 'Search keys', cli: 'astryx theme targets thumb'},
31
31
  {label: 'For a lint or an audit script', cli: 'astryx --json theme targets'},
32
32
  ],
33
+ outsideProject: 'same',
33
34
  exitCodes: [
34
35
  {code: 0, when: 'success'},
35
36
  {code: 1, when: 'a filter matches no target, or core cannot be resolved'},
@@ -35,6 +35,7 @@ export const doc = {
35
35
  {label: 'Write it at the project root', cli: 'astryx theme template'},
36
36
  {label: 'Somewhere else', cli: 'astryx theme template src/themes/starter.ts'},
37
37
  ],
38
+ outsideProject: 'same',
38
39
  exitCodes: [
39
40
  {code: 0, when: 'success, including when an existing file was left untouched'},
40
41
  {code: 1, when: 'the target path escapes the project, or the file cannot be written'},
@@ -14,9 +14,16 @@ export const doc = {
14
14
  fn: 'themeUse',
15
15
  args: [{name: 'slug', param: 'slug', required: true}],
16
16
  examples: [{label: 'Choose the default theme', cli: 'astryx theme use ocean'}],
17
+ outsideProject: 'refuse',
17
18
  exitCodes: [
18
19
  {code: 0, when: 'the module is regenerated with the selected default'},
19
20
  {code: 1, when: 'the theme is not added or state is invalid'},
20
21
  ],
21
22
  related: ['theme add', 'theme remove', 'theme list'],
23
+ notes: [
24
+ {
25
+ type: 'prose',
26
+ text: "In global mode: outside a project, theme use writes nothing and stops with `ERR_THEME_INVALID`: \"No package.json found. Run this command inside an app project.\" In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:problems}.",
27
+ },
28
+ ],
22
29
  };
@@ -30,6 +30,7 @@ import {Command} from 'commander';
30
30
  import {registerUpgrade} from './upgrade.mjs';
31
31
  import {Project} from '../../../foundation/config/project.mjs';
32
32
  import {generateCompressedIndex} from '../../../foundation/agent-docs/agent-docs.mjs';
33
+ import {CLI_VERSION} from '../../../test-utils/release-fixtures.mjs';
33
34
 
34
35
  let tmpDir;
35
36
  let originalCwd;
@@ -189,7 +190,7 @@ describe('upgrade — core codemods run before config load', () => {
189
190
  expect(out).toMatch(/fails strict validation/i);
190
191
  // The fixture has no `astryx` bin installed, so the command names the scoped package.
191
192
  expect(out).toContain(
192
- '@astryxdesign/cli upgrade --from 0.1.2 --codemod migrate-layout-components-to-experimental --apply',
193
+ `@astryxdesign/cli@${CLI_VERSION} upgrade --from 0.1.2 --codemod migrate-layout-components-to-experimental --apply`,
193
194
  );
194
195
  expect(exitCode).not.toBe(1);
195
196
  });
@@ -21,7 +21,9 @@ export const doc = {
21
21
  'agent-docs block when Core or configured integration guidance changes. ' +
22
22
  'Dry-run by default. --apply writes codemod and receipt changes, runs hooks, then refreshes agent docs. ' +
23
23
  'Anything a post-codemod hook prints goes to stderr, so stdout carries only the result. ' +
24
- 'ShadCN-copied compositions are checked automatically during a normal upgrade, or alone with --registry.',
24
+ 'ShadCN-copied compositions are checked automatically during a normal upgrade, or alone with --registry. ' +
25
+ 'Outside a project, --list lists the codemods this release ships and --registry finds no copied compositions to update; ' +
26
+ 'a migration writes nothing and fails with ERR_VERSION_DETECT, because no installed Core names its target.',
25
27
  fn: 'upgrade',
26
28
  options: [
27
29
  {
@@ -102,6 +104,7 @@ export const doc = {
102
104
  },
103
105
  {label: 'Apply a migration', cli: 'astryx upgrade --from 0.1.0 --apply'},
104
106
  ],
107
+ outsideProject: 'own',
105
108
  exitCodes: [
106
109
  {code: 0, when: 'success, including complete dry-run previews'},
107
110
  {
@@ -116,6 +119,24 @@ export const doc = {
116
119
  ],
117
120
  related: ['init', 'doctor'],
118
121
  notes: [
122
+ {
123
+ type: 'prose',
124
+ text: "In global mode: in a project, upgrade runs the codemods of the project's own CLI, whichever astryx command you start; in a project with no CLI of its own, the astryx command you started runs them, so install the CLI at the new Core's version first (`astryx doctor` prints the command). Outside a project, `--list` lists this version's codemods, `--registry` finds no copied compositions, and a migration writes nothing and stops with `ERR_VERSION_DETECT`. See {@link namespace:global} and {@link generic:who-answers}.",
125
+ },
126
+ {type: 'heading', level: 3, text: 'A CLI older than your Core'},
127
+ {
128
+ type: 'prose',
129
+ text:
130
+ 'Core codemods ship inside the CLI, so a CLI older than the installed @astryxdesign/core has none for ' +
131
+ 'the releases after its own version. upgrade then says it cannot finish, never reports your code as up to date, ' +
132
+ 'and prints the same upgrade pinned to the CLI release that matches your Core, such as ' +
133
+ '`cd <project> && npx @astryxdesign/cli@<core-version> upgrade --from <old-version> --path <source-dir> --apply`. ' +
134
+ 'It changes to the folder this run used and names the directory it scanned as an absolute path, both with ' +
135
+ 'symbolic links resolved, so pasted from any folder it upgrades the same code. It is written for a POSIX shell (sh, bash, zsh), or for PowerShell on Windows, ' +
136
+ 'with each argument quoted for that shell; cmd.exe is not a target. The codemods this CLI has still run. ' +
137
+ 'It exits 0, so a script checks the JSON: the result carries `cliBehindCore` with `cliVersion` (the newest release ' +
138
+ 'this CLI has codemods for) and `command`.',
139
+ },
119
140
  {type: 'heading', level: 3, text: 'Protected files'},
120
141
  {
121
142
  type: 'prose',
@@ -10,6 +10,7 @@ import * as fs from 'node:fs';
10
10
  import * as os from 'node:os';
11
11
  import * as path from 'node:path';
12
12
  import {fileURLToPath} from 'node:url';
13
+ import {CLI_VERSION} from '../../../test-utils/release-fixtures.mjs';
13
14
 
14
15
  const CLI = path.resolve(
15
16
  path.dirname(fileURLToPath(import.meta.url)),
@@ -44,7 +45,7 @@ function seed({hook = false} = {}) {
44
45
  write('package.json', JSON.stringify({name: 'consumer', private: true}));
45
46
  write(
46
47
  'node_modules/@astryxdesign/core/package.json',
47
- JSON.stringify({name: '@astryxdesign/core', version: '0.6.0'}),
48
+ JSON.stringify({name: '@astryxdesign/core', version: CLI_VERSION}),
48
49
  );
49
50
  write('.gitattributes', 'generated/** linguist-generated=true\n');
50
51
  const source =
@@ -122,7 +123,7 @@ describe('upgrade protected-file contract', () => {
122
123
  write('package.json', JSON.stringify({name: 'consumer', private: true}));
123
124
  write(
124
125
  'node_modules/@astryxdesign/core/package.json',
125
- JSON.stringify({name: '@astryxdesign/core', version: '0.1.3'}),
126
+ JSON.stringify({name: '@astryxdesign/core', version: CLI_VERSION}),
126
127
  );
127
128
  write(
128
129
  'astryx.config.mjs',
@@ -12,6 +12,7 @@ import * as fs from 'node:fs';
12
12
  import * as path from 'node:path';
13
13
  import * as os from 'node:os';
14
14
  import {fileURLToPath} from 'node:url';
15
+ import {CLI_VERSION} from '../../../test-utils/release-fixtures.mjs';
15
16
 
16
17
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
18
  const CLI = path.resolve(__dirname, '..', 'bin', 'astryx.mjs');
@@ -41,7 +42,7 @@ beforeEach(() => {
41
42
  write('package.json', JSON.stringify({name: 'consumer', private: true}));
42
43
  write(
43
44
  'node_modules/@astryxdesign/core/package.json',
44
- JSON.stringify({name: '@astryxdesign/core', version: '0.6.0'}),
45
+ JSON.stringify({name: '@astryxdesign/core', version: CLI_VERSION}),
45
46
  );
46
47
  write(
47
48
  'src/panel.tsx',