@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
@@ -0,0 +1,87 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file init.user leaf — the `--user` path behind `astryx init`.
5
+ *
6
+ * `user(options)` writes, refreshes, or (with `remove`) removes the
7
+ * computer-level agent text: one skill file in the home folder, linked into
8
+ * the skill folders agents read (spec AST-081 FR7, FR8). It records the
9
+ * setting and the links it made in the settings file, so the global copy,
10
+ * which keeps the text current in the background, does the same, or, after
11
+ * `remove`, writes nothing. The adapter does every file access. It works in any
12
+ * folder and never touches a project's agent docs. A file without the Astryx
13
+ * markers, one a person edited, or a symlinked one is kept as it is. When no
14
+ * `astryx` on the computer's search path runs the Astryx CLI, the text is
15
+ * still written and the receipt warns that the CLI should be installed for
16
+ * the computer.
17
+ *
18
+ * @input `remove`; the home folder, search path, and settings of
19
+ * the computer
20
+ * @output an `init.user` receipt
21
+ * @position packages/cli/api/init — dispatched by init.mjs
22
+ */
23
+
24
+ import {
25
+ COMPUTER_COMMAND,
26
+ COMPUTER_INSTALL_STEP,
27
+ applyComputerAgentText,
28
+ displayHomePath,
29
+ } from '../_adapter.mjs';
30
+ import {logger} from '../../logger.mjs';
31
+
32
+ /**
33
+ * @param {string} file
34
+ * @param {string} home
35
+ * @returns {string}
36
+ */
37
+ const display = (file, home) => displayHomePath(file, home);
38
+
39
+ /** @type {Record<import('../init.type.mjs').InitUserAction, string>} */
40
+ const ACTION_LINES = {
41
+ written: '[ok] Wrote',
42
+ linked: '[ok] Linked',
43
+ unchanged: '[ok] Already current:',
44
+ removed: '[ok] Removed',
45
+ absent: '[ok] Nothing to remove:',
46
+ kept: '[skip] Kept',
47
+ };
48
+
49
+ /** @type {Record<'edited' | 'not-astryx', string>} */
50
+ const KEPT_REASONS = {
51
+ edited: '(edited since Astryx wrote it; delete it to get the current text):',
52
+ 'not-astryx': '(not created by Astryx):',
53
+ };
54
+
55
+ /**
56
+ * Write or remove the computer-level agent text and return an `init.user`
57
+ * receipt. Progress is emitted through the shared `logger` (silent by
58
+ * default); warnings go to its warn channel.
59
+ *
60
+ * @param {{remove?: boolean}} [options]
61
+ * @returns {Promise<import('../init.type.mjs').InitUserResponse>}
62
+ */
63
+ export async function user({remove = false} = {}) {
64
+ const {home, command, files, cliOnSearchPath} = applyComputerAgentText({
65
+ remove,
66
+ });
67
+ /** @type {string[]} */
68
+ const warnings = [];
69
+ // A host's door is its own command; only the plain `astryx` needs a copy of
70
+ // the CLI installed for the computer.
71
+ if (!remove && command === COMPUTER_COMMAND && !cliOnSearchPath) {
72
+ warnings.push(
73
+ `No \`${COMPUTER_COMMAND}\` command on this computer runs the Astryx CLI, so agents cannot run the commands this text names. Install the CLI for the computer: ${COMPUTER_INSTALL_STEP}`,
74
+ );
75
+ }
76
+ for (const file of files) {
77
+ const reason = file.reason ? ` ${KEPT_REASONS[file.reason]}` : '';
78
+ logger.log(
79
+ `${ACTION_LINES[file.action]}${reason || (file.action === 'kept' ? ':' : '')} ${display(file.path, home)}`,
80
+ );
81
+ }
82
+ for (const warning of warnings) logger.warn(`[warn] ${warning}`);
83
+ return {
84
+ type: 'init.user',
85
+ data: {files, command, warnings},
86
+ };
87
+ }
@@ -0,0 +1,232 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `init({user})` and `astryx init --user`: the `init.user` receipt, the
5
+ * install warning, the refused combinations, and that it touches nothing in
6
+ * the folder it runs in. Every test uses a temporary home folder and search
7
+ * path.
8
+ */
9
+
10
+ import * as fs from 'node:fs';
11
+ import * as os from 'node:os';
12
+ import * as path from 'node:path';
13
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
14
+ import {init} from '../init.mjs';
15
+ import {user} from './user.mjs';
16
+ import {runWithCliDoor} from '../../../foundation/env/cli-command.mjs';
17
+ import {renderComputerAgentText} from '../../../foundation/agent-docs/computer-agent-text.mjs';
18
+ import {runCli} from '../../../test-utils/run-cli.mjs';
19
+ import {settingsFile} from '../../../foundation/env/user-settings.mjs';
20
+ import {readGlobalState} from '../../../foundation/release/global-state.mjs';
21
+ import {cliVersion} from '../../../foundation/release/run-context.mjs';
22
+
23
+ /** @type {string[]} */
24
+ const dirs = [];
25
+ /** @param {string} label */
26
+ function tmp(label) {
27
+ const dir = fs.mkdtempSync(
28
+ path.join(os.tmpdir(), `astryx-init-user-${label}-`),
29
+ );
30
+ dirs.push(dir);
31
+ return dir;
32
+ }
33
+
34
+ let home = '';
35
+ let emptyPath = '';
36
+ beforeEach(() => {
37
+ home = tmp('home');
38
+ emptyPath = tmp('path');
39
+ vi.stubEnv('HOME', home);
40
+ vi.stubEnv('USERPROFILE', home);
41
+ vi.stubEnv('PATH', emptyPath);
42
+ // The settings file and the cache live under this home folder too.
43
+ vi.stubEnv('XDG_CONFIG_HOME', path.join(home, '.config'));
44
+ vi.stubEnv('XDG_CACHE_HOME', path.join(home, '.cache'));
45
+ vi.stubEnv('APPDATA', path.join(home, 'AppData', 'Roaming'));
46
+ vi.stubEnv('LOCALAPPDATA', path.join(home, 'AppData', 'Local'));
47
+ });
48
+
49
+ /** The settings file under the temporary home folder. */
50
+ const settings = () => {
51
+ try {
52
+ return JSON.parse(fs.readFileSync(settingsFile(), 'utf8'));
53
+ } catch {
54
+ return null;
55
+ }
56
+ };
57
+ afterEach(() => {
58
+ vi.unstubAllEnvs();
59
+ while (dirs.length) {
60
+ fs.rmSync(/** @type {string} */ (dirs.pop()), {
61
+ recursive: true,
62
+ force: true,
63
+ });
64
+ }
65
+ });
66
+
67
+ const FILE = path.join('.agents', 'skills', 'astryx', 'SKILL.md');
68
+ const CLAUDE = path.join('.claude', 'skills', 'astryx');
69
+
70
+ /** Put a linked Astryx CLI first on the search path. */
71
+ function installCliOnPath() {
72
+ const prefix = tmp('prefix');
73
+ const pkg = path.join(prefix, 'lib', 'node_modules', '@astryxdesign', 'cli');
74
+ fs.mkdirSync(pkg, {recursive: true});
75
+ fs.writeFileSync(
76
+ path.join(pkg, 'package.json'),
77
+ '{"name":"@astryxdesign/cli"}',
78
+ );
79
+ fs.writeFileSync(path.join(pkg, 'bin.mjs'), '#!/usr/bin/env node\n');
80
+ fs.chmodSync(path.join(pkg, 'bin.mjs'), 0o755);
81
+ fs.mkdirSync(path.join(prefix, 'bin'));
82
+ fs.symlinkSync(path.join(pkg, 'bin.mjs'), path.join(prefix, 'bin', 'astryx'));
83
+ vi.stubEnv('PATH', path.join(prefix, 'bin'));
84
+ }
85
+
86
+ describe('init({user: true})', () => {
87
+ it('writes the file, links Claude Code to it, and returns the init.user receipt, warning when no astryx runs the CLI', async () => {
88
+ const r = await init({user: true}, {cwd: tmp('cwd')});
89
+ expect(r.type).toBe('init.user');
90
+ if (r.type !== 'init.user') return;
91
+ expect(r.data.files).toEqual([
92
+ {path: path.join(home, FILE), action: 'written'},
93
+ {path: path.join(home, CLAUDE), action: 'linked'},
94
+ ]);
95
+ expect(r.data.command).toBe('astryx');
96
+ expect(r.data.warnings).toHaveLength(1);
97
+ expect(r.data.warnings[0]).toContain('npm i -g @astryxdesign/cli');
98
+ expect(fs.readFileSync(path.join(home, FILE), 'utf8')).toBe(
99
+ renderComputerAgentText({command: 'astryx'}),
100
+ );
101
+ expect(fs.readFileSync(path.join(home, CLAUDE, 'SKILL.md'), 'utf8')).toBe(
102
+ renderComputerAgentText({command: 'astryx'}),
103
+ );
104
+ });
105
+
106
+ it.skipIf(process.platform === 'win32')(
107
+ 'does not warn when the astryx on the search path is the Astryx CLI',
108
+ async () => {
109
+ installCliOnPath();
110
+ const r = await user();
111
+ expect(r.data.warnings).toEqual([]);
112
+ },
113
+ );
114
+
115
+ it("names the host's door and does not ask for a global install", async () => {
116
+ const r = await runWithCliDoor('acme astryx', () => user());
117
+ expect(r.data.command).toBe('acme astryx');
118
+ expect(r.data.warnings).toEqual([]);
119
+ expect(fs.readFileSync(path.join(home, FILE), 'utf8')).toContain(
120
+ "`acme astryx search '<what you need>'`",
121
+ );
122
+ });
123
+
124
+ it('works inside a project and writes nothing in it', async () => {
125
+ const dir = tmp('project');
126
+ fs.writeFileSync(
127
+ path.join(dir, 'package.json'),
128
+ '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}',
129
+ );
130
+ const before = fs.readdirSync(dir).sort();
131
+ const r = await init({user: true}, {cwd: dir});
132
+ expect(r.type).toBe('init.user');
133
+ expect(fs.readdirSync(dir).sort()).toEqual(before);
134
+ });
135
+
136
+ it('records the links it made, and the release that wrote the text', async () => {
137
+ await init({user: true});
138
+ expect(settings()).toEqual({
139
+ computerAgentText: {install: true, links: [path.join(home, CLAUDE)]},
140
+ });
141
+ expect(readGlobalState().agentText).toEqual({writtenBy: cliVersion()});
142
+ });
143
+
144
+ it('keeps every other setting when it records the choice', async () => {
145
+ fs.mkdirSync(path.dirname(settingsFile()), {recursive: true});
146
+ fs.writeFileSync(settingsFile(), '{"other": 1}');
147
+ await init({user: true, removeAgents: true});
148
+ expect(settings()).toEqual({
149
+ other: 1,
150
+ computerAgentText: {install: false, links: []},
151
+ });
152
+ });
153
+
154
+ it('with removeAgents removes the file and the links it made, and records that the text is not wanted', async () => {
155
+ await init({user: true});
156
+ const r = await init({user: true, removeAgents: true});
157
+ expect(r.type).toBe('init.user');
158
+ if (r.type !== 'init.user') return;
159
+ expect(r.data.files).toEqual([
160
+ {path: path.join(home, FILE), action: 'removed'},
161
+ {path: path.join(home, CLAUDE), action: 'removed'},
162
+ ]);
163
+ expect(r.data.warnings).toEqual([]);
164
+ expect(fs.existsSync(path.join(home, FILE))).toBe(false);
165
+ expect(fs.existsSync(path.join(home, CLAUDE))).toBe(false);
166
+ expect(settings()).toEqual({
167
+ computerAgentText: {install: false, links: []},
168
+ });
169
+ });
170
+
171
+ it.each([
172
+ [{features: 'agents'}, '--features'],
173
+ [{all: true}, '--all'],
174
+ [{agentDocsPath: 'X.md'}, '--agent-docs-path'],
175
+ [{agent: 'claude'}, '--agent'],
176
+ [{removeAgents: true, agent: 'claude'}, '--agent'],
177
+ ])(
178
+ 'refuses %o with ERR_INVALID_ARGUMENT and writes nothing',
179
+ async (extra, flag) => {
180
+ await expect(init({user: true, ...extra})).rejects.toMatchObject({
181
+ code: 'ERR_INVALID_ARGUMENT',
182
+ message: expect.stringContaining(flag),
183
+ });
184
+ expect(fs.existsSync(path.join(home, '.agents'))).toBe(false);
185
+ expect(fs.existsSync(path.join(home, '.claude'))).toBe(false);
186
+ },
187
+ );
188
+ });
189
+
190
+ describe('astryx init --user', () => {
191
+ it('prints the file, the link, and the install warning in text mode', async () => {
192
+ const r = await runCli(['init', '--user'], tmp('cwd'));
193
+ expect(r.status).toBe(0);
194
+ expect(r.stdout).toContain(`Wrote ~${path.sep}${FILE}`);
195
+ expect(r.stdout).toContain(`Linked ~${path.sep}${CLAUDE}`);
196
+ expect(r.stderr).toContain('npm i -g @astryxdesign/cli');
197
+ });
198
+
199
+ it('emits the init.user envelope under --json', async () => {
200
+ const r = await runCli(['--json', 'init', '--user'], tmp('cwd'));
201
+ expect(r.status).toBe(0);
202
+ const env = JSON.parse(r.stdout);
203
+ expect(env.type).toBe('init.user');
204
+ expect(
205
+ env.data.files.map((/** @type {{action: string}} */ f) => f.action),
206
+ ).toEqual(['written', 'linked']);
207
+ expect(env.data.command).toBe('astryx');
208
+ });
209
+
210
+ it('names a file a person edited as kept, and why', async () => {
211
+ await runCli(['init', '--user'], tmp('cwd'));
212
+ const file = path.join(home, FILE);
213
+ fs.appendFileSync(file, 'my note\n');
214
+ const r = await runCli(['init', '--user'], tmp('cwd'));
215
+ expect(r.status).toBe(0);
216
+ expect(r.stdout).toContain(
217
+ `Kept (edited since Astryx wrote it; delete it to get the current text): ~${path.sep}${FILE}`,
218
+ );
219
+ expect(fs.readFileSync(file, 'utf8')).toMatch(/my note\n$/u);
220
+ });
221
+
222
+ it('exits 1 with ERR_INVALID_ARGUMENT when combined with --all or --agent', async () => {
223
+ for (const extra of [['--all'], ['--agent', 'claude']]) {
224
+ const r = await runCli(
225
+ ['--json', 'init', '--user', ...extra],
226
+ tmp('cwd'),
227
+ );
228
+ expect(r.status).toBe(1);
229
+ expect(JSON.parse(r.stdout).code).toBe('ERR_INVALID_ARGUMENT');
230
+ }
231
+ });
232
+ });
@@ -0,0 +1,45 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * Each component doc's props compared with the component's TypeScript props,
6
+ * read with the project's own compiler (spec:AST-039 FR12). Without one, the
7
+ * report says the comparison was skipped.
8
+ * @param {any} integration a loaded integration
9
+ * @param {string} cwd
10
+ * @returns {Promise<import('../../foundation/discovery/prop-drift.mjs').PropDriftReport>}
11
+ */
12
+ export function integrationPropDrift(integration: any, cwd: string): Promise<import("../../foundation/discovery/prop-drift.mjs").PropDriftReport>;
13
+ /**
14
+ * The passages two of a package's topics, or one of them and a Core topic,
15
+ * repeat word for word (architecture:cli-surface DEC-8). Reads the package's
16
+ * topics and Core's guides.
17
+ *
18
+ * @param {Parameters<typeof findCopiedPassages>[0]} discovered the package's
19
+ * docs, as discoverIntegrationDocs returns them
20
+ */
21
+ export function integrationCopiedPassages(discovered: Parameters<typeof findCopiedPassages>[0]): Promise<import("./authoring-checks.type.mjs").CopiedPassage[]>;
22
+ /**
23
+ * Padding phrases and low-density topics in a package's prose
24
+ * (architecture:cli-surface DEC-8). Reads the package's topics, and Core's
25
+ * guides for the density median a finding names.
26
+ *
27
+ * @param {Parameters<typeof findFluff>[0]} discovered the package's docs, as
28
+ * discoverIntegrationDocs returns them
29
+ */
30
+ export function integrationFluff(discovered: Parameters<typeof findFluff>[0]): Promise<import("./authoring-checks.type.mjs").DocFluff[]>;
31
+ /**
32
+ * Code spans in a package's prose that write `astryx docs <name>` for a doc
33
+ * that exists, where `{@link generic:<name>}` would be checked
34
+ * (architecture:cli-surface DEC-8). Reads the package's topics, its own
35
+ * component docs, and the names of Core's docs.
36
+ *
37
+ * @param {Parameters<typeof findStrayPointers>[0]} discovered the package's
38
+ * docs, as discoverIntegrationDocs returns them
39
+ * @param {any} [integration] the loaded integration, whose component docs are
40
+ * read too
41
+ */
42
+ export function integrationStrayPointers(discovered: Parameters<typeof findStrayPointers>[0], integration?: any): Promise<import("./authoring-checks.type.mjs").StrayPointer[]>;
43
+ import { findCopiedPassages } from '../../foundation/discovery/copied-passages.mjs';
44
+ import { findFluff } from '../../foundation/discovery/doc-fluff.mjs';
45
+ import { findStrayPointers } from '../../foundation/discovery/stray-pointers.mjs';
@@ -0,0 +1,112 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The integration subject's access to the environment (INV21): reading
5
+ * one package's component docs and sources with the project's own TypeScript.
6
+ *
7
+ * @input a loaded integration and the directory the command runs in
8
+ * @output the reports the integration checks attach to their results
9
+ * @position api/integration (internal; not exported from ./api)
10
+ */
11
+
12
+ import {
13
+ discoverValidIntegrationComponents,
14
+ forEachIntegrationDoc,
15
+ integrationSourceForDoc,
16
+ } from '../../foundation/discovery/component-discovery.mjs';
17
+ import {comparePropDocs} from '../../foundation/discovery/prop-drift.mjs';
18
+ import {findCopiedPassages} from '../../foundation/discovery/copied-passages.mjs';
19
+ import {findFluff} from '../../foundation/discovery/doc-fluff.mjs';
20
+ import {findStrayPointers} from '../../foundation/discovery/stray-pointers.mjs';
21
+
22
+ /**
23
+ * Each component doc's props compared with the component's TypeScript props,
24
+ * read with the project's own compiler (spec:AST-039 FR12). Without one, the
25
+ * report says the comparison was skipped.
26
+ * @param {any} integration a loaded integration
27
+ * @param {string} cwd
28
+ * @returns {Promise<import('../../foundation/discovery/prop-drift.mjs').PropDriftReport>}
29
+ */
30
+ export async function integrationPropDrift(integration, cwd) {
31
+ const packageDir = /** @type {{__packageDir?: string}} */ (integration)
32
+ .__packageDir;
33
+ const {components} = await discoverValidIntegrationComponents(integration);
34
+ // Every doc the package ships has its prop tables compared or listed as not
35
+ // compared. A doc discovery leaves out (a hidden one, a second doc for one
36
+ // name, or one whose source or own file doesn't load) gets a record under
37
+ // its file name.
38
+ const recorded = new Set(components.map(c => c.docPath));
39
+ /** @type {typeof components} */
40
+ const left = [];
41
+ forEachIntegrationDoc(integration?.components, (docPath, stem) => {
42
+ if (recorded.has(docPath)) return;
43
+ recorded.add(docPath);
44
+ left.push({
45
+ name: stem,
46
+ package: integration.name,
47
+ docPath,
48
+ sourcePath: integrationSourceForDoc(docPath),
49
+ issuesUrl: integration.issuesUrl,
50
+ group: null,
51
+ });
52
+ });
53
+ return comparePropDocs([...components, ...left], {
54
+ packageDir: packageDir ?? cwd,
55
+ resolveFrom: [cwd, packageDir],
56
+ });
57
+ }
58
+
59
+ /**
60
+ * The passages two of a package's topics, or one of them and a Core topic,
61
+ * repeat word for word (architecture:cli-surface DEC-8). Reads the package's
62
+ * topics and Core's guides.
63
+ *
64
+ * @param {Parameters<typeof findCopiedPassages>[0]} discovered the package's
65
+ * docs, as discoverIntegrationDocs returns them
66
+ */
67
+ export function integrationCopiedPassages(discovered) {
68
+ return findCopiedPassages(discovered);
69
+ }
70
+
71
+ /**
72
+ * Padding phrases and low-density topics in a package's prose
73
+ * (architecture:cli-surface DEC-8). Reads the package's topics, and Core's
74
+ * guides for the density median a finding names.
75
+ *
76
+ * @param {Parameters<typeof findFluff>[0]} discovered the package's docs, as
77
+ * discoverIntegrationDocs returns them
78
+ */
79
+ export function integrationFluff(discovered) {
80
+ return findFluff(discovered);
81
+ }
82
+
83
+ /**
84
+ * Code spans in a package's prose that write `astryx docs <name>` for a doc
85
+ * that exists, where `{@link generic:<name>}` would be checked
86
+ * (architecture:cli-surface DEC-8). Reads the package's topics, its own
87
+ * component docs, and the names of Core's docs.
88
+ *
89
+ * @param {Parameters<typeof findStrayPointers>[0]} discovered the package's
90
+ * docs, as discoverIntegrationDocs returns them
91
+ * @param {any} [integration] the loaded integration, whose component docs are
92
+ * read too
93
+ */
94
+ export async function integrationStrayPointers(discovered, integration) {
95
+ /** @type {{name: string, file: string}[]} */
96
+ const components = [];
97
+ if (integration?.components) {
98
+ const seen = new Set();
99
+ try {
100
+ const {components: records} =
101
+ await discoverValidIntegrationComponents(integration);
102
+ for (const record of records) {
103
+ if (!record.docPath || seen.has(record.docPath)) continue;
104
+ seen.add(record.docPath);
105
+ components.push({name: record.name, file: record.docPath});
106
+ }
107
+ } catch {
108
+ // `validate` reports component docs that do not load.
109
+ }
110
+ }
111
+ return findStrayPointers({...discovered, components});
112
+ }
@@ -98,6 +98,72 @@ describe('integrationAddComponent name collisions', () => {
98
98
  expect(snapshot()).toEqual(before);
99
99
  });
100
100
 
101
+ it('adds a name a family doc lists but the module it imports does not export', async () => {
102
+ fs.writeFileSync(
103
+ path.join(tmpDir, 'package.json'),
104
+ `${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './components/tabs/index.ts'}}, null, 2)}\n`,
105
+ );
106
+ const tabs = path.join(tmpDir, 'components', 'tabs');
107
+ fs.mkdirSync(tabs, {recursive: true});
108
+ fs.writeFileSync(
109
+ path.join(tabs, 'AcmeTabs.doc.mjs'),
110
+ "export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTabExtra', description: 'x'}]};\n",
111
+ );
112
+ fs.writeFileSync(
113
+ path.join(tabs, 'AcmeTabs.tsx'),
114
+ 'export function AcmeTabs() { return null; }\nexport function AcmeTabExtra() { return null; }\n',
115
+ );
116
+ fs.writeFileSync(
117
+ path.join(tabs, 'index.ts'),
118
+ "export {AcmeTabs} from './AcmeTabs';\n",
119
+ );
120
+
121
+ const result = await integrationAdd('component', 'AcmeTabExtra', {
122
+ cwd: tmpDir,
123
+ dryRun: true,
124
+ });
125
+ expect(result.data.files).toContain('components/AcmeTabExtra.doc.mjs');
126
+ });
127
+
128
+ it('refuses a member a family exports through built output', async () => {
129
+ fs.writeFileSync(
130
+ path.join(tmpDir, 'package.json'),
131
+ `${JSON.stringify({name: '@acme/widgets', version: '1.0.0', files: ['dist'], exports: {'./tabs': './dist/tabs/index.js'}}, null, 2)}\n`,
132
+ );
133
+ const tabs = path.join(tmpDir, 'components', 'tabs');
134
+ fs.mkdirSync(tabs, {recursive: true});
135
+ fs.writeFileSync(
136
+ path.join(tabs, 'AcmeTabs.doc.mjs'),
137
+ "export default {type: 'component', name: 'AcmeTabs', import: '@acme/widgets/tabs', description: 'x', components: [{name: 'AcmeTab', description: 'x'}]};\n",
138
+ );
139
+ fs.writeFileSync(
140
+ path.join(tabs, 'AcmeTabs.tsx'),
141
+ 'export function AcmeTabs() { return null; }\n',
142
+ );
143
+ fs.writeFileSync(
144
+ path.join(tabs, 'AcmeTab.tsx'),
145
+ 'export function AcmeTab() { return null; }\n',
146
+ );
147
+ const dist = path.join(tmpDir, 'dist', 'tabs');
148
+ fs.mkdirSync(dist, {recursive: true});
149
+ fs.writeFileSync(
150
+ path.join(dist, 'index.js'),
151
+ "export {AcmeTabs} from './tabs.js';\nexport {AcmeTab} from './tab.js';\n",
152
+ );
153
+ fs.writeFileSync(
154
+ path.join(dist, 'tabs.js'),
155
+ 'export function AcmeTabs() { return null; }\n',
156
+ );
157
+ fs.writeFileSync(
158
+ path.join(dist, 'tab.js'),
159
+ 'export function AcmeTab() { return null; }\n',
160
+ );
161
+
162
+ await expect(
163
+ integrationAdd('component', 'AcmeTab', {cwd: tmpDir, dryRun: true}),
164
+ ).rejects.toThrow('Refusing to add component "AcmeTab"');
165
+ });
166
+
101
167
  it('still adds a component whose name is free', async () => {
102
168
  writeAuthoredComponent('components/AcmeWidget/AcmeWidget.doc.mjs');
103
169
 
@@ -264,9 +264,13 @@ async function addComponent(name, options) {
264
264
  ERROR_CODES.ERR_FILE_EXISTS,
265
265
  );
266
266
  }
267
- // Discovery keys components by doc stem anywhere under the root, so a second
268
- // doc with this name would shadow one of the two.
269
- const existingDoc = findIntegrationComponentDoc({components: root}, name);
267
+ // A second doc under a name discovery already records, by a doc's file name
268
+ // anywhere under the root or by a name a doc documents, would shadow one of
269
+ // the two.
270
+ const existingDoc = findIntegrationComponentDoc(
271
+ {name: owner, components: root, __packageDir: packageDir},
272
+ name,
273
+ );
270
274
  if (existingDoc != null) {
271
275
  throw new AstryxError(
272
276
  `Refusing to add component "${name}": ${projectPath(path.relative(packageDir, existingDoc))} already defines it.`,
@@ -691,7 +695,7 @@ async function addTemplate(name, options) {
691
695
  const sourcePath = projectPath(path.relative(packageDir, sourceFile));
692
696
  const extensionlessPath = sourcePath.replace(/\.tsx?$/u, '');
693
697
  const blockFields = templateType === 'block' ? '\n aspectRatio: 1,' : '';
694
- const specContents = `/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */\nexport default {\n type: '${templateType}',\n name: '${name}',\n displayName: '${kebabToTitle(name)}',\n description: '${kebabToTitle(name)} template.',${blockFields}\n};\n`;
698
+ const specContents = `/** @type {import('@astryxdesign/cli/authoring').IntegrationTemplateDoc} */\nexport default {\n type: '${templateType}',\n name: '${name}',\n displayName: '${kebabToTitle(name)}',\n description: '${kebabToTitle(name)} template.',${blockFields}\n};\n`;
695
699
  const sourceContents = `export default function ${pascalName}() {\n return <div>${kebabToTitle(name)}</div>;\n}\n`;
696
700
 
697
701
  /** @type {import('./add-helpers.mjs').WritePlan[]} */
@@ -536,7 +536,9 @@ describe('integrationAdd template', () => {
536
536
  path.join(tmpDir, 'templates/my-widget.doc.mjs'),
537
537
  'utf-8',
538
538
  );
539
- expect(spec).toContain("@astryxdesign/cli/authoring').TemplateDoc");
539
+ expect(spec).toContain(
540
+ "@astryxdesign/cli/authoring').IntegrationTemplateDoc",
541
+ );
540
542
  expect(spec).toContain("type: 'page'");
541
543
  expect(spec).toContain("name: 'my-widget'");
542
544
 
@@ -830,7 +832,7 @@ describe('typed descriptor conformance', () => {
830
832
  for (const [relativePath, type] of [
831
833
  ['components/MyWidget.doc.mjs', 'ComponentDoc'],
832
834
  ['docs/my-guide.doc.mjs', 'ReferenceDoc'],
833
- ['templates/my-page.doc.mjs', 'TemplateDoc'],
835
+ ['templates/my-page.doc.mjs', 'IntegrationTemplateDoc'],
834
836
  ['themes/ocean/oceanTheme.doc.mjs', 'ThemeDoc'],
835
837
  ]) {
836
838
  const source = fs.readFileSync(path.join(tmpDir, relativePath), 'utf-8');