@astryxdesign/cli 0.7.2-canary.fdd384f → 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 (450) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +169 -149
  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/kit/kit.mjs +3 -11
  7. package/api/component/_adapter.d.mts +31 -0
  8. package/api/component/_adapter.mjs +119 -11
  9. package/api/component/component.doc.mjs +6 -1
  10. package/api/component/component.mjs +60 -10
  11. package/api/component/doc-links.test.mjs +386 -0
  12. package/api/discover/_adapter.d.mts +132 -12
  13. package/api/discover/_adapter.mjs +488 -27
  14. package/api/discover/_adapter.test.mjs +599 -17
  15. package/api/discover/_catalog-view.d.mts +16 -5
  16. package/api/discover/_catalog-view.mjs +32 -8
  17. package/api/discover/detail/doc/doc.mjs +9 -1
  18. package/api/discover/discover.d.mts +11 -0
  19. package/api/discover/discover.doc.mjs +9 -7
  20. package/api/discover/discover.mjs +121 -19
  21. package/api/discover/discover.type.d.mts +20 -7
  22. package/api/discover/discover.type.mjs +17 -7
  23. package/api/discover/list/list.d.mts +4 -3
  24. package/api/discover/list/list.mjs +17 -10
  25. package/api/docs/_adapter.d.mts +63 -0
  26. package/api/docs/_adapter.mjs +312 -18
  27. package/api/docs/docs.doc.mjs +2 -1
  28. package/api/docs/docs.mjs +2 -1
  29. package/api/docs/docs.test.mjs +5 -2
  30. package/api/docs/integration-tree.test.mjs +22 -0
  31. package/api/docs/list/list.mjs +12 -2
  32. package/api/docs/reference-blocks.test.mjs +1 -3
  33. package/api/doctor/_adapter.d.mts +108 -0
  34. package/api/doctor/_adapter.mjs +223 -4
  35. package/api/doctor/doctor.d.mts +199 -0
  36. package/api/doctor/doctor.doc.mjs +3 -2
  37. package/api/doctor/doctor.mjs +530 -34
  38. package/api/doctor/doctor.test.mjs +180 -14
  39. package/api/doctor/release-checks.test.mjs +156 -0
  40. package/api/doctor/theme-checks.mjs +16 -3
  41. package/api/doctor/theme-checks.test.mjs +223 -7
  42. package/api/error.d.mts +10 -0
  43. package/api/error.mjs +25 -0
  44. package/api/gap-report/gap-report.d.mts +3 -0
  45. package/api/gap-report/gap-report.doc.mjs +11 -3
  46. package/api/gap-report/gap-report.mjs +152 -48
  47. package/api/gap-report/gap-report.test.mjs +233 -0
  48. package/api/gap-report/gap-report.type.d.mts +41 -0
  49. package/api/gap-report/gap-report.type.mjs +18 -0
  50. package/api/hook/_adapter.mjs +3 -11
  51. package/api/hook/hook.doc.mjs +4 -0
  52. package/api/hook/list/list.d.mts +1 -1
  53. package/api/init/_adapter.d.mts +22 -0
  54. package/api/init/_adapter.mjs +59 -0
  55. package/api/init/init.d.mts +7 -5
  56. package/api/init/init.doc.mjs +28 -7
  57. package/api/init/init.mjs +28 -4
  58. package/api/init/init.type.d.mts +48 -3
  59. package/api/init/init.type.mjs +37 -3
  60. package/api/init/run/run.d.mts +1 -1
  61. package/api/init/run/run.mjs +15 -4
  62. package/api/init/user/user.d.mts +14 -0
  63. package/api/init/user/user.mjs +87 -0
  64. package/api/init/user/user.test.mjs +232 -0
  65. package/api/integration/_adapter.d.mts +33 -0
  66. package/api/integration/_adapter.mjs +58 -0
  67. package/api/integration/authoring-checks.mjs +100 -5
  68. package/api/integration/authoring-checks.test.mjs +769 -0
  69. package/api/integration/authoring-checks.type.d.mts +134 -0
  70. package/api/integration/authoring-checks.type.mjs +60 -1
  71. package/api/integration/integrationCheck.doc.mjs +1 -1
  72. package/api/integration/integrationComponentConflicts.doc.mjs +11 -3
  73. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  74. package/api/integration/pack-check.mjs +303 -13
  75. package/api/integration/pack-check.test.mjs +371 -10
  76. package/api/integration/validate-integration-fixes.test.mjs +67 -0
  77. package/api/integration/validate-integration.d.mts +8 -0
  78. package/api/integration/validate-integration.mjs +55 -9
  79. package/api/integration/validate-integration.test.mjs +77 -8
  80. package/api/integration/validate-integration.type.d.mts +8 -0
  81. package/api/integration/validate-integration.type.mjs +3 -1
  82. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  83. package/api/integration/validateIntegration.doc.mjs +4 -2
  84. package/api/search/_adapter.d.mts +11 -0
  85. package/api/search/_adapter.mjs +25 -0
  86. package/api/search/search.d.mts +73 -13
  87. package/api/search/search.doc.mjs +8 -3
  88. package/api/search/search.domain-priority.test.mjs +108 -18
  89. package/api/search/search.mjs +541 -52
  90. package/api/search/search.test.mjs +143 -1
  91. package/api/search/search.type.d.mts +14 -1
  92. package/api/search/search.type.mjs +6 -1
  93. package/api/swizzle/_adapter.mjs +2 -2
  94. package/api/swizzle/copy/copy.mjs +1 -1
  95. package/api/template/template-integration.test.mjs +1 -1
  96. package/api/theme/_adapter.d.mts +16 -0
  97. package/api/theme/_adapter.mjs +32 -5
  98. package/api/theme/build/build.d.mts +2 -1
  99. package/api/theme/build/build.mjs +70 -14
  100. package/api/theme/build/build.packed-old-core.test.mjs +20 -3
  101. package/api/theme/build/font-warning.mjs +5 -3
  102. package/api/theme/build/font-warning.test.mjs +2 -1
  103. package/api/theme/remove/remove.test.mjs +2 -2
  104. package/api/theme/targets/targets.mjs +3 -10
  105. package/api/theme/themeTargets.doc.mjs +4 -0
  106. package/api/theme/use/use.test.mjs +1 -1
  107. package/api/upgrade/_adapter.d.mts +40 -2
  108. package/api/upgrade/_adapter.mjs +118 -5
  109. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  110. package/api/upgrade/run/run.mjs +35 -2
  111. package/api/upgrade/status/status.d.mts +21 -5
  112. package/api/upgrade/status/status.mjs +45 -8
  113. package/api/upgrade/upgrade.doc.mjs +6 -3
  114. package/api/upgrade/upgrade.mjs +5 -1
  115. package/api/upgrade/upgrade.type.d.mts +23 -0
  116. package/api/upgrade/upgrade.type.mjs +16 -1
  117. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  118. package/assets/codemods/registry.mjs +1 -0
  119. package/assets/codemods/runner.mjs +7 -1
  120. package/assets/codemods/transforms/next/index.mjs +1 -11
  121. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  122. package/assets/discover/official-packages.json +367 -0
  123. package/assets/docs/author-a-theme.doc.mjs +2 -2
  124. package/assets/docs/browser-support.doc.mjs +1 -1
  125. package/assets/docs/getting-started.doc.mjs +23 -3
  126. package/assets/docs/styling-overview.doc.mjs +1 -1
  127. package/assets/docs/theme.doc.mjs +1 -1
  128. package/assets/docs/tree/add-a-component.doc.mjs +12 -2
  129. package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
  130. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  131. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  132. package/assets/docs/tree/block-template.doc.mjs +6 -18
  133. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  134. package/assets/docs/tree/building-blocks.doc.mjs +4 -0
  135. package/assets/docs/tree/check-the-props.doc.mjs +8 -3
  136. package/assets/docs/tree/check-your-docs.doc.mjs +30 -13
  137. package/assets/docs/tree/checks.doc.mjs +17 -17
  138. package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
  139. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  140. package/assets/docs/tree/cli.doc.mjs +6 -0
  141. package/assets/docs/tree/codemods.doc.mjs +17 -7
  142. package/assets/docs/tree/commands.doc.mjs +7 -1
  143. package/assets/docs/tree/component-family.doc.mjs +3 -5
  144. package/assets/docs/tree/component-imports.doc.mjs +13 -3
  145. package/assets/docs/tree/components.doc.mjs +7 -1
  146. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  147. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  148. package/assets/docs/tree/configuration.doc.mjs +7 -3
  149. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  150. package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
  151. package/assets/docs/tree/describe-the-component.doc.mjs +2 -2
  152. package/assets/docs/tree/docs.doc.mjs +9 -3
  153. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  154. package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
  155. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  156. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  157. package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
  158. package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
  159. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  160. package/assets/docs/tree/global.doc.mjs +131 -0
  161. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  162. package/assets/docs/tree/install-once.doc.mjs +105 -0
  163. package/assets/docs/tree/integrations.doc.mjs +13 -1
  164. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  165. package/assets/docs/tree/layout.doc.mjs +6 -6
  166. package/assets/docs/tree/links.doc.mjs +6 -5
  167. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  168. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  169. package/assets/docs/tree/migration.doc.mjs +0 -1
  170. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  171. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  172. package/assets/docs/tree/page-template.doc.mjs +3 -7
  173. package/assets/docs/tree/problems.doc.mjs +205 -0
  174. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  175. package/assets/docs/tree/publishing.doc.mjs +6 -6
  176. package/assets/docs/tree/quick-start.doc.mjs +52 -26
  177. package/assets/docs/tree/reference.doc.mjs +192 -0
  178. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  179. package/assets/docs/tree/replace-a-core-template.doc.mjs +9 -11
  180. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  181. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  182. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  183. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  184. package/assets/docs/tree/single-component.doc.mjs +14 -6
  185. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  186. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  187. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  188. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  189. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  190. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  191. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  192. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  193. package/assets/docs/tree/templates.doc.mjs +7 -1
  194. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  195. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  196. package/assets/docs/tree/themes.doc.mjs +4 -0
  197. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  198. package/assets/docs/tree/troubleshooting.doc.mjs +22 -14
  199. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  200. package/assets/docs/tree/updates.doc.mjs +92 -0
  201. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  202. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
  203. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  204. package/assets/docs/tree/versioning.doc.mjs +9 -9
  205. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  206. package/assets/docs/tree/write-the-template-file.doc.mjs +5 -5
  207. package/assets/docs/working-with-ai.doc.mjs +23 -9
  208. package/authoring/codemod/codemod.doc.mjs +7 -3
  209. package/authoring/config/config.doc.mjs +9 -6
  210. package/authoring/config/type.ts +4 -2
  211. package/authoring/debug/parse.d.mts +5 -5
  212. package/authoring/discover/discover.doc.mjs +7 -1
  213. package/authoring/doctypes/_schema.d.mts +8 -3
  214. package/authoring/doctypes/_schema.mjs +1 -0
  215. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  216. package/authoring/doctypes/command/command.doc.mjs +20 -12
  217. package/authoring/doctypes/command/type.ts +14 -0
  218. package/authoring/doctypes/component/component.doc.mjs +29 -26
  219. package/authoring/doctypes/component/type.ts +15 -5
  220. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  221. package/authoring/doctypes/function/function.doc.mjs +9 -8
  222. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  223. package/authoring/doctypes/hook/type.ts +4 -0
  224. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  225. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  226. package/authoring/doctypes/schema/schema.doc.mjs +9 -9
  227. package/authoring/doctypes/template/template.doc.mjs +2 -2
  228. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  229. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  230. package/authoring/identity/identity.doc.mjs +3 -3
  231. package/authoring/index.d.ts +1 -0
  232. package/authoring/integration/integration.doc.mjs +22 -5
  233. package/authoring/integration/parse.test.mjs +11 -0
  234. package/authoring/integration/schema.d.mts +14 -3
  235. package/authoring/integration/schema.mjs +33 -2
  236. package/authoring/integration/type.ts +8 -0
  237. package/clients/cli/bin/astryx.mjs +20 -3
  238. package/clients/cli/cli-command.test.mjs +166 -0
  239. package/clients/cli/commands/blog.doc.mjs +1 -0
  240. package/clients/cli/commands/build-theme.batch-report.test.mjs +14 -2
  241. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  242. package/clients/cli/commands/build-theme.mjs +25 -12
  243. package/clients/cli/commands/build.doc.mjs +1 -0
  244. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  245. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  246. package/clients/cli/commands/component.doc.mjs +1 -0
  247. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  248. package/clients/cli/commands/discover.doc.mjs +9 -1
  249. package/clients/cli/commands/discover.mjs +144 -93
  250. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  251. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  252. package/clients/cli/commands/docs.doc.mjs +1 -0
  253. package/clients/cli/commands/docs.mjs +49 -19
  254. package/clients/cli/commands/docs.test.mjs +2 -2
  255. package/clients/cli/commands/doctor-integration-components.doc.mjs +7 -3
  256. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  257. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  258. package/clients/cli/commands/doctor-integration-validate.doc.mjs +13 -2
  259. package/clients/cli/commands/doctor-integration.test.mjs +52 -4
  260. package/clients/cli/commands/doctor.doc.mjs +12 -2
  261. package/clients/cli/commands/doctor.mjs +102 -7
  262. package/clients/cli/commands/doctor.test.mjs +10 -4
  263. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  264. package/clients/cli/commands/gap-report.mjs +24 -2
  265. package/clients/cli/commands/gap-report.test.mjs +79 -0
  266. package/clients/cli/commands/hook.doc.mjs +1 -0
  267. package/clients/cli/commands/init.behavior.test.mjs +5 -0
  268. package/clients/cli/commands/init.doc.mjs +29 -3
  269. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  270. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  271. package/clients/cli/commands/integration-check.doc.mjs +10 -2
  272. package/clients/cli/commands/integration-check.test.mjs +175 -1
  273. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  274. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  275. package/clients/cli/commands/integration.mjs +15 -9
  276. package/clients/cli/commands/json-contract.test.mjs +11 -2
  277. package/clients/cli/commands/manifest.doc.mjs +1 -0
  278. package/clients/cli/commands/outside-project.test.mjs +774 -0
  279. package/clients/cli/commands/search.doc.mjs +1 -0
  280. package/clients/cli/commands/search.mjs +16 -11
  281. package/clients/cli/commands/search.test.mjs +429 -296
  282. package/clients/cli/commands/setup-nudge.test.mjs +102 -2
  283. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  284. package/clients/cli/commands/swizzle.mjs +5 -3
  285. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  286. package/clients/cli/commands/template.doc.mjs +1 -0
  287. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  288. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  289. package/clients/cli/commands/theme-build.doc.mjs +1 -0
  290. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  291. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  292. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  293. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  294. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  295. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  296. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  297. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  298. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  299. package/clients/cli/commands/upgrade.doc.mjs +22 -1
  300. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  301. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  302. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  303. package/clients/cli/index.mjs +111 -16
  304. package/clients/cli/lib/cli-error.mjs +4 -1
  305. package/clients/cli/lib/component-format.test.mjs +1 -1
  306. package/clients/cli/lib/define-command.mjs +2 -2
  307. package/clients/cli/lib/json-shim.mjs +3 -1
  308. package/clients/cli/lib/manifest.d.ts +9 -0
  309. package/clients/cli/lib/manifest.mjs +17 -1
  310. package/clients/cli/lib/manifest.test.mjs +25 -0
  311. package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
  312. package/foundation/agent-docs/agent-doc-state.mjs +66 -6
  313. package/foundation/agent-docs/agent-docs.d.mts +4 -3
  314. package/foundation/agent-docs/agent-docs.mjs +11 -9
  315. package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
  316. package/foundation/agent-docs/computer-agent-text.mjs +623 -0
  317. package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
  318. package/foundation/config/project.d.mts +35 -3
  319. package/foundation/config/project.mjs +145 -8
  320. package/foundation/config/project.test.mjs +66 -0
  321. package/foundation/config/theme-state.mjs +5 -4
  322. package/foundation/discovery/authoring-self-docs.mjs +1 -1
  323. package/foundation/discovery/cli-self-docs.mjs +20 -3
  324. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  325. package/foundation/discovery/component-replacement.mjs +2 -1
  326. package/foundation/discovery/copied-passages.d.mts +216 -0
  327. package/foundation/discovery/copied-passages.mjs +720 -0
  328. package/foundation/discovery/copied-passages.test.mjs +124 -0
  329. package/foundation/discovery/doc-consistency.d.mts +34 -0
  330. package/foundation/discovery/doc-consistency.mjs +513 -0
  331. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  332. package/foundation/discovery/doc-fluff.d.mts +112 -0
  333. package/foundation/discovery/doc-fluff.mjs +328 -0
  334. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  335. package/foundation/discovery/doc-types.d.mts +1 -1
  336. package/foundation/discovery/doc-types.mjs +15 -8
  337. package/foundation/discovery/doc-types.test.mjs +94 -2
  338. package/foundation/discovery/docs-discovery.d.mts +7 -0
  339. package/foundation/discovery/docs-discovery.mjs +26 -2
  340. package/foundation/discovery/project-typescript.d.mts +11 -2
  341. package/foundation/discovery/project-typescript.mjs +32 -4
  342. package/foundation/discovery/prop-drift.d.mts +26 -7
  343. package/foundation/discovery/prop-drift.mjs +173 -8
  344. package/foundation/discovery/prop-drift.test.mjs +120 -2
  345. package/foundation/discovery/runner-allowlist.d.mts +40 -0
  346. package/foundation/discovery/runner-allowlist.mjs +53 -0
  347. package/foundation/discovery/stray-pointers.d.mts +52 -0
  348. package/foundation/discovery/stray-pointers.mjs +293 -0
  349. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  350. package/foundation/discovery/template-needs.mjs +5 -2
  351. package/foundation/discovery/theme-imports.mjs +8 -4
  352. package/foundation/discovery/theme-imports.test.mjs +1 -1
  353. package/foundation/discovery/type-text.mjs +1 -1
  354. package/foundation/discovery/type-text.test.mjs +1 -1
  355. package/foundation/doc-compiler/doc-loads.test.mjs +42 -2
  356. package/foundation/doc-compiler/inputs.mjs +4 -1
  357. package/foundation/doc-compiler/links.d.mts +32 -0
  358. package/foundation/doc-compiler/links.mjs +163 -26
  359. package/foundation/doc-compiler/links.test.mjs +97 -4
  360. package/foundation/doc-compiler/read.d.mts +1 -1
  361. package/foundation/doc-compiler/tree.mjs +30 -1
  362. package/foundation/doc-compiler/tree.test.mjs +8 -1
  363. package/foundation/env/cli-command.d.mts +83 -0
  364. package/foundation/env/cli-command.mjs +152 -0
  365. package/foundation/env/cli-command.test.mjs +129 -0
  366. package/foundation/env/node-version.test.mjs +15 -3
  367. package/foundation/env/package-manager.d.mts +93 -9
  368. package/foundation/env/package-manager.global.test.mjs +66 -0
  369. package/foundation/env/package-manager.mjs +184 -13
  370. package/foundation/env/package-manager.test.mjs +341 -15
  371. package/foundation/env/project-scope.d.mts +9 -0
  372. package/foundation/env/project-scope.mjs +33 -0
  373. package/foundation/env/search-path.d.mts +42 -0
  374. package/foundation/env/search-path.mjs +205 -0
  375. package/foundation/env/search-path.test.mjs +122 -0
  376. package/foundation/env/user-dirs.d.mts +39 -0
  377. package/foundation/env/user-dirs.mjs +93 -0
  378. package/foundation/env/user-dirs.test.mjs +72 -0
  379. package/foundation/env/user-settings.d.mts +46 -0
  380. package/foundation/env/user-settings.mjs +106 -0
  381. package/foundation/env/user-settings.test.mjs +64 -0
  382. package/foundation/fs/file-protection.mjs +15 -1
  383. package/foundation/fs/module-loader.d.mts +2 -1
  384. package/foundation/fs/module-loader.mjs +60 -4
  385. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  386. package/foundation/fs/module-loader.test.mjs +194 -0
  387. package/foundation/fs/path-compare.d.mts +33 -0
  388. package/foundation/fs/path-compare.mjs +73 -0
  389. package/foundation/fs/paths.d.mts +57 -1
  390. package/foundation/fs/paths.mjs +131 -3
  391. package/foundation/fs/paths.test.mjs +10 -1
  392. package/foundation/integrations/computer-integrations.d.mts +78 -0
  393. package/foundation/integrations/computer-integrations.mjs +316 -0
  394. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  395. package/foundation/integrations/contribution-inventory.d.mts +11 -0
  396. package/foundation/integrations/contribution-inventory.mjs +50 -2
  397. package/foundation/integrations/integration-warnings.mjs +3 -2
  398. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  399. package/foundation/integrations/integrations.d.mts +25 -1
  400. package/foundation/integrations/integrations.mjs +46 -3
  401. package/foundation/integrations/issue.ts +6 -0
  402. package/foundation/integrations/validate-contributions.d.mts +2 -0
  403. package/foundation/integrations/validate-contributions.mjs +41 -1
  404. package/foundation/release/agent-text-worker.d.mts +4 -0
  405. package/foundation/release/agent-text-worker.mjs +52 -0
  406. package/foundation/release/cache.d.mts +310 -0
  407. package/foundation/release/cache.mjs +1216 -0
  408. package/foundation/release/cache.test.mjs +920 -0
  409. package/foundation/release/choose.d.mts +207 -0
  410. package/foundation/release/choose.mjs +677 -0
  411. package/foundation/release/choose.test.mjs +427 -0
  412. package/foundation/release/core-worker.d.mts +4 -0
  413. package/foundation/release/core-worker.mjs +38 -0
  414. package/foundation/release/global-state.d.mts +259 -0
  415. package/foundation/release/global-state.mjs +472 -0
  416. package/foundation/release/global-state.test.mjs +381 -0
  417. package/foundation/release/handoff.d.mts +60 -0
  418. package/foundation/release/handoff.e2e.test.mjs +278 -0
  419. package/foundation/release/handoff.mjs +357 -0
  420. package/foundation/release/lock-lease.d.mts +23 -0
  421. package/foundation/release/lock-lease.mjs +80 -0
  422. package/foundation/release/notices.d.mts +253 -0
  423. package/foundation/release/notices.mjs +596 -0
  424. package/foundation/release/notices.test.mjs +565 -0
  425. package/foundation/release/npm-guard.d.mts +4 -0
  426. package/foundation/release/npm-guard.mjs +126 -0
  427. package/foundation/release/project.d.mts +141 -0
  428. package/foundation/release/project.mjs +466 -0
  429. package/foundation/release/project.test.mjs +288 -0
  430. package/foundation/release/refresh-worker.d.mts +4 -0
  431. package/foundation/release/refresh-worker.mjs +27 -0
  432. package/foundation/release/run-context.d.mts +47 -0
  433. package/foundation/release/run-context.mjs +149 -0
  434. package/foundation/release/update-notice-env.d.mts +28 -0
  435. package/foundation/release/update-notice-env.mjs +39 -0
  436. package/foundation/response/base.d.ts +26 -3
  437. package/foundation/response/error-codes.d.mts +3 -1
  438. package/foundation/response/error-codes.doc.mjs +12 -0
  439. package/foundation/response/error-codes.mjs +17 -0
  440. package/foundation/response/error-codes.test.mjs +2 -0
  441. package/foundation/response/json-contract.test.mjs +7 -2
  442. package/foundation/response/json.mjs +4 -1
  443. package/foundation/response/response-types.doc.mjs +17 -11
  444. package/foundation/response/response-types.doc.test.mjs +46 -0
  445. package/foundation/response/response.doc.mjs +3 -3
  446. package/foundation/xle/browser-imports.test.mjs +74 -0
  447. package/package.json +11 -11
  448. package/scripts/postinstall.mjs +24 -5
  449. /package/assets/codemods/transforms/{next → v0.7.2}/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +0 -0
  450. /package/assets/codemods/transforms/{next → v0.7.2}/migrate-list-edge-compensation-to-edge.mjs +0 -0
@@ -16,6 +16,8 @@ export const doc = {
16
16
  'Reports a missing component, variant, layout, styling, accessibility, API, or documentation capability to the package that owns it: the --package you name, else the integration whose component replaces it, else the one package that provides the component, else Core. ' +
17
17
  'Every configured handler receives the report: the project config handler first, then each integration handler in config order. Public handlers run only with --confirm-public; internal handlers always run. A failing handler does not stop the others. ' +
18
18
  "With no handler it files a GitHub issue for the owning package, only with --confirm-public (without it nothing is sent), or returns the package's issues URL when that is not on GitHub. " +
19
+ "With --to <package>, the report goes only to that integration's issues URL instead, under the same --confirm-public rule. " +
20
+ 'When loaded integrations name their own issues URLs, the output lists every destination: an agent asks the person where to file and passes their choice with --to; it never picks a package itself, and without a choice the default is used. ' +
19
21
  'The report records whether an agent or a person ran it.',
20
22
  fn: 'gapReport',
21
23
  args: [
@@ -55,13 +57,19 @@ export const doc = {
55
57
  flag: '--confirm-public',
56
58
  param: 'options.confirmPublic',
57
59
  description:
58
- 'Allow public delivery: public handlers run, and with no handler it files a GitHub issue with your gh login',
60
+ 'Allow public delivery: public handlers run, and a GitHub issues URL gets an issue filed with your gh login',
61
+ },
62
+ {
63
+ flag: '--to <package>',
64
+ param: 'options.to',
65
+ description:
66
+ "Send the report only to this loaded integration's issues URL, as the person chose; the destinations the output lists are the choices",
59
67
  },
60
68
  {
61
69
  flag: '--list-categories',
62
70
  param: 'options.listCategories',
63
71
  description:
64
- 'List valid report categories without filing; the component and the other gap-report options are refused with ERR_INVALID_ARGUMENT',
72
+ 'List valid report categories, and the destinations when there is more than one, without filing; the component and the other gap-report options are refused with ERR_INVALID_ARGUMENT',
65
73
  },
66
74
  ],
67
75
  examples: [
@@ -70,7 +78,12 @@ export const doc = {
70
78
  label: 'Prepare a report (nothing public happens without --confirm-public)',
71
79
  cli: "astryx gap-report Button --category missing_variant --reason 'Need a compact size'",
72
80
  },
81
+ {
82
+ label: 'File where the person chose',
83
+ cli: "astryx gap-report Button --category missing_variant --reason 'Need a compact size' --to @acme/widgets",
84
+ },
73
85
  ],
86
+ outsideProject: 'same',
74
87
  exitCodes: [
75
88
  {
76
89
  code: 0,
@@ -7,7 +7,7 @@
7
7
  import {gapReport as gapReportApi} from '../../../api/gap-report/gap-report.mjs';
8
8
  import {NO_RESULT_SET, resultSet} from '../../../foundation/debug/index.mjs';
9
9
  import {jsonOut} from '../../../foundation/response/json.mjs';
10
- import {emit, record, records, section} from '../formatters/index.mjs';
10
+ import {emit, record, records, section, text} from '../formatters/index.mjs';
11
11
  import {cliError} from '../lib/cli-error.mjs';
12
12
  import {defineCommand} from '../lib/define-command.mjs';
13
13
  import {doc as gapReportCommand} from './gap-report.doc.mjs';
@@ -19,7 +19,7 @@ export function registerGapReport(program) {
19
19
  fn: gapReportFn,
20
20
  action: async (
21
21
  /** @type {string|undefined} */ component,
22
- /** @type {{category?: string, reason?: string, additionalContext?: string, package?: string, confirmPublic?: boolean, listCategories?: boolean}} */ options,
22
+ /** @type {{category?: string, reason?: string, additionalContext?: string, package?: string, confirmPublic?: boolean, listCategories?: boolean, to?: string}} */ options,
23
23
  ) => {
24
24
  /** @type {Awaited<ReturnType<typeof gapReportApi>>} */
25
25
  let result;
@@ -35,6 +35,7 @@ export function registerGapReport(program) {
35
35
  package: options.package,
36
36
  confirmPublic: options.confirmPublic,
37
37
  listCategories: options.listCategories,
38
+ to: options.to,
38
39
  });
39
40
  } catch (error) {
40
41
  const err =
@@ -78,6 +79,9 @@ export function registerGapReport(program) {
78
79
  section('Gap report categories'),
79
80
  records(result.data, {fields: ['value', 'label']}),
80
81
  );
82
+ if (result.meta) {
83
+ emit(...destinationBlocks(result.meta.destinations, result.meta.ask));
84
+ }
81
85
  return answered;
82
86
  }
83
87
 
@@ -119,8 +123,26 @@ export function registerGapReport(program) {
119
123
  );
120
124
  }
121
125
 
126
+ if (result.data.destinations && result.data.ask) {
127
+ emit(...destinationBlocks(result.data.destinations, result.data.ask));
128
+ }
129
+
122
130
  if (isFailure) process.exitCode = 1;
123
131
  return answered;
124
132
  },
125
133
  });
126
134
  }
135
+
136
+ /**
137
+ * The destinations a report can go to, then the line telling an agent to ask
138
+ * the person (architecture:cli-surface INV36).
139
+ * @param {import('../../../api/gap-report/gap-report.type.mjs').GapReportDestination[]} destinations
140
+ * @param {string} ask
141
+ */
142
+ function destinationBlocks(destinations, ask) {
143
+ return [
144
+ section('Destinations'),
145
+ records(destinations, {fields: ['to', 'default', 'issuesUrl']}),
146
+ text(ask),
147
+ ];
148
+ }
@@ -331,3 +331,82 @@ describe('gap-report control docs', () => {
331
331
  ).rejects.toMatchObject({code: 'ERR_INVALID_ARGUMENT'});
332
332
  });
333
333
  });
334
+
335
+ describe('gap-report destinations in text', () => {
336
+ it('lists the destinations and tells the agent to ask the person', async () => {
337
+ const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-gap-dest-'));
338
+ try {
339
+ fs.writeFileSync(
340
+ path.join(cwd, 'package.json'),
341
+ JSON.stringify({name: 'fixture-app'}),
342
+ );
343
+ const pkg = path.join(cwd, 'node_modules', '@test', 'widgets');
344
+ fs.mkdirSync(pkg, {recursive: true});
345
+ fs.writeFileSync(
346
+ path.join(pkg, 'package.json'),
347
+ JSON.stringify({name: '@test/widgets', version: '1.0.0'}),
348
+ );
349
+ fs.writeFileSync(
350
+ path.join(pkg, 'astryx.integration.mjs'),
351
+ "export default {issuesUrl: 'https://tracker.example/widgets'};\n",
352
+ );
353
+ fs.writeFileSync(
354
+ path.join(cwd, 'astryx.config.mjs'),
355
+ `export default {
356
+ integrations: ['@test/widgets'],
357
+ gapReport: {audience: 'internal', handle: () => ({status: 'filed', message: 'shared'})},
358
+ };\n`,
359
+ );
360
+
361
+ const listed = await runCli(['gap-report', '--list-categories'], {cwd});
362
+ expect(listed.status).toBe(0);
363
+ expect(listed.stdout).toContain('Destinations');
364
+ expect(listed.stdout).toMatch(/^default:\s+true$/m);
365
+ expect(listed.stdout).toMatch(/^to:\s+@test\/widgets$/m);
366
+ expect(listed.stdout).toMatch(
367
+ /^issuesUrl:\s+https:\/\/tracker\.example\/widgets$/m,
368
+ );
369
+ expect(listed.stdout).toMatch(/ask the person/i);
370
+
371
+ const filed = await runCli(
372
+ [
373
+ 'gap-report',
374
+ 'Button',
375
+ '--category',
376
+ 'docs_gap',
377
+ '--reason',
378
+ 'Need a keyboard example',
379
+ ],
380
+ {cwd},
381
+ );
382
+ expect(filed.status).toBe(0);
383
+ expect(filed.stdout).toContain('Destinations');
384
+ expect(filed.stdout).toMatch(/ask the person/i);
385
+
386
+ const chosen = await runCli(
387
+ [
388
+ 'gap-report',
389
+ 'Button',
390
+ '--category',
391
+ 'docs_gap',
392
+ '--reason',
393
+ 'Need a keyboard example',
394
+ '--to',
395
+ '@test/widgets',
396
+ '--json',
397
+ ],
398
+ {cwd},
399
+ );
400
+ expect(chosen.status).toBe(0);
401
+ expect(JSON.parse(chosen.stdout).data.deliveries).toEqual([
402
+ expect.objectContaining({
403
+ handler: 'issuesUrl',
404
+ status: 'routed_only',
405
+ url: 'https://tracker.example/widgets',
406
+ }),
407
+ ]);
408
+ } finally {
409
+ fs.rmSync(cwd, {recursive: true, force: true});
410
+ }
411
+ });
412
+ });
@@ -40,6 +40,7 @@ export const doc = {
40
40
  {label: 'Browse the catalog', cli: 'astryx hook --list'},
41
41
  {label: 'One hook as JSON', cli: 'astryx hook useFocusTrap --json'},
42
42
  ],
43
+ outsideProject: 'same',
43
44
  exitCodes: [
44
45
  {code: 0, when: 'success'},
45
46
  {
@@ -39,6 +39,11 @@ const exists = rel => fs.existsSync(path.join(tmpDir, rel));
39
39
 
40
40
  describe('astryx init — default (no flags)', () => {
41
41
  it('installs the tool-agnostic AGENTS.md cheat sheet and prints next steps', async () => {
42
+ // Inside a project; outside one the steps are left out (outside-project.test.mjs).
43
+ fs.writeFileSync(
44
+ path.join(tmpDir, 'package.json'),
45
+ '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}',
46
+ );
42
47
  const {status, stdout} = await runCli(['init'], {cwd: tmpDir});
43
48
  expect(status).toBe(0);
44
49
  expect(exists('AGENTS.md')).toBe(true);
@@ -19,7 +19,12 @@ export const doc = {
19
19
  'agents, and CI). By default it installs the AGENTS.md/CLAUDE.md agent-docs, ' +
20
20
  'including guidance from configured integrations, and prints getting-started ' +
21
21
  "steps. --features and --all print only the chosen features' guidance (no " +
22
- 'getting-started steps); the theme feature also writes an annotated theme template.',
22
+ 'getting-started steps); the theme feature also writes an annotated theme template. ' +
23
+ 'Outside a project it writes the same files but prints no step that sets up a project: ' +
24
+ 'no getting-started steps, and no step that adds a theme to an app. ' +
25
+ '--user writes the computer-level agent text instead (see the flag), in any folder, and touches nothing in the folder. ' +
26
+ 'The CLI installed for the computer also keeps that text current in the background, unless --user --remove-agents turned it off; ' +
27
+ 'package install scripts, project setup, and upgrade never write it.',
23
28
  fn: 'init',
24
29
  options: [
25
30
  {
@@ -43,6 +48,18 @@ export const doc = {
43
48
  "(deleting AGENTS.md or .claude/CLAUDE.md when only init's heading is left) and do nothing else. " +
44
49
  '--features, --all, --agent and --agent-docs-path are refused; a file written with --agent-docs-path keeps its block',
45
50
  },
51
+ {
52
+ flag: '--user',
53
+ param: 'options.user',
54
+ description:
55
+ 'Write or refresh the computer-level agent text instead of setting up the folder: one skill file, ~/.agents/skills/astryx/SKILL.md, which most coding agents read, ' +
56
+ 'linked into the skill folders of agents that read only their own (~/.claude/skills always; Kiro, Windsurf, Letta, Xcode\'s coding assistant, and ~/.config/agents/skills when that folder exists): a folder symlink with a relative target, a junction on Windows, or a copy where neither can be made. Continue, whose scanner skips links, gets a managed copy, refreshed with the file. ' +
57
+ "It tells agents anywhere on the computer that Astryx is there, when it is relevant, and to start with `astryx search`. " +
58
+ 'Records the links it made in astryx/settings.json in the per-user configuration folder, so removal removes exactly those; the CLI installed for the computer refreshes the file in the background after each upgrade. ' +
59
+ 'Works in any folder. A file without the Astryx markers, one edited since Astryx wrote it, or a symlink, is kept as it is, and so is anything at a link target that Astryx did not create. ' +
60
+ 'Warns, and still writes, when no `astryx` command on the computer runs the Astryx CLI. ' +
61
+ 'With --remove-agents it removes the file, the links, and the copy instead and records that the text is turned off. --features, --all, --agent and --agent-docs-path are refused',
62
+ },
46
63
  {
47
64
  flag: '--agent <tool>',
48
65
  param: 'options.agent',
@@ -51,7 +68,7 @@ export const doc = {
51
68
  'Target AI tool for agent docs: claude (CLAUDE.md or .claude/CLAUDE.md, else creates .claude/CLAUDE.md), cursor (.cursorrules if present, else AGENTS.md), ' +
52
69
  'codex and muse (AGENTS.md), hermes (.hermes.md or HERMES.md if present, else AGENTS.md), all (every existing agent doc, else AGENTS.md and .claude/CLAUDE.md). ' +
53
70
  'An unknown tool exits 1 with ERR_UNKNOWN_AGENT. ' +
54
- 'Used only when agent docs are installed (the default, --all, or --features agents); --agent-docs-path takes precedence',
71
+ 'Used only when agent docs are installed (the default, --all, or --features agents); --agent-docs-path takes precedence.',
55
72
  },
56
73
  {
57
74
  flag: '--agent-docs-path <path...>',
@@ -66,7 +83,10 @@ export const doc = {
66
83
  {label: 'Default setup', cli: 'astryx init'},
67
84
  {label: 'All features, no prompts', cli: 'astryx init --all'},
68
85
  {label: 'Machine-readable receipt', cli: 'astryx init --json'},
86
+ {label: 'Agent text for the whole computer', cli: 'astryx init --user'},
87
+ {label: 'Remove the computer-level agent text and turn it off', cli: 'astryx init --user --remove-agents'},
69
88
  ],
89
+ outsideProject: 'own',
70
90
  exitCodes: [
71
91
  {
72
92
  code: 0,
@@ -74,8 +94,14 @@ export const doc = {
74
94
  },
75
95
  {
76
96
  code: 1,
77
- when: 'an unknown --agent or feature, an --agent-docs-path outside the project, --remove-agents combined with install options, or --all with --features (ERR_INVALID_ARGUMENT)',
97
+ when: 'an unknown --agent (ERR_UNKNOWN_AGENT) or feature, an --agent-docs-path outside the project, --remove-agents combined with install options, --user combined with --features, --all, --agent or --agent-docs-path, or --all with --features (ERR_INVALID_ARGUMENT)',
78
98
  },
79
99
  ],
80
100
  related: ['doctor', 'upgrade', 'build', 'theme'],
101
+ notes: [
102
+ {
103
+ type: 'prose',
104
+ text: "In global mode: outside a project, init writes the agent docs (AGENTS.md) into the folder and prints no getting-started steps. `init --user` writes the agent guide for your computer, in any folder, and is never handed to a project's own CLI. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:computer-agent-guide}.",
105
+ },
106
+ ],
81
107
  };
@@ -113,6 +113,7 @@ export const doc = {
113
113
  cli: 'astryx integration add theme ocean --from neutral',
114
114
  },
115
115
  ],
116
+ outsideProject: 'refuse',
116
117
  exitCodes: [
117
118
  {code: 0, when: 'the contribution is written or the dry run succeeds'},
118
119
  {
@@ -121,4 +122,10 @@ export const doc = {
121
122
  },
122
123
  ],
123
124
  related: ['integration verify', 'doctor integration validate', 'theme add'],
125
+ notes: [
126
+ {
127
+ type: 'prose',
128
+ text: "In global mode: outside a package, integration add writes nothing and stops with `ERR_FILE_NOT_FOUND`: \"No package.json found. Run this command inside an integration package.\" In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:global-integrations}.",
129
+ },
130
+ ],
124
131
  };
@@ -147,6 +147,52 @@ describe('integration authoring CLI', () => {
147
147
  );
148
148
  });
149
149
 
150
+ it("verify carries each issue's fix, file, and line in JSON and prints them in text", async () => {
151
+ fs.writeFileSync(
152
+ path.join(tmpDir, 'package.json'),
153
+ `${JSON.stringify({
154
+ name: '@acme/widgets',
155
+ version: '1.0.0',
156
+ files: ['astryx.integration.mjs', 'docs'],
157
+ })}\n`,
158
+ );
159
+ fs.writeFileSync(
160
+ path.join(tmpDir, 'astryx.integration.mjs'),
161
+ "export default {docs: './docs'};\n",
162
+ );
163
+ fs.mkdirSync(path.join(tmpDir, 'docs'));
164
+ fs.writeFileSync(
165
+ path.join(tmpDir, 'docs', 'deploying.doc.mjs'),
166
+ "export const docs = {type: 'generic', name: 'deploying', title: 'Deploying', description: 'How to deploy.', sections: [{title: 'Overview', content: [{type: 'prose', text: 'Ship it.'}]}]};\n",
167
+ );
168
+ fs.writeFileSync(
169
+ path.join(tmpDir, 'docs', 'ghost.doc.zh.mjs'),
170
+ "export default {title: 'ghost'};\n",
171
+ );
172
+
173
+ const json = parseEnvelope(
174
+ (await runCli(['integration', 'verify', '--json'], tmpDir)).stdout,
175
+ );
176
+ const orphans = json.data.issues.filter(issue =>
177
+ issue.code.endsWith('orphan_doc_overlay'),
178
+ );
179
+ expect(orphans.map(issue => issue.code).sort()).toEqual([
180
+ 'orphan_doc_overlay',
181
+ 'packed_orphan_doc_overlay',
182
+ ]);
183
+ for (const issue of orphans) {
184
+ expect(issue).toMatchObject({
185
+ file: 'docs/ghost.doc.zh.mjs',
186
+ line: 1,
187
+ fix: expect.stringContaining('Delete docs/ghost.doc.zh.mjs'),
188
+ });
189
+ }
190
+
191
+ const text = (await runCli(['integration', 'verify'], tmpDir)).stdout;
192
+ expect(text).toContain('file: docs/ghost.doc.zh.mjs:1');
193
+ expect(text).toContain(`fix: ${orphans[0].fix}`);
194
+ });
195
+
150
196
  it('keeps `integration pack --check` as a deprecated alias of `integration verify`', async () => {
151
197
  // The old spelling runs the same check: the same JSON, the same exit code.
152
198
  const verify = await runCli(['integration', 'verify', '--json'], tmpDir);
@@ -173,7 +219,7 @@ describe('integration authoring CLI', () => {
173
219
  expect(text.status).toBe(verifyText.status);
174
220
  expect(text.stdout).toBe(verifyText.stdout);
175
221
  expect(text.stderr).toContain('`integration pack --check` is deprecated');
176
- expect(text.stderr).toContain('astryx integration verify');
222
+ expect(text.stderr).toContain(' integration verify`');
177
223
  // Without --check it fails, as it did, and points only at the new name:
178
224
  // suggesting `--check` would send people to the deprecated spelling.
179
225
  const bare = await runCli(['integration', 'pack'], tmpDir);
@@ -181,13 +227,13 @@ describe('integration authoring CLI', () => {
181
227
  expect(bare.stderr).toContain(
182
228
  '`integration pack` is now `integration verify`',
183
229
  );
184
- expect(bare.stderr).toContain('astryx integration verify');
230
+ expect(bare.stderr).toContain(' integration verify`');
185
231
  expect(bare.stderr).toContain('npm pack');
186
232
  expect(bare.stderr).not.toContain('--check');
187
233
  const bareJson = await runCli(['--json', 'integration', 'pack'], tmpDir);
188
234
  expect(parseEnvelope(bareJson.stdout)).toMatchObject({
189
235
  code: 'ERR_INVALID_ARGUMENT',
190
- error: expect.stringContaining('astryx integration verify'),
236
+ error: expect.stringContaining(' integration verify`'),
191
237
  });
192
238
  // Help lists it, marked deprecated: nothing is hidden.
193
239
  const help = await runCli(['integration', '--help'], tmpDir);
@@ -35,14 +35,15 @@ export const doc = {
35
35
  '`integration check` on every build; run ' +
36
36
  '`integration verify` before you publish, to check that the packed package ' +
37
37
  'works in an app. To check an installed integration by name, run the ' +
38
- '`doctor integration` subcommands with its package name.',
38
+ '`doctor integration` subcommands with its package name. Outside a package, ' +
39
+ 'it writes nothing, `validate` reports one `no_package` issue, and it exits 1.',
39
40
  fn: 'integrationCheck',
40
41
  options: [
41
42
  {
42
43
  flag: '--strict',
43
44
  param: 'options.strict',
44
45
  description:
45
- 'Also exit 1 on any warning and on any check that did not run. A new check or failure code joins only in a minor release, named in the release notes.',
46
+ 'Also exit 1 on any warning and on any check that did not run. A new check or failure code joins only in a minor release, named in the release notes; until then, a malformed `cliCommand` is reported as a note (`invalid_cli_command`) that fails nothing.',
46
47
  },
47
48
  ],
48
49
  examples: [
@@ -65,6 +66,7 @@ export const doc = {
65
66
  cli: 'integration verify',
66
67
  },
67
68
  ],
69
+ outsideProject: 'own',
68
70
  exitCodes: [
69
71
  {
70
72
  code: 0,
@@ -82,4 +84,10 @@ export const doc = {
82
84
  'doctor integration templates',
83
85
  'doctor integration docs',
84
86
  ],
87
+ notes: [
88
+ {
89
+ type: 'prose',
90
+ text: "In global mode: outside a package, it writes nothing, its `validate` check reports one `no_package` issue, and it exits 1. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:global-integrations}.",
91
+ },
92
+ ],
85
93
  };
@@ -117,6 +117,23 @@ describe('astryx integration check', () => {
117
117
  expect(run.status).toBe(1);
118
118
  });
119
119
 
120
+ it('--strict prints each finding once: its message above, its code in the failing list', async () => {
121
+ const id = await coreTemplateId();
122
+ writePackage({id});
123
+
124
+ const run = await runCli(['integration', 'check', '--strict'], tmpDir);
125
+ const json = await runCli(
126
+ ['integration', 'check', '--strict', '--json'],
127
+ tmpDir,
128
+ );
129
+ const [failure] = JSON.parse(json.stdout.trim()).data.failures;
130
+
131
+ expect(run.stdout.split(failure.message).length - 1).toBe(1);
132
+ expect(
133
+ run.stdout.slice(run.stdout.indexOf('Failing under --strict')),
134
+ ).toContain('template_id_conflict');
135
+ });
136
+
120
137
  it('--json carries each check with its own envelope, the --strict failures, and exits as the text does', async () => {
121
138
  const id = await coreTemplateId();
122
139
  writePackage({id});
@@ -248,13 +265,43 @@ describe('astryx integration check', () => {
248
265
  '"typecheck": "tsc --noEmit && astryx integration check --strict"',
249
266
  );
250
267
  expect(run.stdout).toContain(
251
- 'A new check or failure code joins only in a minor release, named in the release notes.',
268
+ 'A new check or failure code joins only in a minor release, named in the release notes; until then, a malformed `cliCommand` is reported as a note (`invalid_cli_command`) that fails nothing.',
252
269
  );
253
270
  expect(run.stdout).toContain('integration verify');
254
271
  expect(run.stdout).toContain('against the package in the current folder');
255
272
  expect(run.stdout).not.toContain('[package]');
256
273
  });
257
274
 
275
+ it('reports a malformed cliCommand as a note beside the issues, which --strict does not fail', async () => {
276
+ // A unique template id, so nothing else warns.
277
+ writePackage({
278
+ id: 'acme-notes-only-fixture',
279
+ extraManifest: ", cliCommand: ' acme astryx\\n'",
280
+ });
281
+
282
+ const json = await runCli(
283
+ ['--json', 'integration', 'check', '--strict'],
284
+ tmpDir,
285
+ );
286
+ const envelope = JSON.parse(json.stdout);
287
+ const validate = envelope.data.checks[0].response.data;
288
+ expect(validate.issues.map((/** @type {any} */ i) => i.code)).not.toContain(
289
+ 'invalid_cli_command',
290
+ );
291
+ expect(validate.notes).toEqual([
292
+ {code: 'invalid_cli_command', message: expect.any(String)},
293
+ ]);
294
+ expect(envelope.data.failed).toBe(false);
295
+ expect(json.status).toBe(0);
296
+
297
+ const text = await runCli(['integration', 'check'], tmpDir);
298
+ expect(
299
+ text.stdout
300
+ .split('\n')
301
+ .filter(line => line.startsWith('note (invalid_cli_command): ')),
302
+ ).toHaveLength(1);
303
+ });
304
+
258
305
  it('takes no package name: one passed is an error, not a check of the current folder', async () => {
259
306
  writePackage({id: 'acme-page'});
260
307
 
@@ -265,3 +312,130 @@ describe('astryx integration check', () => {
265
312
  expect(run.status).toBe(1);
266
313
  });
267
314
  });
315
+
316
+ describe('a copied passage', () => {
317
+ const passage =
318
+ 'Themes cannot style the layer that holds a menu or a popover, so a menu ' +
319
+ 'keeps the default surface color until the next release adds a token for it.';
320
+
321
+ function writeCopiedDocs() {
322
+ fs.writeFileSync(
323
+ path.join(tmpDir, 'package.json'),
324
+ JSON.stringify({name: '@acme/widgets', version: '1.2.3'}),
325
+ );
326
+ fs.writeFileSync(
327
+ path.join(tmpDir, 'astryx.integration.mjs'),
328
+ `export default {docs: './docs'};\n`,
329
+ );
330
+ fs.mkdirSync(path.join(tmpDir, 'docs'));
331
+ for (const name of ['acme-setup', 'acme-menus']) {
332
+ const doc = {
333
+ type: 'generic',
334
+ name,
335
+ title: 'Fixture',
336
+ description: 'Fixture topic.',
337
+ sections: [
338
+ {title: 'Overview', content: [{type: 'prose', text: passage}]},
339
+ ],
340
+ };
341
+ fs.writeFileSync(
342
+ path.join(tmpDir, 'docs', `${name}.doc.mjs`),
343
+ `export default ${JSON.stringify(doc)};\n`,
344
+ );
345
+ }
346
+ }
347
+
348
+ it('keeps doctor integration docs at exit 0, and fails integration check --strict', async () => {
349
+ writeCopiedDocs();
350
+
351
+ const doctor = await runCli(['doctor', 'integration', 'docs'], tmpDir);
352
+ expect(doctor.status).toBe(0);
353
+ expect(doctor.stdout).toContain('1 copied passage(s)');
354
+
355
+ const loose = await runCli(['integration', 'check'], tmpDir);
356
+ expect(loose.status).toBe(0);
357
+
358
+ const strict = await runCli(['integration', 'check', '--strict'], tmpDir);
359
+ expect(strict.status).toBe(1);
360
+ expect(strict.stdout).toContain('copied_passage');
361
+ });
362
+ });
363
+
364
+ describe('a padding phrase', () => {
365
+ it('keeps doctor integration docs at exit 0, and fails integration check --strict', async () => {
366
+ fs.writeFileSync(
367
+ path.join(tmpDir, 'package.json'),
368
+ JSON.stringify({name: '@acme/widgets', version: '1.2.3'}),
369
+ );
370
+ fs.writeFileSync(
371
+ path.join(tmpDir, 'astryx.integration.mjs'),
372
+ `export default {docs: './docs'};\n`,
373
+ );
374
+ fs.mkdirSync(path.join(tmpDir, 'docs'));
375
+ const doc = {
376
+ type: 'generic',
377
+ name: 'acme-setup',
378
+ title: 'Fixture',
379
+ description: 'Fixture topic.',
380
+ sections: [
381
+ {
382
+ title: 'Overview',
383
+ content: [{type: 'prose', text: 'In order to start, run the setup.'}],
384
+ },
385
+ ],
386
+ };
387
+ fs.writeFileSync(
388
+ path.join(tmpDir, 'docs', 'acme-setup.doc.mjs'),
389
+ `export default ${JSON.stringify(doc)};\n`,
390
+ );
391
+
392
+ const doctor = await runCli(['doctor', 'integration', 'docs'], tmpDir);
393
+ expect(doctor.status).toBe(0);
394
+ expect(doctor.stdout).toContain('1 fluff finding(s)');
395
+
396
+ const strict = await runCli(['integration', 'check', '--strict'], tmpDir);
397
+ expect(strict.status).toBe(1);
398
+ expect(strict.stdout).toContain('doc_fluff');
399
+ });
400
+ });
401
+
402
+ describe('a stray doc pointer', () => {
403
+ it('keeps doctor integration docs at exit 0, and fails integration check --strict', async () => {
404
+ fs.writeFileSync(
405
+ path.join(tmpDir, 'package.json'),
406
+ JSON.stringify({name: '@acme/widgets', version: '1.2.3'}),
407
+ );
408
+ fs.writeFileSync(
409
+ path.join(tmpDir, 'astryx.integration.mjs'),
410
+ `export default {docs: './docs'};\n`,
411
+ );
412
+ fs.mkdirSync(path.join(tmpDir, 'docs'));
413
+ const doc = {
414
+ type: 'generic',
415
+ name: 'acme-setup',
416
+ title: 'Fixture',
417
+ description: 'Fixture topic.',
418
+ sections: [
419
+ {
420
+ title: 'Overview',
421
+ content: [
422
+ {type: 'prose', text: 'The theme is in `astryx docs theme`.'},
423
+ ],
424
+ },
425
+ ],
426
+ };
427
+ fs.writeFileSync(
428
+ path.join(tmpDir, 'docs', 'acme-setup.doc.mjs'),
429
+ `export default ${JSON.stringify(doc)};\n`,
430
+ );
431
+
432
+ const doctor = await runCli(['doctor', 'integration', 'docs'], tmpDir);
433
+ expect(doctor.status).toBe(0);
434
+ expect(doctor.stdout).toContain('1 stray doc pointer(s)');
435
+ expect(doctor.stdout).toContain('{@link @astryxdesign/cli:generic:theme}');
436
+
437
+ const strict = await runCli(['integration', 'check', '--strict'], tmpDir);
438
+ expect(strict.status).toBe(1);
439
+ expect(strict.stdout).toContain('stray_doc_pointer');
440
+ });
441
+ });
@@ -8,7 +8,7 @@ export const doc = {
8
8
  namespace: 'cli/commands',
9
9
  summary: 'Deprecated: the old name of `integration verify`',
10
10
  description:
11
- '`astryx integration pack --check` is the name this check had before {@link command:integration verify}. It still runs the same check, with the same output, JSON, and exit codes, and prints a note that names `integration verify`. It will be removed in a later release.',
11
+ '`astryx integration pack --check` is the name this check had before {@link command:integration verify}. It still runs the same check, with the same output, JSON, and exit codes, and prints a note that names `integration verify`. It will be removed in a later release. Outside a package it writes nothing and reports one failed check, no_package, naming the integration package it needs (exit 1).',
12
12
  fn: 'integrationPackCheck',
13
13
  options: [
14
14
  {
@@ -19,6 +19,7 @@ export const doc = {
19
19
  examples: [
20
20
  {label: 'The old spelling', cli: 'astryx integration pack --check'},
21
21
  ],
22
+ outsideProject: 'own',
22
23
  exitCodes: [
23
24
  {code: 0, when: 'the packed package exposes the same valid contributions'},
24
25
  {
@@ -27,4 +28,10 @@ export const doc = {
27
28
  },
28
29
  ],
29
30
  related: ['integration verify'],
31
+ notes: [
32
+ {
33
+ type: 'prose',
34
+ text: "In global mode: outside a package, `integration pack --check` writes nothing, reports one failed check, `no_package`, and exits 1. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:global-integrations}.",
35
+ },
36
+ ],
30
37
  };
@@ -8,15 +8,22 @@ export const doc = {
8
8
  namespace: 'cli/commands',
9
9
  summary: 'Check the package the way npm will publish it, before you publish',
10
10
  description:
11
- 'Packs the package with npm, unpacks the tarball into a temporary app without installing its dependencies, and checks that the app sees the same components, templates, themes, docs, and codemods as the package, that every public import resolves, and that the package declares a CLI new enough to read it. It publishes nothing and leaves no tarball behind. It runs the package\'s own pack lifecycle scripts, as `npm pack` does.',
11
+ 'Packs the package with npm, unpacks the tarball into a temporary app without installing its dependencies, and checks that the app sees the same components, templates, themes, docs, and codemods as the package, that every public import resolves, and that the package declares a CLI new enough to read it. It publishes nothing and leaves no tarball behind. It runs the package\'s own pack lifecycle scripts, as `npm pack` does. Outside a package it writes nothing and reports one failed check, no_package, naming the integration package it needs (exit 1).',
12
12
  fn: 'integrationPackCheck',
13
13
  examples: [
14
14
  {label: 'Check before publishing', cli: 'astryx integration verify'},
15
15
  {label: 'Machine-readable result', cli: 'astryx integration verify --json'},
16
16
  ],
17
+ outsideProject: 'own',
17
18
  exitCodes: [
18
19
  {code: 0, when: 'the packed package exposes the same valid contributions'},
19
20
  {code: 1, when: 'the tarball is incomplete or invalid'},
20
21
  ],
21
22
  related: ['integration add', 'doctor integration validate'],
23
+ notes: [
24
+ {
25
+ type: 'prose',
26
+ text: "In global mode: outside a package, it writes nothing, reports one failed check, `no_package`, and exits 1. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:global-integrations}.",
27
+ },
28
+ ],
22
29
  };