@astryxdesign/cli 0.7.2 → 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 (373) hide show
  1. package/README.md +104 -71
  2. package/api/build/_adapter.d.mts +58 -0
  3. package/api/build/_adapter.mjs +127 -3
  4. package/api/build/blocks/blocks.d.mts +92 -0
  5. package/api/build/blocks/blocks.mjs +528 -0
  6. package/api/build/blocks/blocks.test.mjs +238 -0
  7. package/api/build/blocks/blocks.weights.json +1 -0
  8. package/api/build/build.mjs +25 -6
  9. package/api/build/build.type.mjs +1 -1
  10. package/api/build/kit/answer.d.mts +18 -0
  11. package/api/build/kit/answer.mjs +195 -0
  12. package/api/build/kit/answer.test.mjs +108 -0
  13. package/api/build/kit/kind.d.mts +25 -0
  14. package/api/build/kit/kind.mjs +170 -0
  15. package/api/build/kit/kit.d.mts +2 -4
  16. package/api/build/kit/kit.mjs +8 -398
  17. package/api/build/kit/rank.d.mts +3 -32
  18. package/api/build/kit/rank.mjs +25 -342
  19. package/api/build/kit/rank.test.mjs +2 -1
  20. package/api/build/kit/signals.d.mts +79 -0
  21. package/api/build/kit/signals.mjs +295 -0
  22. package/api/build/kit/start.d.mts +32 -0
  23. package/api/build/kit/start.mjs +163 -0
  24. package/api/build/kit/words.d.mts +72 -0
  25. package/api/build/kit/words.mjs +202 -0
  26. package/api/build/tree.d.mts +20 -0
  27. package/api/build/tree.mjs +53 -0
  28. package/api/build/tree.test.mjs +185 -0
  29. package/api/build/tree.weights.json +1 -0
  30. package/api/component/_adapter.mjs +39 -5
  31. package/api/component/component-replacement.test.mjs +1 -0
  32. package/api/component/component.mjs +17 -3
  33. package/api/component/component.test.mjs +15 -0
  34. package/api/component/doc-links.test.mjs +2 -2
  35. package/api/discover/_adapter.d.mts +1 -2
  36. package/api/discover/_adapter.mjs +42 -17
  37. package/api/discover/_adapter.test.mjs +42 -0
  38. package/api/discover/discover.mjs +0 -1
  39. package/api/docs/_adapter.d.mts +2 -2
  40. package/api/docs/_adapter.mjs +82 -23
  41. package/api/docs/docs-homes.test.mjs +127 -0
  42. package/api/docs/docs.doc.mjs +3 -3
  43. package/api/docs/docs.test.mjs +35 -19
  44. package/api/docs/integration-tree.test.mjs +20 -20
  45. package/api/docs/integrationDocs.test.mjs +1 -1
  46. package/api/docs/namespace-section.test.mjs +6 -6
  47. package/api/docs/reference-blocks.test.mjs +2 -2
  48. package/api/doctor/_adapter.d.mts +33 -13
  49. package/api/doctor/_adapter.mjs +55 -25
  50. package/api/doctor/doctor.d.mts +23 -5
  51. package/api/doctor/doctor.mjs +183 -40
  52. package/api/doctor/doctor.test.mjs +95 -12
  53. package/api/hook/hook.mjs +1 -1
  54. package/api/init/init.doc.mjs +20 -6
  55. package/api/init/init.test.mjs +18 -2
  56. package/api/init/init.type.d.mts +3 -3
  57. package/api/init/init.type.mjs +3 -3
  58. package/api/init/remove/remove.mjs +17 -4
  59. package/api/init/remove/remove.test.mjs +114 -2
  60. package/api/init/run/run.mjs +69 -6
  61. package/api/integration/_adapter.d.mts +8 -0
  62. package/api/integration/_adapter.mjs +21 -1
  63. package/api/integration/authoring-checks.mjs +83 -9
  64. package/api/integration/authoring-checks.test.mjs +220 -0
  65. package/api/integration/pack-check.mjs +123 -4
  66. package/api/integration/pack-check.test.mjs +87 -0
  67. package/api/integration/validate-integration-case-disk.test.mjs +111 -0
  68. package/api/integration/validate-integration-fixes.test.mjs +6 -5
  69. package/api/integration/validate-integration-gaps.test.mjs +1975 -0
  70. package/api/integration/validate-integration.d.mts +15 -2
  71. package/api/integration/validate-integration.mjs +298 -39
  72. package/api/integration/validate-integration.type.d.mts +90 -1
  73. package/api/integration/validate-integration.type.mjs +67 -2
  74. package/api/integration/validateIntegration.doc.mjs +1 -1
  75. package/api/search/ORDERING.md +28 -0
  76. package/api/search/_adapter.d.mts +82 -2
  77. package/api/search/_adapter.mjs +157 -10
  78. package/api/search/_adapter.test.mjs +173 -0
  79. package/api/search/_candidate-score.d.mts +40 -0
  80. package/api/search/_candidate-score.mjs +238 -0
  81. package/api/search/_cards.json +6098 -0
  82. package/api/search/_compound.d.mts +50 -0
  83. package/api/search/_compound.mjs +170 -0
  84. package/api/search/_doc-searcher.d.mts +4 -0
  85. package/api/search/_doc-searcher.mjs +23 -0
  86. package/api/search/_doc-searcher.test.mjs +36 -0
  87. package/api/search/_doc-searcher.weights.json +1 -0
  88. package/api/search/_doc-text.d.mts +30 -0
  89. package/api/search/_doc-text.mjs +87 -0
  90. package/api/search/_entries.d.mts +63 -0
  91. package/api/search/_entries.mjs +232 -0
  92. package/api/search/_entries.test.mjs +48 -0
  93. package/api/search/_features.d.mts +35 -0
  94. package/api/search/_features.mjs +155 -0
  95. package/api/search/_gather-components.d.mts +26 -0
  96. package/api/search/_gather-components.mjs +284 -0
  97. package/api/search/_gather-docs.d.mts +20 -0
  98. package/api/search/_gather-docs.mjs +254 -0
  99. package/api/search/_gather-hooks.d.mts +12 -0
  100. package/api/search/_gather-hooks.mjs +52 -0
  101. package/api/search/_gather-templates.d.mts +25 -0
  102. package/api/search/_gather-templates.mjs +107 -0
  103. package/api/search/_lexical.d.mts +135 -0
  104. package/api/search/_lexical.mjs +351 -0
  105. package/api/search/_main-searcher.d.mts +19 -0
  106. package/api/search/_main-searcher.mjs +115 -0
  107. package/api/search/_main-searcher.test.mjs +106 -0
  108. package/api/search/_main-searcher.weights.json +1 -0
  109. package/api/search/_module-doc.d.mts +32 -0
  110. package/api/search/_module-doc.mjs +78 -0
  111. package/api/search/_order.d.mts +32 -0
  112. package/api/search/_order.mjs +162 -0
  113. package/api/search/_order.test.mjs +72 -0
  114. package/api/search/_priority.d.mts +50 -0
  115. package/api/search/_priority.mjs +139 -0
  116. package/api/search/_query-words.d.mts +25 -0
  117. package/api/search/_query-words.mjs +92 -0
  118. package/api/search/_query.d.mts +65 -0
  119. package/api/search/_query.mjs +176 -0
  120. package/api/search/_result.d.mts +97 -0
  121. package/api/search/_result.mjs +150 -0
  122. package/api/search/_score.d.mts +60 -0
  123. package/api/search/_score.mjs +283 -0
  124. package/api/search/_synonyms.d.mts +21 -0
  125. package/api/search/_synonyms.mjs +67 -0
  126. package/api/search/_template-searcher.d.mts +4 -0
  127. package/api/search/_template-searcher.mjs +23 -0
  128. package/api/search/_template-searcher.test.mjs +40 -0
  129. package/api/search/_template-searcher.weights.json +1 -0
  130. package/api/search/_titles.d.mts +33 -0
  131. package/api/search/_titles.mjs +65 -0
  132. package/api/search/_words.d.mts +64 -0
  133. package/api/search/_words.mjs +157 -0
  134. package/api/search/search.d.mts +22 -305
  135. package/api/search/search.doc.mjs +8 -6
  136. package/api/search/search.mjs +56 -2482
  137. package/api/search/search.test.mjs +14 -14
  138. package/api/search/search.type.d.mts +6 -1
  139. package/api/search/search.type.mjs +6 -1
  140. package/api/search/tree.d.mts +15 -0
  141. package/api/search/tree.mjs +40 -0
  142. package/api/search/tree.test.mjs +66 -0
  143. package/api/search/tree.weights.json +1 -0
  144. package/api/template/template.mjs +5 -1
  145. package/api/theme/build/build.packed-old-core.test.mjs +1 -0
  146. package/api/upgrade/_adapter.d.mts +57 -9
  147. package/api/upgrade/_adapter.mjs +198 -28
  148. package/api/upgrade/registry/registry.d.mts +10 -4
  149. package/api/upgrade/registry/registry.mjs +33 -16
  150. package/api/upgrade/registry/registry.test.mjs +85 -0
  151. package/api/upgrade/run/run.d.mts +4 -2
  152. package/api/upgrade/run/run.mjs +13 -2
  153. package/api/upgrade/run/run.test.mjs +417 -3
  154. package/api/upgrade/upgrade.doc.mjs +10 -5
  155. package/api/upgrade/upgrade.mjs +13 -2
  156. package/api/upgrade/upgrade.test.mjs +194 -0
  157. package/api/upgrade/upgrade.type.d.mts +5 -3
  158. package/api/upgrade/upgrade.type.mjs +8 -6
  159. package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
  160. package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
  161. package/assets/docs/author-a-theme.doc.mjs +2 -2
  162. package/assets/docs/is-my-code-good.doc.mjs +287 -0
  163. package/assets/docs/tree/add-a-component.doc.mjs +1 -1
  164. package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
  165. package/assets/docs/tree/add-a-topic.doc.mjs +2 -2
  166. package/assets/docs/tree/agent-guidance.doc.mjs +1 -1
  167. package/assets/docs/tree/api.doc.mjs +6 -0
  168. package/assets/docs/tree/{integrations.doc.mjs → authoring.doc.mjs} +15 -6
  169. package/assets/docs/tree/block-template.doc.mjs +1 -1
  170. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  171. package/assets/docs/tree/building-blocks.doc.mjs +2 -2
  172. package/assets/docs/tree/check-the-props.doc.mjs +1 -1
  173. package/assets/docs/tree/check-your-docs.doc.mjs +2 -2
  174. package/assets/docs/tree/checks.doc.mjs +3 -3
  175. package/assets/docs/tree/ci-and-containers.doc.mjs +13 -0
  176. package/assets/docs/tree/cli-command.doc.mjs +1 -1
  177. package/assets/docs/tree/cli.doc.mjs +1 -1
  178. package/assets/docs/tree/codemods.doc.mjs +1 -1
  179. package/assets/docs/tree/component-family.doc.mjs +1 -1
  180. package/assets/docs/tree/component-imports.doc.mjs +1 -1
  181. package/assets/docs/tree/components.doc.mjs +1 -1
  182. package/assets/docs/tree/configuration.doc.mjs +1 -1
  183. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +1 -1
  184. package/assets/docs/tree/define-the-theme.doc.mjs +1 -1
  185. package/assets/docs/tree/describe-the-component.doc.mjs +1 -1
  186. package/assets/docs/tree/docs.doc.mjs +1 -1
  187. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  188. package/assets/docs/tree/document-the-theme.doc.mjs +1 -1
  189. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  190. package/assets/docs/tree/extend-or-replace.doc.mjs +1 -1
  191. package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
  192. package/assets/docs/tree/fonts-and-assets.doc.mjs +1 -1
  193. package/assets/docs/tree/generate-a-palette.doc.mjs +1 -1
  194. package/assets/docs/tree/global-integrations.doc.mjs +2 -2
  195. package/assets/docs/tree/grade-template-with-agent.doc.mjs +4 -4
  196. package/assets/docs/tree/help.doc.mjs +2 -2
  197. package/assets/docs/tree/host-entry.doc.mjs +128 -0
  198. package/assets/docs/tree/links.doc.mjs +1 -1
  199. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  200. package/assets/docs/tree/page-template.doc.mjs +1 -1
  201. package/assets/docs/tree/publishing.doc.mjs +1 -1
  202. package/assets/docs/tree/quick-start.doc.mjs +1 -1
  203. package/assets/docs/tree/replace-a-core-component.doc.mjs +1 -1
  204. package/assets/docs/tree/replace-a-core-template.doc.mjs +1 -1
  205. package/assets/docs/tree/sections-and-placement.doc.mjs +1 -1
  206. package/assets/docs/tree/see-it-in-an-app.doc.mjs +1 -1
  207. package/assets/docs/tree/ship.doc.mjs +2 -2
  208. package/assets/docs/tree/short-and-findable.doc.mjs +1 -1
  209. package/assets/docs/tree/single-component.doc.mjs +1 -1
  210. package/assets/docs/tree/start-a-template.doc.mjs +1 -1
  211. package/assets/docs/tree/subcomponent.doc.mjs +1 -1
  212. package/assets/docs/tree/template-assets.doc.mjs +1 -1
  213. package/assets/docs/tree/template-doc-overview.doc.mjs +2 -2
  214. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  215. package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
  216. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  217. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  218. package/assets/docs/tree/template-styles.doc.mjs +1 -1
  219. package/assets/docs/tree/templates.doc.mjs +1 -1
  220. package/assets/docs/tree/test-in-an-app.doc.mjs +1 -1
  221. package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
  222. package/assets/docs/tree/themes.doc.mjs +1 -1
  223. package/assets/docs/tree/tokens-data.doc.mjs +2 -2
  224. package/assets/docs/tree/troubleshooting.doc.mjs +1 -1
  225. package/assets/docs/tree/upgrading.doc.mjs +1 -1
  226. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +1 -1
  227. package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
  228. package/assets/docs/tree/versioning.doc.mjs +5 -1
  229. package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
  230. package/assets/docs/tree/write-the-template-file.doc.mjs +1 -1
  231. package/assets/docs/use-integrations.doc.mjs +120 -0
  232. package/assets/docs/working-with-ai.doc.mjs +6 -2
  233. package/assets/templates/themes/butter/butterTheme.ts +4 -2
  234. package/assets/templates/themes/stone/stoneTheme.ts +4 -2
  235. package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
  236. package/authoring/debug/parse.d.mts +1 -1
  237. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  238. package/authoring/integration/integration.doc.mjs +1 -1
  239. package/authoring/integration/type.ts +1 -1
  240. package/clients/cli/bin/astryx.mjs +7 -78
  241. package/clients/cli/command-result-coverage.test.mjs +6 -5
  242. package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
  243. package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
  244. package/clients/cli/commands/component.test.mjs +6 -6
  245. package/clients/cli/commands/docs.doc.mjs +2 -2
  246. package/clients/cli/commands/docs.mjs +1 -1
  247. package/clients/cli/commands/docs.test.mjs +14 -14
  248. package/clients/cli/commands/doctor-integration.test.mjs +49 -1
  249. package/clients/cli/commands/doctor.doc.mjs +1 -1
  250. package/clients/cli/commands/doctor.mjs +40 -0
  251. package/clients/cli/commands/doctor.test.mjs +65 -0
  252. package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
  253. package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
  254. package/clients/cli/commands/init.behavior.test.mjs +230 -1
  255. package/clients/cli/commands/init.doc.mjs +28 -9
  256. package/clients/cli/commands/init.flag-help.test.mjs +1 -0
  257. package/clients/cli/commands/init.mjs +2 -2
  258. package/clients/cli/commands/integration-check.test.mjs +48 -0
  259. package/clients/cli/commands/integration.doc.mjs +1 -1
  260. package/clients/cli/commands/manifest.doc.mjs +1 -1
  261. package/clients/cli/commands/manifest.mjs +67 -0
  262. package/clients/cli/commands/outside-project.test.mjs +101 -1
  263. package/clients/cli/commands/postinstall.doc.mjs +23 -0
  264. package/clients/cli/commands/postinstall.mjs +31 -0
  265. package/clients/cli/commands/setup-nudge.test.mjs +78 -0
  266. package/clients/cli/commands/{build-theme.mjs → theme.mjs} +1 -1
  267. package/clients/cli/commands/upgrade.doc.mjs +4 -2
  268. package/clients/cli/commands/upgrade.mjs +9 -2
  269. package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
  270. package/clients/cli/index.mjs +54 -94
  271. package/clients/cli/lib/component-format.mjs +1 -1
  272. package/clients/cli/lib/define-command.mjs +12 -7
  273. package/clients/cli/lib/exit-codes.test.mjs +5 -0
  274. package/clients/cli/lib/manifest.test.mjs +12 -0
  275. package/clients/cli/lib/welcome-box.mjs +50 -0
  276. package/clients/cli/run.mjs +108 -0
  277. package/foundation/agent-docs/agent-doc-state.d.mts +32 -7
  278. package/foundation/agent-docs/agent-doc-state.mjs +58 -9
  279. package/foundation/agent-docs/agent-docs.d.mts +100 -12
  280. package/foundation/agent-docs/agent-docs.mjs +1017 -105
  281. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
  282. package/foundation/agent-docs/agent-docs.test.mjs +683 -39
  283. package/foundation/agent-docs/computer-agent-text.d.mts +39 -2
  284. package/foundation/agent-docs/computer-agent-text.mjs +135 -8
  285. package/foundation/agent-docs/computer-agent-text.test.mjs +99 -2
  286. package/foundation/config/project.mjs +20 -22
  287. package/foundation/config/project.test.mjs +56 -0
  288. package/foundation/discovery/authoring-self-docs.d.mts +7 -0
  289. package/foundation/discovery/authoring-self-docs.mjs +16 -4
  290. package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
  291. package/foundation/discovery/authoring-surface.d.mts +1 -1
  292. package/foundation/discovery/authoring-surface.mjs +2 -2
  293. package/foundation/discovery/authoring-surface.test.mjs +1 -1
  294. package/foundation/discovery/cli-self-docs.d.mts +2 -1
  295. package/foundation/discovery/cli-self-docs.mjs +4 -3
  296. package/foundation/discovery/cli-self-docs.test.mjs +2 -2
  297. package/foundation/discovery/component-discovery.d.mts +37 -0
  298. package/foundation/discovery/component-discovery.mjs +80 -5
  299. package/foundation/discovery/component-loader.d.mts +1 -1
  300. package/foundation/discovery/docs-discovery.mjs +14 -1
  301. package/foundation/discovery/module-exports.d.mts +41 -0
  302. package/foundation/discovery/module-exports.mjs +253 -0
  303. package/foundation/discovery/runner-allowlist.d.mts +2 -4
  304. package/foundation/discovery/runner-allowlist.mjs +2 -4
  305. package/foundation/discovery/runner-commands.d.mts +77 -0
  306. package/foundation/discovery/runner-commands.mjs +294 -0
  307. package/foundation/discovery/runner-commands.test.mjs +128 -0
  308. package/foundation/discovery/stray-pointers.test.mjs +1 -1
  309. package/foundation/discovery/template-adapter.mjs +18 -1
  310. package/foundation/discovery/template-needs.mjs +1 -44
  311. package/foundation/discovery/theme-discovery.mjs +147 -3
  312. package/foundation/doc-compiler/doc-loads.test.mjs +33 -9
  313. package/foundation/doc-compiler/read.mjs +59 -1
  314. package/foundation/doc-compiler/read.test.mjs +11 -2
  315. package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
  316. package/foundation/doc-compiler/tree.d.mts +32 -6
  317. package/foundation/doc-compiler/tree.mjs +77 -43
  318. package/foundation/doc-compiler/tree.test.mjs +7 -7
  319. package/foundation/fs/paths.d.mts +70 -8
  320. package/foundation/fs/paths.mjs +556 -38
  321. package/foundation/fs/paths.test.mjs +430 -54
  322. package/foundation/fs/read-record.d.mts +18 -0
  323. package/foundation/fs/read-record.mjs +131 -0
  324. package/foundation/fs/read-record.test.mjs +77 -0
  325. package/foundation/integrations/autolink.d.mts +2 -1
  326. package/foundation/integrations/autolink.mjs +4 -13
  327. package/foundation/integrations/cli-peer-version.d.mts +36 -0
  328. package/foundation/integrations/cli-peer-version.mjs +132 -0
  329. package/foundation/integrations/cli-peer-version.test.mjs +354 -0
  330. package/foundation/integrations/computer-integrations.d.mts +6 -3
  331. package/foundation/integrations/computer-integrations.mjs +38 -9
  332. package/foundation/integrations/contribution-inventory.d.mts +15 -20
  333. package/foundation/integrations/contribution-inventory.mjs +41 -5
  334. package/foundation/integrations/exports-subpaths.d.mts +57 -0
  335. package/foundation/integrations/exports-subpaths.mjs +113 -0
  336. package/foundation/integrations/integrations.d.mts +27 -1
  337. package/foundation/integrations/integrations.mjs +61 -2
  338. package/foundation/integrations/public-imports.d.mts +118 -0
  339. package/foundation/integrations/public-imports.mjs +1769 -0
  340. package/foundation/integrations/public-imports.test.mjs +1793 -0
  341. package/foundation/integrations/validate-contributions.d.mts +115 -0
  342. package/foundation/integrations/validate-contributions.mjs +1168 -13
  343. package/foundation/release/cache.test.mjs +24 -21
  344. package/foundation/release/global-state.d.mts +8 -4
  345. package/foundation/release/global-state.mjs +4 -2
  346. package/foundation/release/handoff.d.mts +23 -4
  347. package/foundation/release/handoff.mjs +175 -8
  348. package/foundation/release/notices.d.mts +62 -8
  349. package/foundation/release/notices.mjs +136 -25
  350. package/foundation/release/notices.test.mjs +21 -0
  351. package/foundation/release/run-context.mjs +14 -0
  352. package/foundation/response/response-types.doc.mjs +1 -1
  353. package/foundation/route/route.d.mts +285 -0
  354. package/foundation/route/route.mjs +324 -0
  355. package/foundation/route/route.test.mjs +153 -0
  356. package/foundation/runtime/hosted-runtime.test.mjs +403 -0
  357. package/foundation/runtime/locked-versions.d.mts +32 -0
  358. package/foundation/runtime/locked-versions.mjs +65 -0
  359. package/foundation/runtime/package-root.d.mts +91 -0
  360. package/foundation/runtime/package-root.mjs +174 -0
  361. package/foundation/runtime/package-set.d.mts +62 -0
  362. package/foundation/runtime/package-set.mjs +130 -0
  363. package/foundation/runtime/package-set.test.mjs +432 -0
  364. package/foundation/text/string-utils.d.mts +2 -1
  365. package/foundation/text/string-utils.mjs +16 -5
  366. package/foundation/text/suggest-order.d.mts +72 -0
  367. package/foundation/text/suggest-order.mjs +363 -0
  368. package/foundation/text/suggest-order.test.mjs +259 -0
  369. package/host/door-conformance.test.mjs +274 -0
  370. package/host/index.d.ts +116 -0
  371. package/host/index.mjs +295 -0
  372. package/host/index.test.mjs +302 -0
  373. package/package.json +14 -9
@@ -10,7 +10,8 @@
10
10
  */
11
11
  export function validateLocalIntegration(cwd?: string): Promise<ValidateResult>;
12
12
  /**
13
- * Validate an INSTALLED integration package resolved from `cwd`/node_modules.
13
+ * Validate an INSTALLED integration package: the nearest `node_modules/<spec>`
14
+ * at or above `cwd`, resolved the way the project loads it.
14
15
  * @param {string} spec package name
15
16
  * @param {string} [cwd]
16
17
  * @returns {Promise<ValidateResult>}
@@ -43,7 +44,6 @@ export function summarizeIssues(issues: Issue[]): {
43
44
  errors: number;
44
45
  warnings: number;
45
46
  };
46
- export { validateLoadedIntegration };
47
47
  export type Issue = import("../../foundation/integrations/issue").AstryxIntegrationIssue;
48
48
  export type ValidateResult = {
49
49
  /**
@@ -75,6 +75,19 @@ export type ValidateResult = {
75
75
  code: string;
76
76
  message: string;
77
77
  }[] | undefined;
78
+ /**
79
+ * Layout findings added after the last minor
80
+ * release: validate lists them as notes, which count nowhere, since they
81
+ * may not fail `--strict` until the next (architecture:cli-surface INV35);
82
+ * `integration verify` still fails on a package.json npm cannot pack.
83
+ */
84
+ listed?: import("../../foundation/integrations/issue").AstryxIntegrationIssue[] | undefined;
78
85
  integration?: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | undefined;
86
+ /**
87
+ * what the public-import check could not judge
88
+ */
89
+ publicImports?: import("./validate-integration.type.mjs").PublicImportsReport | undefined;
79
90
  };
80
91
  import { validateLoadedIntegration } from '../../foundation/integrations/validate-contributions.mjs';
92
+ import { isListedIssue } from '../../foundation/integrations/validate-contributions.mjs';
93
+ export { validateLoadedIntegration, isListedIssue };
@@ -12,7 +12,7 @@
12
12
  * - validateLocalIntegration(cwd) — the package rooted at `cwd` (nearest
13
13
  * package.json + sibling astryx.integration.{ts,mjs,js}).
14
14
  * - validateInstalledIntegration(spec, cwd) — an installed package resolved
15
- * from `cwd`/node_modules.
15
+ * from the node_modules chain at or above `cwd`.
16
16
  *
17
17
  * Both return a { found, name, version, manifestFile, issues } result. `found`
18
18
  * is false only for the no-manifest local case, which is guidance (not an
@@ -34,8 +34,10 @@
34
34
  import * as fs from 'node:fs';
35
35
  import * as path from 'node:path';
36
36
  import {assertWithin} from '../../foundation/fs/path-safety.mjs';
37
+ import {normalizeProviderId} from '../../foundation/identity/provider-identity.mjs';
37
38
  import {integrationDocTypes} from '../docs/_adapter.mjs';
38
39
  import {integrationDocConsistency} from '../../foundation/discovery/doc-consistency.mjs';
40
+ import {integrationRunnerCommands} from './_adapter.mjs';
39
41
  import {
40
42
  THEME_SLUG_RE,
41
43
  unreadThemeFolders,
@@ -51,20 +53,31 @@ import {
51
53
  import {
52
54
  findManifestPaths,
53
55
  loadManifest,
54
- resolvePackageDir,
56
+ resolveInstalledIntegrationDir,
55
57
  } from '../../foundation/integrations/integrations.mjs';
56
58
  // The on-disk contribution validators live in foundation: Project and
57
59
  // integration-warnings need them too, and foundation must not depend on api.
58
60
  import {
61
+ blockComponentsCheck,
62
+ componentDocNamesCheck,
59
63
  INVALID_CLI_COMMAND,
64
+ isListedIssue,
65
+ issueListed as listed,
60
66
  validateLoadedIntegration,
67
+ validateLoadedIntegrationListed,
61
68
  issueError as error,
62
69
  issueWarning as warning,
63
70
  rootProblem,
64
71
  } from '../../foundation/integrations/validate-contributions.mjs';
65
72
  import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
73
+ import {cliPeerVersionProblem} from '../../foundation/integrations/cli-peer-version.mjs';
74
+ import {publicImportIssues} from '../../foundation/integrations/public-imports.mjs';
75
+ import {runChoice} from '../../foundation/release/run-context.mjs';
66
76
 
67
- export {validateLoadedIntegration};
77
+ /** The running CLI is outside the package's `@astryxdesign/cli` peer range. */
78
+ const CLI_PEER_VERSION = 'cli_peer_version';
79
+
80
+ export {validateLoadedIntegration, isListedIssue};
68
81
 
69
82
  /**
70
83
  * @typedef {import('../../foundation/integrations/issue').AstryxIntegrationIssue} Issue
@@ -80,7 +93,13 @@ export {validateLoadedIntegration};
80
93
  * @property {Issue[]} issues
81
94
  * @property {Array<{code: string, message: string}>} [notes] Information that
82
95
  * fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
96
+ * @property {Issue[]} [listed] Layout findings added after the last minor
97
+ * release: validate lists them as notes, which count nowhere, since they
98
+ * may not fail `--strict` until the next (architecture:cli-surface INV35);
99
+ * `integration verify` still fails on a package.json npm cannot pack.
83
100
  * @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} [integration]
101
+ * @property {import('./validate-integration.type.mjs').PublicImportsReport} [publicImports]
102
+ * what the public-import check could not judge
84
103
  */
85
104
 
86
105
  /**
@@ -99,6 +118,14 @@ function findNearestPackageJson(cwd) {
99
118
  }
100
119
  }
101
120
 
121
+ const ROOT_KINDS = /** @type {const} */ ([
122
+ 'components',
123
+ 'templates',
124
+ 'codemods',
125
+ 'docs',
126
+ 'themes',
127
+ ]);
128
+
102
129
  const UNREACHABLE_SCAN_LIMIT = 5_000;
103
130
  const UNREACHABLE_SKIP_DIRS = new Set([
104
131
  'node_modules',
@@ -148,27 +175,51 @@ function unreadThemeFolderIssues(packageDir, loaded) {
148
175
  *
149
176
  * @param {string} packageDir
150
177
  * @param {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} loaded
178
+ * @param {string[]} [reported] folders whose files another issue already covers
151
179
  * @returns {Promise<Issue[]>}
152
180
  */
153
- async function findUnreachableContributionIssues(packageDir, loaded) {
181
+ async function findUnreachableContributionIssues(
182
+ packageDir,
183
+ loaded,
184
+ reported = [],
185
+ ) {
186
+ // A root that is not a readable folder holds nothing: a fix must never
187
+ // send a file into it.
188
+ const usable = {...loaded};
189
+ for (const kind of ROOT_KINDS) {
190
+ const root = usable[kind];
191
+ if (root != null && rootProblem(root)) usable[kind] = undefined;
192
+ }
193
+ // Every declared root is skipped, readable or not: one that cannot be read
194
+ // has its own issue.
154
195
  const roots = /** @type {string[]} */ (
155
- [
156
- loaded.components,
157
- loaded.templates,
158
- loaded.codemods,
159
- loaded.docs,
160
- loaded.themes,
161
- ].filter(Boolean)
196
+ ROOT_KINDS.map(kind => loaded[kind]).filter(Boolean)
162
197
  );
198
+ // A folder a symlinked root points at is read through that root.
199
+ const realRoots = roots.map(root => {
200
+ try {
201
+ return fs.realpathSync(root);
202
+ } catch {
203
+ return root;
204
+ }
205
+ });
163
206
  /** @type {Issue[]} */
164
207
  const issues = [];
165
- const context = createFixContext(packageDir, loaded);
208
+ const context = createFixContext(packageDir, usable);
166
209
  let scanned = 0;
167
210
  let truncated = false;
168
211
 
169
212
  /** @param {string} dir */
170
213
  async function walk(dir) {
171
214
  if (roots.some(root => pathIsInside(dir, root))) return;
215
+ if (reported.some(folder => pathIsInside(dir, folder))) return;
216
+ let realDir = dir;
217
+ try {
218
+ realDir = fs.realpathSync(dir);
219
+ } catch {
220
+ // Unreadable: reported below.
221
+ }
222
+ if (realRoots.some(root => pathIsInside(realDir, root))) return;
172
223
  let entries;
173
224
  try {
174
225
  entries = fs
@@ -235,13 +286,15 @@ async function findUnreachableContributionIssues(packageDir, loaded) {
235
286
  * Shared core for the local and installed entry points.
236
287
  * @param {string} packageDir
237
288
  * @param {{name: string, version?: string}} identity
238
- * @param {{scanUnreachable?: boolean}} [options]
289
+ * @param {{scanUnreachable?: boolean, own?: boolean, cwd?: string}} [options]
290
+ * `own`: the package is the one being authored in the current folder;
291
+ * `cwd`: the folder whose package manager an install command names
239
292
  * @returns {Promise<ValidateResult>}
240
293
  */
241
294
  async function validateAtPackageDir(
242
295
  packageDir,
243
296
  identity,
244
- {scanUnreachable = false} = {},
297
+ {scanUnreachable = false, own = false, cwd = packageDir} = {},
245
298
  ) {
246
299
  /** @type {Issue[]} */
247
300
  const issues = [];
@@ -286,12 +339,14 @@ async function validateAtPackageDir(
286
339
  let manifest;
287
340
  /** @type {string[]} */
288
341
  let unknownKeys;
342
+ /** @type {string[]} */
343
+ let declaredKeys;
289
344
  /** @type {string | undefined} */
290
345
  let agentDocsError;
291
346
  /** @type {string | undefined} */
292
347
  let cliCommandError;
293
348
  try {
294
- ({manifest, unknownKeys, agentDocsError, cliCommandError} =
349
+ ({manifest, unknownKeys, declaredKeys, agentDocsError, cliCommandError} =
295
350
  await loadManifest(
296
351
  manifestFile,
297
352
  `Integration manifest (${path.basename(manifestFile)})`,
@@ -301,9 +356,36 @@ async function validateAtPackageDir(
301
356
  return result;
302
357
  }
303
358
 
304
- /** @param {string | null | undefined} value */
305
- const resolveRoot = (value, kind = 'contribution root') => {
359
+ /** @type {string[]} absolute roots inside the package */
360
+ const absoluteRoots = [];
361
+ /**
362
+ * @param {string | null | undefined} value
363
+ * @param {string} key the manifest key that declares it
364
+ */
365
+ const resolveRoot = (value, key, kind = 'contribution root') => {
306
366
  if (value == null) return undefined;
367
+ if (path.isAbsolute(value)) {
368
+ // An absolute root names this machine's disk, which no install shares,
369
+ // even when it happens to point inside the package.
370
+ const inside = path.relative(packageDir, value);
371
+ const relative =
372
+ inside === '' || (!inside.startsWith('..') && !path.isAbsolute(inside))
373
+ ? `./${inside.split(path.sep).join('/')}`.replace(/\/$/u, '')
374
+ : null;
375
+ // The code an absolute root has always carried, reworded.
376
+ result.issues.push(
377
+ error(
378
+ 'root_outside_package',
379
+ `The ${key} root "${value}" is an absolute path, so Astryx reads nothing from it: a root is relative to the package, so it resolves the same wherever the package is installed.` +
380
+ (relative
381
+ ? ` Fix: set \`${key}: '${relative === './' ? '.' : relative}'\` in ${path.basename(manifestFile)}.`
382
+ : ` It also points outside the package. Fix: move the files into the package and set \`${key}\` to their folder relative to package.json, such as './${key}'.`),
383
+ ),
384
+ );
385
+ // Its files are reported through this issue, not one by one.
386
+ if (relative) absoluteRoots.push(path.resolve(value));
387
+ return undefined;
388
+ }
307
389
  try {
308
390
  return assertWithin(value, packageDir, {label: kind});
309
391
  } catch {
@@ -320,18 +402,20 @@ async function validateAtPackageDir(
320
402
  const loaded = {
321
403
  name: identity.name,
322
404
  version: identity.version,
323
- components: resolveRoot(manifest.components),
324
- templates: resolveRoot(manifest.templates),
325
- codemods: resolveRoot(manifest.codemods),
326
- docs: resolveRoot(manifest.docs),
327
- themes: resolveRoot(manifest.themes),
405
+ components: resolveRoot(manifest.components, 'components'),
406
+ templates: resolveRoot(manifest.templates, 'templates'),
407
+ codemods: resolveRoot(manifest.codemods, 'codemods'),
408
+ docs: resolveRoot(manifest.docs, 'docs'),
409
+ themes: resolveRoot(manifest.themes, 'themes'),
328
410
  issuesUrl: manifest.issuesUrl,
329
411
  agentDocs: manifest.agentDocs,
330
412
  cliCommand: manifest.cliCommand,
331
413
  __cliCommandError: cliCommandError,
332
414
  __agentDocsError: agentDocsError,
333
415
  __unknownKeys: unknownKeys,
416
+ __declaredKeys: declaredKeys,
334
417
  __spec: identity.name,
418
+ __declaredProviderId: manifest.providerId,
335
419
  __packageDir: packageDir,
336
420
  __manifestFile: manifestFile,
337
421
  };
@@ -343,13 +427,33 @@ async function validateAtPackageDir(
343
427
  // `integration check --strict` fails on any warning, and a new failure code
344
428
  // joins only in a minor release (architecture:cli-surface INV35). Doctor's
345
429
  // project check still warns about it.
346
- for (const issue of await validateLoadedIntegration(loaded)) {
430
+ const contribution = await validateLoadedIntegrationListed(loaded);
431
+ (result.listed ??= []).push(...contribution.listed);
432
+ for (const issue of contribution.issues) {
347
433
  if (issue.code === INVALID_CLI_COMMAND) {
348
434
  (result.notes ??= []).push({code: issue.code, message: issue.message});
349
435
  } else {
350
436
  issues.push(issue);
351
437
  }
352
438
  }
439
+ // The running CLI outside the package's `@astryxdesign/cli` peer range is a
440
+ // note for the same reason. It is built here, not among the contribution
441
+ // checks, so `integration verify` (which reports their layout findings)
442
+ // does not see it.
443
+ // The version an upgrade starts from is the project's: its own CLI's, or,
444
+ // with none, its Core's, as the project-upgrade notice takes it.
445
+ const choice = runChoice(cwd);
446
+ const from =
447
+ choice.inProject && choice.copy === 'starting' && choice.coreVersion
448
+ ? choice.coreVersion
449
+ : undefined;
450
+ const peerProblem = cliPeerVersionProblem(loaded, undefined, cwd, {
451
+ own,
452
+ from,
453
+ });
454
+ if (peerProblem) {
455
+ (result.notes ??= []).push({code: CLI_PEER_VERSION, message: peerProblem});
456
+ }
353
457
  if (loaded.themes && !rootProblem(loaded.themes))
354
458
  issues.push(...unreadThemeFolderIssues(packageDir, loaded));
355
459
  // What the docs say that no reader serves: a prop listed twice, an
@@ -368,9 +472,21 @@ async function validateAtPackageDir(
368
472
  packageDir,
369
473
  )),
370
474
  );
475
+ // What the package tells apps to import, read from source: package.json
476
+ // `exports`, docs, examples and template imports.
477
+ const publicImports = await publicImportIssues(packageDir, loaded);
478
+ issues.push(...publicImports.issues);
479
+ // Each finding is a note until the next minor makes it a warning.
480
+ if (publicImports.notes.length > 0)
481
+ (result.notes ??= []).push(...publicImports.notes);
482
+ result.publicImports = publicImports.report;
371
483
  if (scanUnreachable) {
372
484
  issues.push(
373
- ...(await findUnreachableContributionIssues(packageDir, loaded)),
485
+ ...(await findUnreachableContributionIssues(
486
+ packageDir,
487
+ loaded,
488
+ absoluteRoots,
489
+ )),
374
490
  );
375
491
  }
376
492
 
@@ -397,7 +513,7 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
397
513
  return {found: false, issues: []};
398
514
  }
399
515
 
400
- /** @type {{name?: string, version?: string}} */
516
+ /** @type {{name?: string, version?: string, private?: boolean}} */
401
517
  let pkg;
402
518
  try {
403
519
  pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
@@ -416,31 +532,121 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
416
532
  };
417
533
  }
418
534
 
419
- return validateAtPackageDir(
535
+ // npm publishes nothing without a name and a version, and the name is the
536
+ // provider ID every reader keys the package's contributions on.
537
+ // A package without one is still checked, under a placeholder name.
538
+ const fields = packageJsonFieldIssues(pkg, pkgJsonPath);
539
+ const name =
540
+ typeof pkg.name === 'string' && pkg.name !== ''
541
+ ? pkg.name
542
+ : '(local package)';
543
+ const result = await validateAtPackageDir(
420
544
  packageDir,
421
- {
422
- name: pkg.name ?? '(local package)',
423
- version: pkg.version,
424
- },
425
- {scanUnreachable: true},
545
+ {name, version: pkg.version},
546
+ {scanUnreachable: true, own: true},
426
547
  );
548
+ (result.listed ??= []).unshift(
549
+ ...fields,
550
+ // Only a manifest that loaded says whether it declares a providerId; one
551
+ // that did not is reported as invalid_manifest.
552
+ ...(result.integration
553
+ ? providerIdIssues(
554
+ pkg.name,
555
+ result.integration.__declaredProviderId,
556
+ result.integration.__manifestFile,
557
+ )
558
+ : []),
559
+ );
560
+ return result;
561
+ }
562
+
563
+ /**
564
+ * Whether `name` is a bare npm package name, the form a provider ID takes.
565
+ * @param {string} name
566
+ */
567
+ function isPackageName(name) {
568
+ try {
569
+ normalizeProviderId(name);
570
+ return true;
571
+ } catch {
572
+ return false;
573
+ }
427
574
  }
428
575
 
429
576
  /**
430
- * Validate an INSTALLED integration package resolved from `cwd`/node_modules.
577
+ * A warning when no provider ID can be derived for the package: its
578
+ * package.json `name` is not a bare package name and its manifest declares
579
+ * no `providerId` that is one. Readers key the package's contributions on
580
+ * that ID; a missing name is its own warning.
581
+ * @param {unknown} name package.json `name`
582
+ * @param {unknown} declared the manifest's `providerId`
583
+ * @param {string} manifestFile
584
+ * @returns {Issue[]}
585
+ */
586
+ function providerIdIssues(name, declared, manifestFile) {
587
+ if (typeof name !== 'string' || name === '') return [];
588
+ if (isPackageName(name)) return [];
589
+ if (typeof declared === 'string' && isPackageName(declared)) return [];
590
+ const manifest = path.basename(manifestFile);
591
+ return [
592
+ listed(
593
+ 'no_provider_id',
594
+ `No provider ID can be derived for this package: package.json "name" ${JSON.stringify(name)} is not a bare package name (an optional @scope/ and a name, each starting with a lowercase letter or digit and holding only lowercase letters, digits, "-", ".", "_" and "~"), and ${manifest} declares no providerId that is one. Astryx files the package's components, templates and docs under that ID, so links to them and selecting the package cannot work. Fix: rename the package, such as "@your-scope/your-package", or set \`providerId: '@your-scope/your-package'\` in ${manifest}.`,
595
+ ),
596
+ ];
597
+ }
598
+
599
+ /**
600
+ * A warning for each field npm needs that package.json lacks.
601
+ * @param {{name?: unknown, version?: unknown, private?: unknown}} pkg
602
+ * @param {string} pkgJsonPath
603
+ * @returns {Issue[]}
604
+ */
605
+ function packageJsonFieldIssues(pkg, pkgJsonPath) {
606
+ /** @type {Issue[]} */
607
+ const issues = [];
608
+ const shown = path.basename(pkgJsonPath);
609
+ // Listed, so validate and `--strict` keep the result they had for these
610
+ // packages; `integration verify`, which packs, reports them as errors.
611
+ if (typeof pkg.name !== 'string' || pkg.name === '') {
612
+ issues.push(
613
+ listed(
614
+ 'invalid_package_json',
615
+ `${shown} has no "name", so npm cannot pack or publish the package, and a project that installs it has no name to select it by. Fix: add "name": "@your-scope/your-package" to ${shown}.`,
616
+ ),
617
+ );
618
+ }
619
+ // A private package is never published, so it needs no version.
620
+ if (
621
+ pkg.private !== true &&
622
+ (typeof pkg.version !== 'string' || pkg.version === '')
623
+ ) {
624
+ issues.push(
625
+ listed(
626
+ 'invalid_package_json',
627
+ `${shown} has no "version", so npm cannot pack or publish the package. Fix: add "version": "0.1.0" to ${shown}.`,
628
+ ),
629
+ );
630
+ }
631
+ return issues;
632
+ }
633
+
634
+ /**
635
+ * Validate an INSTALLED integration package: the nearest `node_modules/<spec>`
636
+ * at or above `cwd`, resolved the way the project loads it.
431
637
  * @param {string} spec package name
432
638
  * @param {string} [cwd]
433
639
  * @returns {Promise<ValidateResult>}
434
640
  */
435
641
  export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
436
- // resolvePackageDir throws (path-safety guard) on a spec with path segments,
642
+ // The resolver throws (path-safety guard) on a spec with path segments,
437
643
  // `..`, or an absolute path. Every other malformed input to this command
438
644
  // degrades into a diagnostic — so catch it here and return an issue instead
439
645
  // of letting the throw escape to a raw stack (human) / generic ERR_UNKNOWN
440
646
  // (--json).
441
647
  let packageDir;
442
648
  try {
443
- packageDir = resolvePackageDir(spec, cwd);
649
+ packageDir = resolveInstalledIntegrationDir(spec, cwd);
444
650
  } catch (err) {
445
651
  return {
446
652
  found: true,
@@ -472,10 +678,29 @@ export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
472
678
  };
473
679
  }
474
680
 
475
- return validateAtPackageDir(packageDir, {
476
- name: pkg.name ?? spec,
477
- version: pkg.version,
478
- });
681
+ return validateAtPackageDir(
682
+ packageDir,
683
+ {name: pkg.name ?? spec, version: pkg.version},
684
+ {cwd},
685
+ );
686
+ }
687
+
688
+ /**
689
+ * The runner-command notes for a package's topics: each Astryx command a topic
690
+ * writes with a package runner, where the doc file is, and the bare command to
691
+ * write.
692
+ * @param {any} integration a loaded integration
693
+ * @returns {Promise<Array<{code: string, message: string}>>}
694
+ */
695
+ async function runnerCommandNotes(integration) {
696
+ const packageDir = integration.__packageDir;
697
+ return (await integrationRunnerCommands(integration)).map(each => ({
698
+ code: 'runner_command',
699
+ message:
700
+ typeof packageDir === 'string'
701
+ ? `${path.relative(packageDir, each.file).split(path.sep).join('/')}: ${each.message}`
702
+ : each.message,
703
+ }));
479
704
  }
480
705
 
481
706
  /**
@@ -504,7 +729,35 @@ export async function validateIntegration(pkg, options = {}) {
504
729
  const docTypes = integration
505
730
  ? await integrationDocTypes(integration, cwd)
506
731
  : undefined;
507
- const notes = result.found ? (result.notes ?? []) : [];
732
+ // The component names docs and blocks give: those that cannot be judged
733
+ // are listed in their reports, and those judged wrong are notes.
734
+ const names = integration
735
+ ? [
736
+ await componentDocNamesCheck(integration),
737
+ await blockComponentsCheck(integration),
738
+ ]
739
+ : undefined;
740
+ const docNames = names?.[0].report;
741
+ const blockComponents = names?.[1].report;
742
+ // Notes fail nothing: a malformed `cliCommand`, and the findings added
743
+ // after the last minor release, each with its fix in the message, which
744
+ // may not fail `--strict` until the next (architecture:cli-surface INV35):
745
+ // the layout findings and the component names judged wrong.
746
+ const notes = result.found
747
+ ? [
748
+ ...(result.notes ?? []),
749
+ ...(result.listed ?? []).map(issue => ({
750
+ code: issue.code,
751
+ message: issue.message,
752
+ })),
753
+ ...(names ?? []).flatMap(each => each.notes),
754
+ ]
755
+ : [];
756
+ // Each Astryx command a topic writes with a package runner, as a
757
+ // `runner_command` note with its fix, the same way.
758
+ if (integration?.docs) {
759
+ notes.push(...(await runnerCommandNotes(integration)));
760
+ }
508
761
  return {
509
762
  type: 'integration.validate',
510
763
  data: {
@@ -526,6 +779,12 @@ export async function validateIntegration(pkg, options = {}) {
526
779
  : result.issues,
527
780
  ...(notes.length > 0 ? {notes} : {}),
528
781
  ...(docTypes ? {docTypes} : {}),
782
+ ...(docNames ? {docNames} : {}),
783
+ ...(blockComponents ? {blockComponents} : {}),
784
+ // What the public-import check could not judge: listed, never failed on.
785
+ ...(result.found && result.publicImports
786
+ ? {publicImports: result.publicImports}
787
+ : {}),
529
788
  },
530
789
  };
531
790
  }
@@ -14,6 +14,7 @@ export type LoadedIntegration = {
14
14
  codemods?: string | undefined;
15
15
  docs?: string | undefined;
16
16
  issuesUrl?: string | undefined;
17
+ __declaredKeys?: string[] | undefined;
17
18
  __unknownKeys?: string[] | undefined;
18
19
  __spec: string;
19
20
  __packageDir: string;
@@ -36,7 +37,21 @@ export type ValidateIntegrationResponse = {
36
37
  type: "integration.validate";
37
38
  /**
38
39
  * `notes`: information beside the issues that fails nothing, such as
39
- * `invalid_cli_command`, a `cliCommand` that was ignored as malformed
40
+ * `invalid_cli_command`, a `cliCommand` that was ignored as malformed;
41
+ * `cli_peer_version`, the running CLI outside the package's
42
+ * `@astryxdesign/cli` peer range; and
43
+ * the package layout findings added after the last minor release, each with
44
+ * its fix in the message: two docs for one component
45
+ * (`duplicate_component_doc`), a root reached through a symlink
46
+ * (`symlinked_root`), a contribution file that cannot be read
47
+ * (`unreadable_file`), a package.json without `name` or `version`
48
+ * (`invalid_package_json`), no provider ID (`no_provider_id`), and a doc
49
+ * whose file name differs from its source only in letter case where the two
50
+ * still pair (`source_without_component_doc`); `doc_name_mismatch` and
51
+ * `unknown_block_component` (see `docNames` and `blockComponents`); and
52
+ * since 0.7.3 each public-import finding; they become warnings in the next
53
+ * minor release; and `runner_command`, an Astryx command a topic writes
54
+ * with a package runner
40
55
  */
41
56
  data: {
42
57
  validated: boolean;
@@ -48,6 +63,9 @@ export type ValidateIntegrationResponse = {
48
63
  message: string;
49
64
  }>;
50
65
  docTypes?: DocTypesReport;
66
+ docNames?: DocNamesReport;
67
+ blockComponents?: BlockComponentsReport;
68
+ publicImports?: PublicImportsReport;
51
69
  };
52
70
  };
53
71
  /**
@@ -57,3 +75,74 @@ export type ValidateIntegrationResponse = {
57
75
  export type DocTypesReport = import("../../foundation/discovery/doc-types.mjs").DocTypesReport & {
58
76
  fixtures?: number;
59
77
  };
78
+ /**
79
+ * Each component doc whose `name` differs from the name it is listed under,
80
+ * judged against its source. Present when the manifest loads. A name the
81
+ * module its printed import names provably does not export is a
82
+ * `doc_name_mismatch` note beside the issues, with its fix in the message
83
+ * (it becomes a warning in the next minor release), so `findings` is always
84
+ * empty; `unchecked` lists each doc whose source's
85
+ * exports could not all be read (a re-export from another package, `export
86
+ * =`, a destructured binding, a namespace): `file` (the doc, package-relative),
87
+ * `name` (what the doc says), and `reason`.
88
+ */
89
+ export type DocNamesReport = {
90
+ status: "checked";
91
+ findings: [];
92
+ unchecked: Array<{
93
+ file: string;
94
+ name: string;
95
+ reason: string;
96
+ }>;
97
+ };
98
+ /**
99
+ * Each component name a template gives in `exampleFor` or `componentsUsed`
100
+ * that could not be judged. Present when the manifest loads. A name neither
101
+ * the package nor Core has, and the template does not import, is an
102
+ * `unknown_block_component` note beside the issues, with its fix in the
103
+ * message (it becomes a warning in the next minor release), so `findings` is
104
+ * always empty;
105
+ * `unchecked` lists each name that cannot be judged: one the template may
106
+ * reach through anything other than named imports and re-exports from
107
+ * Core, React, StyleX, local helpers or the package's own entry (an import from another
108
+ * package, a default or namespace import, an alias of or member read off an imported
109
+ * binding, require(), a dynamic import(), a local module this check cannot
110
+ * read), or, without Core installed, any name Core would have to resolve: `file` (the template doc, package-relative),
111
+ * `name`, and `reason`.
112
+ */
113
+ export type BlockComponentsReport = {
114
+ status: "checked";
115
+ findings: [];
116
+ unchecked: Array<{
117
+ file: string;
118
+ name: string;
119
+ reason: string;
120
+ }>;
121
+ };
122
+ /**
123
+ * An import the public-import check could not judge.
124
+ */
125
+ export type PublicImportUnchecked = {
126
+ /**
127
+ * package-relative file that names it
128
+ */
129
+ file: string;
130
+ /**
131
+ * the import specifier
132
+ */
133
+ specifier: string;
134
+ /**
135
+ * why it was not checked
136
+ */
137
+ reason: string;
138
+ };
139
+ /**
140
+ * The public-import check's report on validate's result: `unchecked` lists
141
+ * what it could not judge, never counted or failed on. Its findings are
142
+ * notes on the result (`data.notes`), so `findings` stays empty.
143
+ */
144
+ export type PublicImportsReport = {
145
+ status: "checked";
146
+ findings: never[];
147
+ unchecked: PublicImportUnchecked[];
148
+ };