@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.3-canary.02f5fe4

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 (694) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +216 -162
  3. package/api/build/_adapter.d.mts +66 -0
  4. package/api/build/_adapter.mjs +139 -4
  5. package/api/build/blocks/blocks.d.mts +92 -0
  6. package/api/build/blocks/blocks.mjs +528 -0
  7. package/api/build/blocks/blocks.test.mjs +238 -0
  8. package/api/build/blocks/blocks.weights.json +1 -0
  9. package/api/build/build.doc.mjs +4 -0
  10. package/api/build/build.mjs +25 -6
  11. package/api/build/build.type.mjs +1 -1
  12. package/api/build/help/help.mjs +1 -1
  13. package/api/build/kit/answer.d.mts +18 -0
  14. package/api/build/kit/answer.mjs +195 -0
  15. package/api/build/kit/answer.test.mjs +108 -0
  16. package/api/build/kit/kind.d.mts +25 -0
  17. package/api/build/kit/kind.mjs +170 -0
  18. package/api/build/kit/kit.d.mts +2 -4
  19. package/api/build/kit/kit.mjs +8 -406
  20. package/api/build/kit/rank.d.mts +3 -32
  21. package/api/build/kit/rank.mjs +25 -342
  22. package/api/build/kit/rank.test.mjs +2 -1
  23. package/api/build/kit/signals.d.mts +79 -0
  24. package/api/build/kit/signals.mjs +295 -0
  25. package/api/build/kit/start.d.mts +32 -0
  26. package/api/build/kit/start.mjs +163 -0
  27. package/api/build/kit/words.d.mts +72 -0
  28. package/api/build/kit/words.mjs +202 -0
  29. package/api/build/tree.d.mts +20 -0
  30. package/api/build/tree.mjs +53 -0
  31. package/api/build/tree.test.mjs +185 -0
  32. package/api/build/tree.weights.json +1 -0
  33. package/api/component/_adapter.d.mts +72 -1
  34. package/api/component/_adapter.mjs +251 -23
  35. package/api/component/component-replacement.test.mjs +1 -0
  36. package/api/component/component.doc.mjs +6 -1
  37. package/api/component/component.mjs +97 -16
  38. package/api/component/component.test.mjs +95 -0
  39. package/api/component/doc-links.test.mjs +386 -0
  40. package/api/component/integration-export-name.test.mjs +644 -0
  41. package/api/component/list/list.mjs +42 -4
  42. package/api/discover/_adapter.d.mts +131 -12
  43. package/api/discover/_adapter.mjs +520 -34
  44. package/api/discover/_adapter.test.mjs +641 -17
  45. package/api/discover/_catalog-view.d.mts +16 -5
  46. package/api/discover/_catalog-view.mjs +32 -8
  47. package/api/discover/detail/doc/doc.mjs +9 -1
  48. package/api/discover/discover.d.mts +11 -0
  49. package/api/discover/discover.doc.mjs +9 -7
  50. package/api/discover/discover.mjs +120 -19
  51. package/api/discover/discover.type.d.mts +20 -7
  52. package/api/discover/discover.type.mjs +17 -7
  53. package/api/discover/list/list.d.mts +4 -3
  54. package/api/discover/list/list.mjs +17 -10
  55. package/api/docs/_adapter.d.mts +76 -2
  56. package/api/docs/_adapter.mjs +630 -34
  57. package/api/docs/docs-homes.test.mjs +127 -0
  58. package/api/docs/docs.doc.mjs +5 -4
  59. package/api/docs/docs.mjs +2 -1
  60. package/api/docs/docs.test.mjs +39 -20
  61. package/api/docs/integration-tree.test.mjs +42 -20
  62. package/api/docs/integrationDocs.test.mjs +125 -1
  63. package/api/docs/list/list.mjs +12 -2
  64. package/api/docs/namespace-section.test.mjs +6 -6
  65. package/api/docs/reference-blocks.test.mjs +3 -5
  66. package/api/doctor/_adapter.d.mts +128 -0
  67. package/api/doctor/_adapter.mjs +253 -4
  68. package/api/doctor/doctor.d.mts +217 -0
  69. package/api/doctor/doctor.doc.mjs +3 -2
  70. package/api/doctor/doctor.mjs +691 -52
  71. package/api/doctor/doctor.test.mjs +267 -18
  72. package/api/doctor/release-checks.test.mjs +156 -0
  73. package/api/doctor/theme-checks.mjs +17 -4
  74. package/api/doctor/theme-checks.test.mjs +223 -7
  75. package/api/error.d.mts +10 -0
  76. package/api/error.mjs +25 -0
  77. package/api/gap-report/gap-report.d.mts +3 -0
  78. package/api/gap-report/gap-report.doc.mjs +11 -3
  79. package/api/gap-report/gap-report.mjs +219 -52
  80. package/api/gap-report/gap-report.test.mjs +233 -0
  81. package/api/gap-report/gap-report.type.d.mts +41 -0
  82. package/api/gap-report/gap-report.type.mjs +18 -0
  83. package/api/hook/_adapter.mjs +3 -11
  84. package/api/hook/hook.doc.mjs +4 -0
  85. package/api/hook/hook.mjs +1 -1
  86. package/api/hook/list/list.d.mts +1 -1
  87. package/api/index.d.mts +2 -0
  88. package/api/index.mjs +2 -0
  89. package/api/init/_adapter.d.mts +22 -0
  90. package/api/init/_adapter.mjs +59 -0
  91. package/api/init/init.d.mts +7 -5
  92. package/api/init/init.doc.mjs +45 -10
  93. package/api/init/init.mjs +28 -4
  94. package/api/init/init.test.mjs +18 -2
  95. package/api/init/init.type.d.mts +50 -5
  96. package/api/init/init.type.mjs +39 -5
  97. package/api/init/remove/remove.mjs +17 -4
  98. package/api/init/remove/remove.test.mjs +114 -2
  99. package/api/init/run/run.d.mts +1 -1
  100. package/api/init/run/run.mjs +86 -12
  101. package/api/init/user/user.d.mts +14 -0
  102. package/api/init/user/user.mjs +87 -0
  103. package/api/init/user/user.test.mjs +232 -0
  104. package/api/integration/_adapter.d.mts +53 -0
  105. package/api/integration/_adapter.mjs +132 -0
  106. package/api/integration/add-contribution.component-names.test.mjs +66 -0
  107. package/api/integration/add-contribution.mjs +8 -4
  108. package/api/integration/add-contribution.test.mjs +4 -2
  109. package/api/integration/authoring-checks.mjs +192 -14
  110. package/api/integration/authoring-checks.test.mjs +1028 -0
  111. package/api/integration/authoring-checks.type.d.mts +143 -0
  112. package/api/integration/authoring-checks.type.mjs +74 -2
  113. package/api/integration/check/check.d.mts +96 -0
  114. package/api/integration/check/check.mjs +357 -0
  115. package/api/integration/check/check.test.mjs +489 -0
  116. package/api/integration/integration-check.type.d.mts +118 -0
  117. package/api/integration/integration-check.type.mjs +84 -0
  118. package/api/integration/integrationCheck.doc.d.mts +10 -0
  119. package/api/integration/integrationCheck.doc.mjs +73 -0
  120. package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
  121. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  122. package/api/integration/pack-check.mjs +486 -123
  123. package/api/integration/pack-check.test.mjs +817 -10
  124. package/api/integration/validate-integration-case-disk.test.mjs +111 -0
  125. package/api/integration/validate-integration-fixes.test.mjs +73 -5
  126. package/api/integration/validate-integration-gaps.test.mjs +1975 -0
  127. package/api/integration/validate-integration.d.mts +23 -2
  128. package/api/integration/validate-integration.mjs +358 -45
  129. package/api/integration/validate-integration.test.mjs +88 -8
  130. package/api/integration/validate-integration.type.d.mts +105 -0
  131. package/api/integration/validate-integration.type.mjs +79 -1
  132. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  133. package/api/integration/validateIntegration.doc.mjs +19 -3
  134. package/api/search/ORDERING.md +28 -0
  135. package/api/search/_adapter.d.mts +91 -0
  136. package/api/search/_adapter.mjs +172 -0
  137. package/api/search/_adapter.test.mjs +173 -0
  138. package/api/search/_candidate-score.d.mts +40 -0
  139. package/api/search/_candidate-score.mjs +238 -0
  140. package/api/search/_cards.json +6098 -0
  141. package/api/search/_compound.d.mts +50 -0
  142. package/api/search/_compound.mjs +170 -0
  143. package/api/search/_doc-searcher.d.mts +4 -0
  144. package/api/search/_doc-searcher.mjs +23 -0
  145. package/api/search/_doc-searcher.test.mjs +36 -0
  146. package/api/search/_doc-searcher.weights.json +1 -0
  147. package/api/search/_doc-text.d.mts +30 -0
  148. package/api/search/_doc-text.mjs +87 -0
  149. package/api/search/_entries.d.mts +63 -0
  150. package/api/search/_entries.mjs +232 -0
  151. package/api/search/_entries.test.mjs +48 -0
  152. package/api/search/_features.d.mts +35 -0
  153. package/api/search/_features.mjs +155 -0
  154. package/api/search/_gather-components.d.mts +26 -0
  155. package/api/search/_gather-components.mjs +284 -0
  156. package/api/search/_gather-docs.d.mts +20 -0
  157. package/api/search/_gather-docs.mjs +254 -0
  158. package/api/search/_gather-hooks.d.mts +12 -0
  159. package/api/search/_gather-hooks.mjs +52 -0
  160. package/api/search/_gather-templates.d.mts +25 -0
  161. package/api/search/_gather-templates.mjs +107 -0
  162. package/api/search/_lexical.d.mts +135 -0
  163. package/api/search/_lexical.mjs +351 -0
  164. package/api/search/_main-searcher.d.mts +19 -0
  165. package/api/search/_main-searcher.mjs +115 -0
  166. package/api/search/_main-searcher.test.mjs +106 -0
  167. package/api/search/_main-searcher.weights.json +1 -0
  168. package/api/search/_module-doc.d.mts +32 -0
  169. package/api/search/_module-doc.mjs +78 -0
  170. package/api/search/_order.d.mts +32 -0
  171. package/api/search/_order.mjs +162 -0
  172. package/api/search/_order.test.mjs +72 -0
  173. package/api/search/_priority.d.mts +50 -0
  174. package/api/search/_priority.mjs +139 -0
  175. package/api/search/_query-words.d.mts +25 -0
  176. package/api/search/_query-words.mjs +92 -0
  177. package/api/search/_query.d.mts +65 -0
  178. package/api/search/_query.mjs +176 -0
  179. package/api/search/_result.d.mts +97 -0
  180. package/api/search/_result.mjs +150 -0
  181. package/api/search/_score.d.mts +60 -0
  182. package/api/search/_score.mjs +283 -0
  183. package/api/search/_synonyms.d.mts +21 -0
  184. package/api/search/_synonyms.mjs +67 -0
  185. package/api/search/_template-searcher.d.mts +4 -0
  186. package/api/search/_template-searcher.mjs +23 -0
  187. package/api/search/_template-searcher.test.mjs +40 -0
  188. package/api/search/_template-searcher.weights.json +1 -0
  189. package/api/search/_titles.d.mts +33 -0
  190. package/api/search/_titles.mjs +65 -0
  191. package/api/search/_words.d.mts +64 -0
  192. package/api/search/_words.mjs +157 -0
  193. package/api/search/search.d.mts +22 -236
  194. package/api/search/search.doc.mjs +14 -7
  195. package/api/search/search.domain-priority.test.mjs +108 -18
  196. package/api/search/search.integration-check.test.mjs +24 -0
  197. package/api/search/search.mjs +59 -1904
  198. package/api/search/search.test.mjs +193 -15
  199. package/api/search/search.type.d.mts +20 -2
  200. package/api/search/search.type.mjs +12 -2
  201. package/api/search/tree.d.mts +15 -0
  202. package/api/search/tree.mjs +40 -0
  203. package/api/search/tree.test.mjs +66 -0
  204. package/api/search/tree.weights.json +1 -0
  205. package/api/swizzle/_adapter.mjs +2 -2
  206. package/api/swizzle/copy/copy.mjs +29 -15
  207. package/api/template/template-integration.test.mjs +1 -1
  208. package/api/template/template.mjs +5 -1
  209. package/api/template/template.test.mjs +120 -3
  210. package/api/theme/_adapter.d.mts +16 -0
  211. package/api/theme/_adapter.mjs +32 -5
  212. package/api/theme/build/build.d.mts +2 -1
  213. package/api/theme/build/build.family.test.mjs +64 -0
  214. package/api/theme/build/build.mjs +250 -38
  215. package/api/theme/build/build.packed-old-core.test.mjs +21 -3
  216. package/api/theme/build/font-warning.mjs +5 -3
  217. package/api/theme/build/font-warning.test.mjs +2 -1
  218. package/api/theme/remove/remove.test.mjs +2 -2
  219. package/api/theme/targets/targets.mjs +3 -10
  220. package/api/theme/themeBuild.doc.mjs +4 -4
  221. package/api/theme/themeTargets.doc.mjs +4 -0
  222. package/api/theme/use/use.test.mjs +1 -1
  223. package/api/upgrade/_adapter.d.mts +97 -11
  224. package/api/upgrade/_adapter.mjs +315 -32
  225. package/api/upgrade/registry/registry.d.mts +10 -4
  226. package/api/upgrade/registry/registry.mjs +33 -16
  227. package/api/upgrade/registry/registry.test.mjs +85 -0
  228. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  229. package/api/upgrade/run/run.d.mts +4 -2
  230. package/api/upgrade/run/run.mjs +48 -4
  231. package/api/upgrade/run/run.test.mjs +417 -3
  232. package/api/upgrade/status/status.d.mts +21 -5
  233. package/api/upgrade/status/status.mjs +45 -8
  234. package/api/upgrade/upgrade.doc.mjs +16 -8
  235. package/api/upgrade/upgrade.mjs +18 -3
  236. package/api/upgrade/upgrade.test.mjs +194 -0
  237. package/api/upgrade/upgrade.type.d.mts +28 -3
  238. package/api/upgrade/upgrade.type.mjs +24 -7
  239. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  240. package/assets/codemods/registry.mjs +1 -0
  241. package/assets/codemods/runner.mjs +7 -1
  242. package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
  243. package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
  244. package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
  245. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  246. package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
  247. package/assets/discover/official-packages.json +367 -0
  248. package/assets/docs/README.md +10 -0
  249. package/assets/docs/author-a-theme.doc.mjs +5 -5
  250. package/assets/docs/browser-support.doc.mjs +1 -1
  251. package/assets/docs/getting-started.doc.mjs +26 -6
  252. package/assets/docs/is-my-code-good.doc.mjs +287 -0
  253. package/assets/docs/styling-overview.doc.mjs +1 -1
  254. package/assets/docs/theme.doc.dense.mjs +1 -1
  255. package/assets/docs/theme.doc.mjs +2 -2
  256. package/assets/docs/theme.doc.zh.mjs +1 -1
  257. package/assets/docs/tree/add-a-component.doc.mjs +22 -2
  258. package/assets/docs/tree/add-a-theme.doc.mjs +14 -4
  259. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  260. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  261. package/assets/docs/tree/api.doc.mjs +6 -0
  262. package/assets/docs/tree/authoring.doc.mjs +61 -0
  263. package/assets/docs/tree/block-template.doc.mjs +8 -20
  264. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  265. package/assets/docs/tree/building-blocks.doc.mjs +6 -2
  266. package/assets/docs/tree/check-the-props.doc.mjs +201 -0
  267. package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
  268. package/assets/docs/tree/checks.doc.mjs +32 -24
  269. package/assets/docs/tree/ci-and-containers.doc.mjs +101 -0
  270. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  271. package/assets/docs/tree/cli.doc.mjs +7 -1
  272. package/assets/docs/tree/codemods.doc.mjs +17 -7
  273. package/assets/docs/tree/commands.doc.mjs +7 -1
  274. package/assets/docs/tree/component-family.doc.mjs +8 -6
  275. package/assets/docs/tree/component-imports.doc.mjs +21 -3
  276. package/assets/docs/tree/components.doc.mjs +7 -1
  277. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  278. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  279. package/assets/docs/tree/configuration.doc.mjs +8 -4
  280. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  281. package/assets/docs/tree/define-the-theme.doc.mjs +7 -6
  282. package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
  283. package/assets/docs/tree/docs.doc.mjs +9 -3
  284. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  285. package/assets/docs/tree/document-the-theme.doc.mjs +4 -4
  286. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  287. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  288. package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
  289. package/assets/docs/tree/fonts-and-assets.doc.mjs +3 -3
  290. package/assets/docs/tree/generate-a-palette.doc.mjs +8 -6
  291. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  292. package/assets/docs/tree/global.doc.mjs +131 -0
  293. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  294. package/assets/docs/tree/help.doc.mjs +2 -2
  295. package/assets/docs/tree/host-entry.doc.mjs +128 -0
  296. package/assets/docs/tree/install-once.doc.mjs +105 -0
  297. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  298. package/assets/docs/tree/layout.doc.mjs +6 -6
  299. package/assets/docs/tree/links.doc.mjs +7 -6
  300. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  301. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  302. package/assets/docs/tree/migration.doc.mjs +0 -1
  303. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  304. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  305. package/assets/docs/tree/page-template.doc.mjs +4 -8
  306. package/assets/docs/tree/problems.doc.mjs +205 -0
  307. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  308. package/assets/docs/tree/publishing.doc.mjs +6 -6
  309. package/assets/docs/tree/quick-start.doc.mjs +54 -28
  310. package/assets/docs/tree/reference.doc.mjs +192 -0
  311. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  312. package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
  313. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  314. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  315. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  316. package/assets/docs/tree/ship.doc.mjs +2 -2
  317. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  318. package/assets/docs/tree/single-component.doc.mjs +15 -6
  319. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  320. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  321. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  322. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  323. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  324. package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
  325. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  326. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  327. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  328. package/assets/docs/tree/templates.doc.mjs +7 -1
  329. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  330. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  331. package/assets/docs/tree/themes.doc.mjs +5 -1
  332. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  333. package/assets/docs/tree/tokens-data.doc.mjs +2 -2
  334. package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
  335. package/assets/docs/tree/type-scale.doc.mjs +3 -3
  336. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  337. package/assets/docs/tree/updates.doc.mjs +92 -0
  338. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  339. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +15 -3
  340. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  341. package/assets/docs/tree/versioning.doc.mjs +14 -9
  342. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  343. package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
  344. package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
  345. package/assets/docs/use-a-theme.doc.mjs +2 -2
  346. package/assets/docs/use-integrations.doc.mjs +120 -0
  347. package/assets/docs/working-with-ai.doc.mjs +70 -13
  348. package/assets/templates/themes/butter/butterTheme.ts +4 -2
  349. package/assets/templates/themes/stone/stoneTheme.ts +4 -2
  350. package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
  351. package/assets/theme.template.ts +1 -1
  352. package/authoring/codemod/codemod.doc.mjs +7 -3
  353. package/authoring/config/config.doc.mjs +9 -6
  354. package/authoring/config/type.ts +4 -2
  355. package/authoring/debug/parse.d.mts +5 -5
  356. package/authoring/discover/discover.doc.mjs +7 -1
  357. package/authoring/doctypes/_schema.d.mts +8 -3
  358. package/authoring/doctypes/_schema.mjs +1 -0
  359. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  360. package/authoring/doctypes/command/command.doc.mjs +20 -12
  361. package/authoring/doctypes/command/type.ts +14 -0
  362. package/authoring/doctypes/component/component.doc.mjs +30 -27
  363. package/authoring/doctypes/component/type.ts +21 -8
  364. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  365. package/authoring/doctypes/function/function.doc.mjs +9 -8
  366. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  367. package/authoring/doctypes/hook/type.ts +4 -0
  368. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  369. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  370. package/authoring/doctypes/schema/schema.doc.mjs +10 -10
  371. package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
  372. package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
  373. package/authoring/doctypes/template/parse.d.mts +6 -2
  374. package/authoring/doctypes/template/parse.mjs +3 -1
  375. package/authoring/doctypes/template/template.doc.mjs +3 -3
  376. package/authoring/doctypes/template/type.ts +22 -0
  377. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  378. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  379. package/authoring/identity/identity.doc.mjs +3 -3
  380. package/authoring/index.d.ts +2 -0
  381. package/authoring/integration/integration.doc.mjs +30 -6
  382. package/authoring/integration/parse.test.mjs +21 -0
  383. package/authoring/integration/schema.d.mts +16 -3
  384. package/authoring/integration/schema.mjs +34 -2
  385. package/authoring/integration/type.ts +13 -1
  386. package/clients/cli/bin/astryx.mjs +11 -65
  387. package/clients/cli/cli-command.test.mjs +166 -0
  388. package/clients/cli/command-result-coverage.test.mjs +6 -5
  389. package/clients/cli/commands/blog.doc.mjs +1 -0
  390. package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
  391. package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
  392. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  393. package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
  394. package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
  395. package/clients/cli/commands/build.doc.mjs +1 -0
  396. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  397. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  398. package/clients/cli/commands/component.doc.mjs +1 -0
  399. package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
  400. package/clients/cli/commands/component.test.mjs +6 -6
  401. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  402. package/clients/cli/commands/discover.doc.mjs +9 -1
  403. package/clients/cli/commands/discover.mjs +144 -93
  404. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  405. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  406. package/clients/cli/commands/docs.doc.mjs +3 -2
  407. package/clients/cli/commands/docs.mjs +50 -20
  408. package/clients/cli/commands/docs.test.mjs +16 -16
  409. package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
  410. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  411. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  412. package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
  413. package/clients/cli/commands/doctor-integration.test.mjs +936 -3
  414. package/clients/cli/commands/doctor.doc.mjs +12 -2
  415. package/clients/cli/commands/doctor.mjs +332 -7
  416. package/clients/cli/commands/doctor.test.mjs +75 -4
  417. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  418. package/clients/cli/commands/gap-report.mjs +24 -2
  419. package/clients/cli/commands/gap-report.test.mjs +79 -0
  420. package/clients/cli/commands/hook.doc.mjs +1 -0
  421. package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
  422. package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
  423. package/clients/cli/commands/init.behavior.test.mjs +235 -1
  424. package/clients/cli/commands/init.doc.mjs +55 -10
  425. package/clients/cli/commands/init.flag-help.test.mjs +1 -0
  426. package/clients/cli/commands/init.mjs +2 -2
  427. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  428. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  429. package/clients/cli/commands/integration-check.doc.mjs +93 -0
  430. package/clients/cli/commands/integration-check.test.mjs +489 -0
  431. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  432. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  433. package/clients/cli/commands/integration.doc.mjs +6 -2
  434. package/clients/cli/commands/integration.mjs +119 -7
  435. package/clients/cli/commands/json-contract.test.mjs +11 -2
  436. package/clients/cli/commands/manifest.doc.mjs +2 -1
  437. package/clients/cli/commands/manifest.mjs +67 -0
  438. package/clients/cli/commands/outside-project.test.mjs +874 -0
  439. package/clients/cli/commands/postinstall.doc.mjs +23 -0
  440. package/clients/cli/commands/postinstall.mjs +31 -0
  441. package/clients/cli/commands/search.doc.mjs +1 -0
  442. package/clients/cli/commands/search.mjs +16 -11
  443. package/clients/cli/commands/search.test.mjs +429 -296
  444. package/clients/cli/commands/setup-nudge.test.mjs +180 -2
  445. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  446. package/clients/cli/commands/swizzle.mjs +5 -3
  447. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  448. package/clients/cli/commands/template.doc.mjs +1 -0
  449. package/clients/cli/commands/text-json-parity.test.mjs +5 -0
  450. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  451. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  452. package/clients/cli/commands/theme-build.doc.mjs +3 -2
  453. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  454. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  455. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  456. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  457. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  458. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  459. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  460. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  461. package/clients/cli/commands/{build-theme.mjs → theme.mjs} +27 -14
  462. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  463. package/clients/cli/commands/upgrade.doc.mjs +26 -3
  464. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  465. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  466. package/clients/cli/commands/upgrade.mjs +9 -2
  467. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  468. package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
  469. package/clients/cli/index.mjs +156 -100
  470. package/clients/cli/lib/cli-error.mjs +4 -1
  471. package/clients/cli/lib/component-format.mjs +1 -1
  472. package/clients/cli/lib/component-format.test.mjs +1 -1
  473. package/clients/cli/lib/define-command.mjs +14 -9
  474. package/clients/cli/lib/exit-codes.test.mjs +5 -0
  475. package/clients/cli/lib/json-shim.mjs +3 -1
  476. package/clients/cli/lib/manifest.d.ts +9 -0
  477. package/clients/cli/lib/manifest.mjs +17 -1
  478. package/clients/cli/lib/manifest.test.mjs +37 -0
  479. package/clients/cli/lib/welcome-box.mjs +50 -0
  480. package/clients/cli/run.mjs +108 -0
  481. package/foundation/agent-docs/agent-doc-state.d.mts +67 -13
  482. package/foundation/agent-docs/agent-doc-state.mjs +123 -14
  483. package/foundation/agent-docs/agent-docs.d.mts +104 -15
  484. package/foundation/agent-docs/agent-docs.mjs +1028 -114
  485. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
  486. package/foundation/agent-docs/agent-docs.test.mjs +683 -39
  487. package/foundation/agent-docs/computer-agent-text.d.mts +170 -0
  488. package/foundation/agent-docs/computer-agent-text.mjs +750 -0
  489. package/foundation/agent-docs/computer-agent-text.test.mjs +699 -0
  490. package/foundation/config/project.d.mts +35 -3
  491. package/foundation/config/project.mjs +243 -26
  492. package/foundation/config/project.test.mjs +122 -0
  493. package/foundation/config/theme-state.mjs +5 -4
  494. package/foundation/discovery/authoring-self-docs.d.mts +7 -0
  495. package/foundation/discovery/authoring-self-docs.mjs +17 -4
  496. package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
  497. package/foundation/discovery/authoring-surface.d.mts +1 -1
  498. package/foundation/discovery/authoring-surface.mjs +2 -2
  499. package/foundation/discovery/authoring-surface.test.mjs +1 -1
  500. package/foundation/discovery/cli-self-docs.d.mts +2 -1
  501. package/foundation/discovery/cli-self-docs.mjs +22 -4
  502. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  503. package/foundation/discovery/component-discovery.d.mts +227 -10
  504. package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
  505. package/foundation/discovery/component-discovery.mjs +940 -57
  506. package/foundation/discovery/component-discovery.test.mjs +96 -0
  507. package/foundation/discovery/component-loader.d.mts +1 -1
  508. package/foundation/discovery/component-replacement.mjs +20 -1
  509. package/foundation/discovery/component-replacement.test.mjs +40 -0
  510. package/foundation/discovery/copied-passages.d.mts +216 -0
  511. package/foundation/discovery/copied-passages.mjs +720 -0
  512. package/foundation/discovery/copied-passages.test.mjs +124 -0
  513. package/foundation/discovery/doc-consistency.d.mts +34 -0
  514. package/foundation/discovery/doc-consistency.mjs +513 -0
  515. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  516. package/foundation/discovery/doc-fluff.d.mts +112 -0
  517. package/foundation/discovery/doc-fluff.mjs +328 -0
  518. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  519. package/foundation/discovery/doc-types.d.mts +157 -0
  520. package/foundation/discovery/doc-types.mjs +1231 -0
  521. package/foundation/discovery/doc-types.test.mjs +744 -0
  522. package/foundation/discovery/docs-discovery.d.mts +88 -0
  523. package/foundation/discovery/docs-discovery.mjs +97 -3
  524. package/foundation/discovery/integration-doc-files.d.mts +22 -0
  525. package/foundation/discovery/integration-doc-files.mjs +231 -0
  526. package/foundation/discovery/integration-doc-files.test.mjs +246 -0
  527. package/foundation/discovery/module-exports.d.mts +68 -0
  528. package/foundation/discovery/module-exports.mjs +609 -31
  529. package/foundation/discovery/module-exports.test.mjs +172 -0
  530. package/foundation/discovery/package-tsconfig.d.mts +14 -0
  531. package/foundation/discovery/package-tsconfig.mjs +228 -0
  532. package/foundation/discovery/package-tsconfig.test.mjs +210 -0
  533. package/foundation/discovery/project-typescript.d.mts +32 -0
  534. package/foundation/discovery/project-typescript.mjs +89 -0
  535. package/foundation/discovery/prop-drift.d.mts +297 -0
  536. package/foundation/discovery/prop-drift.mjs +2428 -0
  537. package/foundation/discovery/prop-drift.test.mjs +2337 -0
  538. package/foundation/discovery/runner-allowlist.d.mts +38 -0
  539. package/foundation/discovery/runner-allowlist.mjs +51 -0
  540. package/foundation/discovery/runner-commands.d.mts +77 -0
  541. package/foundation/discovery/runner-commands.mjs +294 -0
  542. package/foundation/discovery/runner-commands.test.mjs +128 -0
  543. package/foundation/discovery/stray-pointers.d.mts +52 -0
  544. package/foundation/discovery/stray-pointers.mjs +293 -0
  545. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  546. package/foundation/discovery/template-adapter.mjs +92 -6
  547. package/foundation/discovery/template-needs.mjs +6 -46
  548. package/foundation/discovery/theme-discovery.mjs +147 -3
  549. package/foundation/discovery/theme-imports.mjs +8 -4
  550. package/foundation/discovery/theme-imports.test.mjs +1 -1
  551. package/foundation/discovery/type-match.d.mts +53 -0
  552. package/foundation/discovery/type-match.mjs +660 -0
  553. package/foundation/discovery/type-match.test.mjs +169 -0
  554. package/foundation/discovery/type-text.d.mts +68 -0
  555. package/foundation/discovery/type-text.mjs +658 -0
  556. package/foundation/discovery/type-text.test.mjs +196 -0
  557. package/foundation/discovery/unresolved-references.d.mts +62 -0
  558. package/foundation/discovery/unresolved-references.mjs +790 -0
  559. package/foundation/discovery/unresolved-references.test.mjs +567 -0
  560. package/foundation/doc-compiler/doc-loads.test.mjs +84 -10
  561. package/foundation/doc-compiler/inputs.mjs +27 -1
  562. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  563. package/foundation/doc-compiler/links.d.mts +41 -5
  564. package/foundation/doc-compiler/links.mjs +167 -28
  565. package/foundation/doc-compiler/links.test.mjs +97 -4
  566. package/foundation/doc-compiler/read.d.mts +1 -1
  567. package/foundation/doc-compiler/read.mjs +59 -1
  568. package/foundation/doc-compiler/read.test.mjs +11 -2
  569. package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
  570. package/foundation/doc-compiler/tree.d.mts +32 -6
  571. package/foundation/doc-compiler/tree.mjs +107 -44
  572. package/foundation/doc-compiler/tree.test.mjs +14 -7
  573. package/foundation/env/cli-command.d.mts +83 -0
  574. package/foundation/env/cli-command.mjs +152 -0
  575. package/foundation/env/cli-command.test.mjs +129 -0
  576. package/foundation/env/node-version.test.mjs +15 -3
  577. package/foundation/env/package-manager.d.mts +93 -9
  578. package/foundation/env/package-manager.global.test.mjs +66 -0
  579. package/foundation/env/package-manager.mjs +184 -13
  580. package/foundation/env/package-manager.test.mjs +341 -15
  581. package/foundation/env/project-scope.d.mts +9 -0
  582. package/foundation/env/project-scope.mjs +33 -0
  583. package/foundation/env/search-path.d.mts +42 -0
  584. package/foundation/env/search-path.mjs +205 -0
  585. package/foundation/env/search-path.test.mjs +122 -0
  586. package/foundation/env/user-dirs.d.mts +39 -0
  587. package/foundation/env/user-dirs.mjs +93 -0
  588. package/foundation/env/user-dirs.test.mjs +72 -0
  589. package/foundation/env/user-settings.d.mts +46 -0
  590. package/foundation/env/user-settings.mjs +106 -0
  591. package/foundation/env/user-settings.test.mjs +64 -0
  592. package/foundation/fs/file-protection.mjs +15 -1
  593. package/foundation/fs/module-loader.d.mts +2 -1
  594. package/foundation/fs/module-loader.mjs +60 -4
  595. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  596. package/foundation/fs/module-loader.test.mjs +194 -0
  597. package/foundation/fs/path-compare.d.mts +33 -0
  598. package/foundation/fs/path-compare.mjs +73 -0
  599. package/foundation/fs/paths.d.mts +122 -4
  600. package/foundation/fs/paths.mjs +675 -29
  601. package/foundation/fs/paths.test.mjs +439 -54
  602. package/foundation/fs/read-record.d.mts +18 -0
  603. package/foundation/fs/read-record.mjs +131 -0
  604. package/foundation/fs/read-record.test.mjs +77 -0
  605. package/foundation/integrations/autolink.d.mts +2 -1
  606. package/foundation/integrations/autolink.mjs +4 -13
  607. package/foundation/integrations/cli-peer-version.d.mts +36 -0
  608. package/foundation/integrations/cli-peer-version.mjs +132 -0
  609. package/foundation/integrations/cli-peer-version.test.mjs +354 -0
  610. package/foundation/integrations/computer-integrations.d.mts +81 -0
  611. package/foundation/integrations/computer-integrations.mjs +345 -0
  612. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  613. package/foundation/integrations/contribution-inventory.d.mts +26 -20
  614. package/foundation/integrations/contribution-inventory.mjs +97 -8
  615. package/foundation/integrations/exports-subpaths.d.mts +57 -0
  616. package/foundation/integrations/exports-subpaths.mjs +113 -0
  617. package/foundation/integrations/integration-warnings.mjs +3 -2
  618. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  619. package/foundation/integrations/integrations.d.mts +51 -1
  620. package/foundation/integrations/integrations.mjs +106 -4
  621. package/foundation/integrations/issue.ts +6 -0
  622. package/foundation/integrations/public-imports.d.mts +118 -0
  623. package/foundation/integrations/public-imports.mjs +1769 -0
  624. package/foundation/integrations/public-imports.test.mjs +1793 -0
  625. package/foundation/integrations/validate-contributions.d.mts +117 -0
  626. package/foundation/integrations/validate-contributions.mjs +1209 -14
  627. package/foundation/release/agent-text-worker.d.mts +4 -0
  628. package/foundation/release/agent-text-worker.mjs +52 -0
  629. package/foundation/release/cache.d.mts +310 -0
  630. package/foundation/release/cache.mjs +1216 -0
  631. package/foundation/release/cache.test.mjs +923 -0
  632. package/foundation/release/choose.d.mts +207 -0
  633. package/foundation/release/choose.mjs +677 -0
  634. package/foundation/release/choose.test.mjs +427 -0
  635. package/foundation/release/core-worker.d.mts +4 -0
  636. package/foundation/release/core-worker.mjs +38 -0
  637. package/foundation/release/global-state.d.mts +263 -0
  638. package/foundation/release/global-state.mjs +474 -0
  639. package/foundation/release/global-state.test.mjs +381 -0
  640. package/foundation/release/handoff.d.mts +79 -0
  641. package/foundation/release/handoff.e2e.test.mjs +278 -0
  642. package/foundation/release/handoff.mjs +524 -0
  643. package/foundation/release/lock-lease.d.mts +23 -0
  644. package/foundation/release/lock-lease.mjs +80 -0
  645. package/foundation/release/notices.d.mts +307 -0
  646. package/foundation/release/notices.mjs +707 -0
  647. package/foundation/release/notices.test.mjs +586 -0
  648. package/foundation/release/npm-guard.d.mts +4 -0
  649. package/foundation/release/npm-guard.mjs +126 -0
  650. package/foundation/release/project.d.mts +141 -0
  651. package/foundation/release/project.mjs +466 -0
  652. package/foundation/release/project.test.mjs +288 -0
  653. package/foundation/release/refresh-worker.d.mts +4 -0
  654. package/foundation/release/refresh-worker.mjs +27 -0
  655. package/foundation/release/run-context.d.mts +47 -0
  656. package/foundation/release/run-context.mjs +163 -0
  657. package/foundation/release/update-notice-env.d.mts +28 -0
  658. package/foundation/release/update-notice-env.mjs +39 -0
  659. package/foundation/response/base.d.ts +26 -3
  660. package/foundation/response/error-codes.d.mts +3 -1
  661. package/foundation/response/error-codes.doc.mjs +12 -0
  662. package/foundation/response/error-codes.mjs +17 -0
  663. package/foundation/response/error-codes.test.mjs +2 -0
  664. package/foundation/response/json-contract.test.mjs +7 -2
  665. package/foundation/response/json.mjs +4 -1
  666. package/foundation/response/response-types.doc.mjs +22 -11
  667. package/foundation/response/response-types.doc.test.mjs +46 -0
  668. package/foundation/response/response.doc.mjs +3 -3
  669. package/foundation/route/route.d.mts +285 -0
  670. package/foundation/route/route.mjs +324 -0
  671. package/foundation/route/route.test.mjs +153 -0
  672. package/foundation/runtime/hosted-runtime.test.mjs +403 -0
  673. package/foundation/runtime/locked-versions.d.mts +32 -0
  674. package/foundation/runtime/locked-versions.mjs +65 -0
  675. package/foundation/runtime/package-root.d.mts +91 -0
  676. package/foundation/runtime/package-root.mjs +174 -0
  677. package/foundation/runtime/package-set.d.mts +62 -0
  678. package/foundation/runtime/package-set.mjs +130 -0
  679. package/foundation/runtime/package-set.test.mjs +432 -0
  680. package/foundation/text/string-utils.d.mts +2 -1
  681. package/foundation/text/string-utils.mjs +16 -5
  682. package/foundation/text/suggest-order.d.mts +72 -0
  683. package/foundation/text/suggest-order.mjs +363 -0
  684. package/foundation/text/suggest-order.test.mjs +259 -0
  685. package/foundation/xle/browser-imports.test.mjs +74 -0
  686. package/foundation/xle/registry.mjs +4 -0
  687. package/foundation/xle/registry.test.mjs +28 -0
  688. package/host/door-conformance.test.mjs +274 -0
  689. package/host/index.d.ts +116 -0
  690. package/host/index.mjs +295 -0
  691. package/host/index.test.mjs +302 -0
  692. package/package.json +16 -11
  693. package/scripts/postinstall.mjs +24 -5
  694. package/assets/docs/tree/integrations.doc.mjs +0 -40
@@ -9,6 +9,12 @@
9
9
  * - Multi-file write is atomic: if one file fails, none are left behind.
10
10
  * - An `--out` escape, or an output directory that cannot be created, fails
11
11
  * with a registered error code.
12
+ * - Every output a build writes stays inside the working directory: an
13
+ * absolute `--out` path or a theme file outside it fails before anything
14
+ * is written, while absolute paths inside it build, also through a
15
+ * symlinked spelling. `--check` writes nothing, so it compares those
16
+ * outside outputs read-only, and a stale report for them ends with a
17
+ * remedy that works: the directory to build and check from.
12
18
  *
13
19
  * Runs the CLI in-process (shared runCli harness) against a tiny synthetic theme file.
14
20
  */
@@ -22,6 +28,7 @@ import {runCli} from '../../../test-utils/run-cli.mjs';
22
28
  import {themeBuild} from '../../../api/theme/build/build.mjs';
23
29
  import {AstryxError} from '../../../api/error.mjs';
24
30
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
31
+ import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
25
32
 
26
33
  function writeTheme(dir, name) {
27
34
  fs.mkdirSync(dir, {recursive: true});
@@ -59,7 +66,9 @@ describe('theme build path safety', () => {
59
66
  );
60
67
 
61
68
  expect(result.code).not.toBe(0);
62
- expect(result.stderr + result.stdout).toMatch(/path separator|invalid theme name/i);
69
+ expect(result.stderr + result.stdout).toMatch(
70
+ /path separator|invalid theme name/i,
71
+ );
63
72
 
64
73
  // The traversal target must not exist.
65
74
  expect(fs.existsSync(path.join(tmpDir, 'escaped.js'))).toBe(false);
@@ -92,7 +101,10 @@ describe('theme build path safety', () => {
92
101
 
93
102
  const themeFile = writeTheme(themesDir, '../leak');
94
103
 
95
- await runCli(['theme', 'build', path.relative(project, themeFile)], project);
104
+ await runCli(
105
+ ['theme', 'build', path.relative(project, themeFile)],
106
+ project,
107
+ );
96
108
 
97
109
  // Neither the CSS nor any sibling JS should have been written.
98
110
  const entries = fs.readdirSync(themesDir).sort();
@@ -114,19 +126,200 @@ describe('theme build output-path failures carry registered codes', () => {
114
126
  return {result, envelope: JSON.parse(result.stdout)};
115
127
  }
116
128
 
117
- it('reports an --out path outside the project as ERR_PATH_TRAVERSAL', async () => {
129
+ it('reports a relative --out path outside the project as ERR_PATH_TRAVERSAL, with --check too', async () => {
118
130
  const project = path.join(tmpDir, 'project');
119
131
  const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
120
132
 
133
+ for (const extra of [[], ['--check']]) {
134
+ const {result, envelope} = await buildJson(
135
+ [
136
+ path.relative(project, themeFile),
137
+ '--out',
138
+ '../escaped.css',
139
+ ...extra,
140
+ ],
141
+ project,
142
+ );
143
+
144
+ expect(result.code).toBe(1);
145
+ expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
146
+ expect(registered.has(envelope.code)).toBe(true);
147
+ }
148
+ expect(fs.existsSync(path.join(tmpDir, 'escaped.css'))).toBe(false);
149
+ });
150
+
151
+ it('reports an absolute --out path outside the project as ERR_PATH_TRAVERSAL', async () => {
152
+ const project = path.join(tmpDir, 'project');
153
+ const outside = path.join(tmpDir, 'outside');
154
+ fs.mkdirSync(outside, {recursive: true});
155
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
156
+ const out = path.join(outside, 'ocean.css');
157
+
121
158
  const {result, envelope} = await buildJson(
122
- [path.relative(project, themeFile), '--out', '../escaped.css'],
159
+ [path.relative(project, themeFile), '--out', out],
123
160
  project,
124
161
  );
125
162
 
126
163
  expect(result.code).toBe(1);
127
164
  expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
128
- expect(registered.has(envelope.code)).toBe(true);
129
- expect(fs.existsSync(path.join(tmpDir, 'escaped.css'))).toBe(false);
165
+ expect(fs.readdirSync(outside)).toEqual([]);
166
+ });
167
+
168
+ it('checks an absolute --out path outside the project read-only', async () => {
169
+ const project = path.join(tmpDir, 'project');
170
+ const outside = path.join(tmpDir, 'outside');
171
+ fs.mkdirSync(outside, {recursive: true});
172
+ const themeFile = path.relative(
173
+ project,
174
+ writeTheme(path.join(project, 'themes'), 'ocean'),
175
+ );
176
+ const out = path.join(outside, 'ocean.css');
177
+
178
+ const missing = await buildJson(
179
+ [themeFile, '--out', out, '--check'],
180
+ project,
181
+ );
182
+ expect(missing.result.code).toBe(1);
183
+ expect(missing.envelope.type).toBe('theme.build.check');
184
+ expect(missing.envelope.data.upToDate).toBe(false);
185
+ expect(fs.readdirSync(outside)).toEqual([]);
186
+
187
+ // Outputs built inside the project compare equal once copied outside:
188
+ // only the volatile Command line, which --check ignores, names --out.
189
+ const dist = path.join(project, 'dist');
190
+ const built = await buildJson(
191
+ [themeFile, '--out', path.join(dist, 'ocean.css')],
192
+ project,
193
+ );
194
+ expect(built.result.code).toBe(0);
195
+ for (const file of fs.readdirSync(dist)) {
196
+ fs.copyFileSync(path.join(dist, file), path.join(outside, file));
197
+ }
198
+ const copied = fs.readdirSync(outside).sort();
199
+
200
+ const current = await buildJson(
201
+ [themeFile, '--out', out, '--check'],
202
+ project,
203
+ );
204
+ expect(current.result.code).toBe(0);
205
+ expect(current.envelope.type).toBe('theme.build.check');
206
+ expect(current.envelope.data.upToDate).toBe(true);
207
+ expect(fs.readdirSync(outside).sort()).toEqual(copied);
208
+ });
209
+
210
+ it('reports a theme file outside the project as ERR_PATH_TRAVERSAL, because its outputs go beside it; --check only compares them', async () => {
211
+ const project = path.join(tmpDir, 'project');
212
+ fs.mkdirSync(project, {recursive: true});
213
+ const shared = path.join(tmpDir, 'shared');
214
+ const themeFile = writeTheme(shared, 'ocean');
215
+
216
+ for (const file of [themeFile, path.relative(project, themeFile)]) {
217
+ const {result, envelope} = await buildJson([file], project);
218
+
219
+ expect(result.code).toBe(1);
220
+ expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
221
+
222
+ const checked = await buildJson([file, '--check'], project);
223
+ expect(checked.result.code).toBe(1);
224
+ expect(checked.envelope.type).toBe('theme.build.check');
225
+ expect(checked.envelope.data.upToDate).toBe(false);
226
+ }
227
+ expect(fs.readdirSync(shared)).toEqual(['theme.mjs']);
228
+ });
229
+
230
+ /**
231
+ * Read the remedy that ends a stale report for outputs outside cwd: the
232
+ * directory to run from, then the build and check arguments after `theme
233
+ * build`. Each command starts with the install-aware invocation for it.
234
+ * @param {string} stderr
235
+ */
236
+ function readRemedy(stderr) {
237
+ const lines = stderr.split('\n').map(line => line.trim());
238
+ const cd = lines.find(line => line.startsWith('cd '));
239
+ expect(cd).toBeDefined();
240
+ const dir = /** @type {string} */ (cd).slice('cd '.length);
241
+ const stem = `${getCliInvocation(dir)} theme build `;
242
+ const commands = lines.filter(line => line.startsWith(stem));
243
+ expect(commands).toHaveLength(2);
244
+ const [build, check] = commands.map(line =>
245
+ line.slice(stem.length).split(' '),
246
+ );
247
+ expect(check).toEqual([...build, '--check']);
248
+ return {dir, build, check};
249
+ }
250
+
251
+ it('ends a stale report for outputs outside cwd with a remedy that works, and keeps the report for outputs inside it', async () => {
252
+ const project = path.join(tmpDir, 'project');
253
+ const inside = path.relative(
254
+ project,
255
+ writeTheme(path.join(project, 'themes'), 'ocean'),
256
+ );
257
+ const shared = writeTheme(path.join(tmpDir, 'shared'), 'ocean');
258
+ const outside = path.join(tmpDir, 'outside');
259
+
260
+ for (const args of [
261
+ [path.relative(project, shared)],
262
+ [inside, '--out', path.join(outside, 'ocean.css')],
263
+ ]) {
264
+ const stale = await runCli(
265
+ ['theme', 'build', ...args, '--check'],
266
+ project,
267
+ );
268
+ expect(stale.code).toBe(1);
269
+ // The old remedy ran the build from cwd, which refuses these outputs.
270
+ expect(stale.stderr).not.toContain('Rebuild with:');
271
+ expect(stale.stderr).not.toContain(`theme build ${args.join(' ')}`);
272
+
273
+ // Following the remedy builds, and the check from there passes.
274
+ const remedy = readRemedy(stale.stderr);
275
+ const built = await runCli(
276
+ ['theme', 'build', ...remedy.build],
277
+ remedy.dir,
278
+ );
279
+ expect(built.code).toBe(0);
280
+ const checked = await runCli(
281
+ ['--json', 'theme', 'build', ...remedy.check],
282
+ remedy.dir,
283
+ );
284
+ expect(checked.code).toBe(0);
285
+ expect(JSON.parse(checked.stdout).data.upToDate).toBe(true);
286
+ }
287
+
288
+ // Outputs inside cwd keep the plain rebuild line.
289
+ const local = await runCli(['theme', 'build', inside, '--check'], project);
290
+ expect(local.code).toBe(1);
291
+ expect(local.stderr).toContain(
292
+ `Rebuild with: astryx theme build ${inside}`,
293
+ );
294
+ expect(local.stderr).not.toMatch(/^\s*cd /m);
295
+ });
296
+
297
+ it('builds absolute paths inside the project, also when they reach it through a symlink', async () => {
298
+ const project = path.join(tmpDir, 'project');
299
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
300
+ const alias = path.join(tmpDir, 'alias');
301
+ fs.symlinkSync(project, alias, 'dir');
302
+
303
+ for (const [args, written] of [
304
+ [
305
+ [themeFile, '--out', path.join(project, 'dist', 'direct.css')],
306
+ path.join(project, 'dist', 'direct.css'),
307
+ ],
308
+ [
309
+ [themeFile, '--out', path.join(alias, 'dist', 'aliased.css')],
310
+ path.join(project, 'dist', 'aliased.css'),
311
+ ],
312
+ [
313
+ [path.join(alias, 'themes', 'theme.mjs')],
314
+ path.join(project, 'themes', 'ocean.css'),
315
+ ],
316
+ ]) {
317
+ const {result, envelope} = await buildJson(args, project);
318
+
319
+ expect(result.code).toBe(0);
320
+ expect(envelope.type).toBe('theme.build');
321
+ expect(fs.existsSync(written)).toBe(true);
322
+ }
130
323
  });
131
324
 
132
325
  it('reports an --out path that escapes through a symlink as ERR_PATH_TRAVERSAL', async () => {
@@ -177,4 +370,29 @@ describe('theme build output-path failures carry registered codes', () => {
177
370
  code: ERROR_CODES.ERR_PATH_TRAVERSAL,
178
371
  });
179
372
  });
373
+
374
+ it('themeBuild() rejects an output outside cwd, an absolute out path or the default beside a theme file outside cwd, and checks it read-only', async () => {
375
+ const project = path.join(tmpDir, 'project');
376
+ const inside = writeTheme(path.join(project, 'themes'), 'ocean');
377
+ const shared = path.join(tmpDir, 'shared');
378
+ const outsideTheme = writeTheme(shared, 'ocean');
379
+ const outDir = path.join(tmpDir, 'out');
380
+
381
+ for (const [file, options] of [
382
+ [path.relative(project, inside), {out: path.join(outDir, 'ocean.css')}],
383
+ [outsideTheme, {}],
384
+ ]) {
385
+ await expect(
386
+ themeBuild(file, options, {cwd: project}),
387
+ ).rejects.toMatchObject({code: ERROR_CODES.ERR_PATH_TRAVERSAL});
388
+ await expect(
389
+ themeBuild(file, {...options, check: true}, {cwd: project}),
390
+ ).resolves.toMatchObject({
391
+ type: 'theme.build.check',
392
+ data: {upToDate: false},
393
+ });
394
+ }
395
+ expect(fs.existsSync(outDir)).toBe(false);
396
+ expect(fs.readdirSync(shared)).toEqual(['theme.mjs']);
397
+ });
180
398
  });
@@ -126,7 +126,10 @@ describe('theme build emits a live TextInput selector (#4109)', () => {
126
126
  `};\n`,
127
127
  );
128
128
 
129
- const result = await runCli(['theme', 'build', themeFile, '-o', outFile]);
129
+ const result = await runCli(
130
+ ['theme', 'build', themeFile, '-o', outFile],
131
+ tmpDir,
132
+ );
130
133
  const css = fs.readFileSync(outFile, 'utf8');
131
134
 
132
135
  expect(result.status).toBe(0);
@@ -148,7 +151,7 @@ describe('theme build emits a live TextInput selector (#4109)', () => {
148
151
  `};\n`,
149
152
  );
150
153
 
151
- await runCli(['theme', 'build', themeFile, '-o', outFile]);
154
+ await runCli(['theme', 'build', themeFile, '-o', outFile], tmpDir);
152
155
  const css = fs.readFileSync(outFile, 'utf8');
153
156
 
154
157
  expect(css).toContain('.astryx-text-input');
@@ -47,6 +47,7 @@ export const doc = {
47
47
  cli: 'astryx build "analytics dashboard" --json',
48
48
  },
49
49
  ],
50
+ outsideProject: 'same',
50
51
  exitCodes: [
51
52
  {code: 0, when: 'success (including zero matches)'},
52
53
  {
@@ -11,6 +11,7 @@ import * as os from 'node:os';
11
11
  import * as path from 'node:path';
12
12
  import {runCli} from '../../../test-utils/run-cli.mjs';
13
13
  import {doc as buildDoc} from './build.doc.mjs';
14
+ import {linkThisCliAsProjectCli} from '../../../test-utils/release-fixtures.mjs';
14
15
 
15
16
  const SLOW = 30_000;
16
17
 
@@ -20,6 +21,9 @@ let tmpDir;
20
21
  beforeEach(() => {
21
22
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-build-no-core-'));
22
23
  fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
24
+ // A project whose own CLI answers and that installs no Core: outside a
25
+ // project a copy answers from the Core it carries instead (AST-081 FR3).
26
+ linkThisCliAsProjectCli(tmpDir);
23
27
  });
24
28
 
25
29
  afterEach(() => {
@@ -8,9 +8,16 @@
8
8
  * transient fetch (path _npx or npm_command=exec), and once set up.
9
9
  */
10
10
 
11
- import {describe, it, expect} from 'vitest';
11
+ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
12
+ import {spawnSync} from 'node:child_process';
13
+ import * as fs from 'node:fs';
14
+ import * as os from 'node:os';
15
+ import * as path from 'node:path';
16
+ import {fileURLToPath} from 'node:url';
12
17
  import {shouldNudge} from '../../../scripts/postinstall.mjs';
13
18
 
19
+ const CLI = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
20
+
14
21
  const DEP = '/proj/node_modules/@astryxdesign/cli/scripts/postinstall.mjs'; // real dep install
15
22
  const NPX = '/Users/x/.npm/_npx/a1b2/node_modules/@astryxdesign/cli/scripts/postinstall.mjs';
16
23
  const REPO = '/repo/packages/cli/scripts/postinstall.mjs'; // monorepo/source
@@ -40,3 +47,44 @@ describe('cli postinstall — shouldNudge', () => {
40
47
  expect(shouldNudge({})).toBe(false);
41
48
  });
42
49
  });
50
+
51
+ // Install time, end to end: the real script and the leaf it loads, installed
52
+ // under a monorepo's node_modules, run the way npm runs them for a package.
53
+ describe('cli postinstall — inside a monorepo package', () => {
54
+ let repo;
55
+ beforeEach(() => {
56
+ repo = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-cli-postinstall-'));
57
+ fs.mkdirSync(path.join(repo, '.git'));
58
+ fs.mkdirSync(path.join(repo, 'packages/app'), {recursive: true});
59
+ fs.writeFileSync(path.join(repo, 'packages/app/package.json'), '{"name":"app"}');
60
+ const installed = path.join(repo, 'node_modules/@astryxdesign/cli');
61
+ for (const rel of ['scripts/postinstall.mjs', 'foundation/agent-docs/agent-doc-state.mjs']) {
62
+ fs.mkdirSync(path.dirname(path.join(installed, rel)), {recursive: true});
63
+ fs.copyFileSync(path.join(CLI, rel), path.join(installed, rel));
64
+ }
65
+ });
66
+ afterEach(() => fs.rmSync(repo, {recursive: true, force: true}));
67
+
68
+ const install = () =>
69
+ spawnSync(
70
+ process.execPath,
71
+ [path.join(repo, 'node_modules/@astryxdesign/cli/scripts/postinstall.mjs')],
72
+ {
73
+ env: {...process.env, INIT_CWD: path.join(repo, 'packages/app'), npm_command: 'install'},
74
+ encoding: 'utf8',
75
+ },
76
+ );
77
+
78
+ it('stays quiet when init ran at the repository root', () => {
79
+ fs.writeFileSync(path.join(repo, 'AGENTS.md'), '<!-- ASTRYX:START -->\n');
80
+ const r = install();
81
+ expect(r.status).toBe(0);
82
+ expect(r.stdout).toBe('');
83
+ });
84
+
85
+ it('still nudges when no folder up to the repository root ran init', () => {
86
+ const r = install();
87
+ expect(r.status).toBe(0);
88
+ expect(r.stdout).toMatch(/finish setup and install the Astryx agent prompt/);
89
+ });
90
+ });
@@ -90,6 +90,7 @@ export const doc = {
90
90
  cli: 'astryx component SideNav --package @astryxdesign/core',
91
91
  },
92
92
  ],
93
+ outsideProject: 'same',
93
94
  exitCodes: [
94
95
  {code: 0, when: 'success'},
95
96
  {
@@ -6,30 +6,30 @@
6
6
  * Global options: --detail full|compact|brief, --lang en|zh|dense
7
7
  */
8
8
 
9
- import {findCoreDir} from '../../../../foundation/fs/paths.mjs';
9
+ import {findCoreDir} from '../../../foundation/fs/paths.mjs';
10
10
  import {
11
11
  resolveImportPath,
12
- } from '../../../../foundation/discovery/component-discovery.mjs';
12
+ } from '../../../foundation/discovery/component-discovery.mjs';
13
13
  import {
14
14
  formatFull,
15
15
  formatCompact,
16
16
  formatBrief,
17
17
  formatProps,
18
18
  formatBriefAll,
19
- } from '../../lib/component-format.mjs';
20
- import {resolveTheme} from '../../lib/resolve-theme.mjs';
21
- import {getCliInvocation} from '../../../../foundation/env/package-manager.mjs';
22
- import {jsonOut} from '../../../../foundation/response/json.mjs';
23
- import {emit, section, text, list, record, records, code} from '../../formatters/index.mjs';
24
- import {cliError} from '../../lib/cli-error.mjs';
25
- import {defineCommand} from '../../lib/define-command.mjs';
26
- import {resultSet} from '../../../../foundation/debug/index.mjs';
27
- import {ERROR_CODES} from '../../../../foundation/response/error-codes.mjs';
28
- import {component as componentApi} from '../../../../api/component/component.mjs';
29
- import {Project} from '../../../../foundation/config/project.mjs';
30
- import {warnOnIntegrationIssues} from '../../../../foundation/integrations/integration-warnings.mjs';
31
- import {doc as componentCommand} from '../component.doc.mjs';
32
- import {doc as componentFn} from '../../../../api/component/component.doc.mjs';
19
+ } from '../lib/component-format.mjs';
20
+ import {resolveTheme} from '../lib/resolve-theme.mjs';
21
+ import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
22
+ import {jsonOut} from '../../../foundation/response/json.mjs';
23
+ import {emit, section, text, list, record, records, code} from '../formatters/index.mjs';
24
+ import {cliError} from '../lib/cli-error.mjs';
25
+ import {defineCommand} from '../lib/define-command.mjs';
26
+ import {resultSet} from '../../../foundation/debug/index.mjs';
27
+ import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
28
+ import {component as componentApi} from '../../../api/component/component.mjs';
29
+ import {Project} from '../../../foundation/config/project.mjs';
30
+ import {warnOnIntegrationIssues} from '../../../foundation/integrations/integration-warnings.mjs';
31
+ import {doc as componentCommand} from './component.doc.mjs';
32
+ import {doc as componentFn} from '../../../api/component/component.doc.mjs';
33
33
 
34
34
  /**
35
35
  * The api layer's component() widens its return to `{type: string, data: unknown}`,
@@ -37,13 +37,13 @@ import {doc as componentFn} from '../../../../api/component/component.doc.mjs';
37
37
  * src/types/component to get narrowing + typed data.
38
38
  *
39
39
  * @typedef {(
40
- * | import('../../../../api/component/component.type.mjs').ComponentListResponse
41
- * | import('../../../../api/component/component.type.mjs').ComponentBatchResponse
42
- * | import('../../../../api/component/component.type.mjs').ComponentDetailResponse
43
- * | import('../../../../api/component/component.type.mjs').ComponentDetailPropsResponse
44
- * | import('../../../../api/component/component.type.mjs').ComponentDetailSourceResponse
45
- * | import('../../../../api/component/component.type.mjs').ComponentDetailShowcaseResponse
46
- * | import('../../../../api/component/component.type.mjs').ComponentDetailBlocksResponse
40
+ * | import('../../../api/component/component.type.mjs').ComponentListResponse
41
+ * | import('../../../api/component/component.type.mjs').ComponentBatchResponse
42
+ * | import('../../../api/component/component.type.mjs').ComponentDetailResponse
43
+ * | import('../../../api/component/component.type.mjs').ComponentDetailPropsResponse
44
+ * | import('../../../api/component/component.type.mjs').ComponentDetailSourceResponse
45
+ * | import('../../../api/component/component.type.mjs').ComponentDetailShowcaseResponse
46
+ * | import('../../../api/component/component.type.mjs').ComponentDetailBlocksResponse
47
47
  * )} ComponentResult
48
48
  */
49
49
 
@@ -57,7 +57,7 @@ import {doc as componentFn} from '../../../../api/component/component.doc.mjs';
57
57
  * the thing that resolved (the component) is not the thing being counted.
58
58
  *
59
59
  * @param {ComponentResult} result
60
- * @returns {import('../../../../foundation/debug/command-result.mjs').CommandResult}
60
+ * @returns {import('../../../foundation/debug/command-result.mjs').CommandResult}
61
61
  */
62
62
  function summarize(result) {
63
63
  switch (result.type) {
@@ -90,11 +90,11 @@ function summarize(result) {
90
90
 
91
91
  /**
92
92
  * Project one single-component API result through the existing formatter kit.
93
- * @param {import('../../../../api/component/component.type.mjs').ComponentSingleResponse} result
93
+ * @param {import('../../../api/component/component.type.mjs').ComponentSingleResponse} result
94
94
  * @param {string} requestedName
95
95
  * @param {'full'|'compact'|'brief'} detail
96
96
  * @param {Awaited<ReturnType<typeof resolveTheme>>} themeData
97
- * @returns {import('../../formatters/index.mjs').Block[]}
97
+ * @returns {import('../formatters/index.mjs').Block[]}
98
98
  */
99
99
  function componentDetailBlocks(result, requestedName, detail, themeData) {
100
100
  const requested = (requestedName.split('/').pop() ?? requestedName).replace(
@@ -111,7 +111,7 @@ function componentDetailBlocks(result, requestedName, detail, themeData) {
111
111
  : requested;
112
112
  switch (result.type) {
113
113
  case 'component.detail': {
114
- /** @type {import('../../formatters/index.mjs').Block[]} */
114
+ /** @type {import('../formatters/index.mjs').Block[]} */
115
115
  const out = [record({package: result.package})];
116
116
  if (result.data.parentDoc) {
117
117
  out.push(record(result.data, {fields: ['parentDoc']}));
@@ -150,7 +150,7 @@ function componentDetailBlocks(result, requestedName, detail, themeData) {
150
150
  /** @param {{package: string}} block @param {string} label */
151
151
  const owned = (block, label) =>
152
152
  block.package === result.package ? label : `${label} (${block.package})`;
153
- /** @type {import('../../formatters/index.mjs').Block[]} */
153
+ /** @type {import('../formatters/index.mjs').Block[]} */
154
154
  const out = [record({package: result.package})];
155
155
  if (showcase) {
156
156
  out.push(
@@ -243,7 +243,7 @@ export function registerComponent(program) {
243
243
  lang, zh, dense,
244
244
  }));
245
245
  } catch (e) {
246
- const err = /** @type {import('../../../../api/error.mjs').AstryxError} */ (e);
246
+ const err = /** @type {import('../../../api/error.mjs').AstryxError} */ (e);
247
247
  return cliError(err.message, {suggestions: err.suggestions, code: err.code});
248
248
  }
249
249
 
@@ -326,7 +326,7 @@ export function registerComponent(program) {
326
326
  // description), grouped by category. Fields mirror the JSON keys.
327
327
  const groups = result.data.components;
328
328
  const entries = Object.entries(groups);
329
- /** @type {import('../../formatters/index.mjs').Block[]} */
329
+ /** @type {import('../formatters/index.mjs').Block[]} */
330
330
  const out = [];
331
331
  for (const [cat, items] of entries) {
332
332
  // Skip the synthetic group header when there's only one ungrouped category
@@ -362,7 +362,7 @@ export function registerComponent(program) {
362
362
  nameCounts.set(item.name, set);
363
363
  }
364
364
  }
365
- /** @param {import('../../../../api/component/component.type.mjs').ComponentListEntry} item */
365
+ /** @param {import('../../../api/component/component.type.mjs').ComponentListEntry} item */
366
366
  const importCell = item => {
367
367
  // Use a precomputed import when the API supplies one (integration
368
368
  // components carry it); only fall back to the core resolver for
@@ -392,7 +392,7 @@ export function registerComponent(program) {
392
392
  }
393
393
 
394
394
  case 'component.batch': {
395
- /** @type {import('../../formatters/index.mjs').Block[]} */
395
+ /** @type {import('../formatters/index.mjs').Block[]} */
396
396
  const out = [
397
397
  section('Component batch'),
398
398
  record({count: result.data.count}),
@@ -474,8 +474,8 @@ export function registerComponent(program) {
474
474
 
475
475
  // Re-export lib functions for backward compatibility
476
476
  // (agent-docs.mjs, tests, and generate-skill-doc.sh import from here)
477
- export {discoverComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '../../../../foundation/discovery/component-discovery.mjs';
478
- export {discoverExternalPackages} from '../../../../foundation/fs/paths.mjs';
479
- export {loadDocs} from '../../../../foundation/discovery/component-loader.mjs';
480
- export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '../../lib/component-format.mjs';
481
- export {levenshteinDistance, findClosestComponents, searchComponents} from '../../../../foundation/text/string-utils.mjs';
477
+ export {discoverComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '../../../foundation/discovery/component-discovery.mjs';
478
+ export {discoverExternalPackages} from '../../../foundation/fs/paths.mjs';
479
+ export {loadDocs} from '../../../foundation/discovery/component-loader.mjs';
480
+ export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '../lib/component-format.mjs';
481
+ export {levenshteinDistance, findClosestComponents, searchComponents} from '../../../foundation/text/string-utils.mjs';
@@ -12,7 +12,7 @@ import {
12
12
  findComponentSource,
13
13
  levenshteinDistance,
14
14
  findClosestComponents,
15
- } from './component/index.mjs';
15
+ } from './component.mjs';
16
16
  import {runCli} from '../../../test-utils/run-cli.mjs';
17
17
 
18
18
  const REPO_ROOT = path.resolve(import.meta.dirname, '../../../../..');
@@ -528,7 +528,7 @@ describe('findExternalComponentDoc', () => {
528
528
  describe('searchComponents', () => {
529
529
  it('finds Collapsible when searching "accordion"', async () => {
530
530
  const {searchComponents, discoverComponents} =
531
- await import('./component/index.mjs');
531
+ await import('./component.mjs');
532
532
  const components = discoverComponents('packages/core');
533
533
  const results = await searchComponents(
534
534
  'accordion',
@@ -542,7 +542,7 @@ describe('searchComponents', () => {
542
542
 
543
543
  it('finds Dialog when searching "modal"', async () => {
544
544
  const {searchComponents, discoverComponents} =
545
- await import('./component/index.mjs');
545
+ await import('./component.mjs');
546
546
  const components = discoverComponents('packages/core');
547
547
  const results = await searchComponents(
548
548
  'modal',
@@ -556,7 +556,7 @@ describe('searchComponents', () => {
556
556
 
557
557
  it('returns multiple matches for ambiguous terms like "select"', async () => {
558
558
  const {searchComponents, discoverComponents} =
559
- await import('./component/index.mjs');
559
+ await import('./component.mjs');
560
560
  const components = discoverComponents('packages/core');
561
561
  const results = await searchComponents(
562
562
  'select',
@@ -571,7 +571,7 @@ describe('searchComponents', () => {
571
571
 
572
572
  it('finds exact name matches with score 100', async () => {
573
573
  const {searchComponents, discoverComponents} =
574
- await import('./component/index.mjs');
574
+ await import('./component.mjs');
575
575
  const components = discoverComponents('packages/core');
576
576
  const results = await searchComponents(
577
577
  'Button',
@@ -584,7 +584,7 @@ describe('searchComponents', () => {
584
584
 
585
585
  it('returns empty array for complete gibberish', async () => {
586
586
  const {searchComponents, discoverComponents} =
587
- await import('./component/index.mjs');
587
+ await import('./component.mjs');
588
588
  const components = discoverComponents('packages/core');
589
589
  const results = await searchComponents(
590
590
  'zzzzzzzzzzz',
@@ -68,8 +68,8 @@ describe('astryx discover with a manifest that fails to load', () => {
68
68
  const {status, stdout, stderr} = await runCli(['discover'], {cwd: project});
69
69
 
70
70
  expect(status).toBe(0);
71
- expect(stderr).toContain(
72
- 'Warning: @test/broken has 1 integration issue(s). Run: astryx doctor',
71
+ expect(stderr).toMatch(
72
+ /Warning: @test\/broken has 1 integration issue\(s\)\. Run: .+ doctor/,
73
73
  );
74
74
  expect(stdout).not.toContain('No integrations configured.');
75
75
  expect(stdout).toContain(
@@ -83,7 +83,11 @@ describe('astryx discover with a manifest that fails to load', () => {
83
83
  });
84
84
 
85
85
  expect(status).toBe(0);
86
- expect(JSON.parse(stdout).meta).toEqual({configured: true});
86
+ const {meta} = JSON.parse(stdout);
87
+ expect(meta.configured).toBe(true);
88
+ // The official list still answers; nothing else is claimed.
89
+ expect(meta.sources.map(s => s.name)).toEqual(['Astryx']);
90
+ expect(meta.answeredBy).toEqual(expect.any(Object));
87
91
  expect(stderr).not.toContain('integration issue');
88
92
  });
89
93
  });
@@ -129,8 +133,8 @@ describe('astryx discover with a configured package that is not installed', () =
129
133
  const {status, stderr} = await runCli(['discover'], {cwd: project});
130
134
 
131
135
  expect(status).toBe(0);
132
- expect(stderr).toContain(
133
- 'Warning: @test/missing has 1 integration issue(s). Run: astryx doctor\n',
136
+ expect(stderr).toMatch(
137
+ /Warning: @test\/missing has 1 integration issue\(s\)\. Run: .+ doctor\n/,
134
138
  );
135
139
  });
136
140
  });
@@ -148,8 +152,8 @@ describe('astryx search with a manifest that fails to load', () => {
148
152
  const {status, stderr} = await runCli(['search', 'button'], {cwd: project});
149
153
 
150
154
  expect(status).toBe(0);
151
- expect(stderr).toContain(
152
- 'Warning: @test/broken has 1 integration issue(s). Run: astryx doctor',
155
+ expect(stderr).toMatch(
156
+ /Warning: @test\/broken has 1 integration issue\(s\)\. Run: .+ doctor/,
153
157
  );
154
158
 
155
159
  const asJson = await runCli(['search', 'button', '--json'], {cwd: project});