@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db52d98

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 (397) hide show
  1. package/README.md +38 -15
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/_adapter.d.mts +50 -0
  4. package/api/build/_adapter.mjs +60 -0
  5. package/api/build/build.doc.mjs +14 -7
  6. package/api/build/build.test.mjs +184 -6
  7. package/api/build/build.type.d.mts +57 -2
  8. package/api/build/build.type.mjs +30 -7
  9. package/api/build/help/help.d.mts +4 -0
  10. package/api/build/help/help.mjs +24 -11
  11. package/api/build/kit/kit.d.mts +4 -1
  12. package/api/build/kit/kit.mjs +165 -49
  13. package/api/build/kit/rank.d.mts +44 -0
  14. package/api/build/kit/rank.mjs +432 -0
  15. package/api/build/kit/rank.test.mjs +196 -0
  16. package/api/component/_adapter.d.mts +6 -12
  17. package/api/component/_adapter.mjs +20 -10
  18. package/api/component/component.doc.mjs +1 -0
  19. package/api/component/component.mjs +60 -12
  20. package/api/component/list/list.mjs +3 -2
  21. package/api/discover/discover.doc.mjs +1 -0
  22. package/api/docs/_adapter.d.mts +252 -34
  23. package/api/docs/_adapter.mjs +923 -132
  24. package/api/docs/detail/detail.mjs +11 -3
  25. package/api/docs/detail/section/section.mjs +24 -13
  26. package/api/docs/detail/section/section.test.mjs +15 -6
  27. package/api/docs/docs.d.mts +5 -3
  28. package/api/docs/docs.doc.mjs +39 -17
  29. package/api/docs/docs.mjs +44 -8
  30. package/api/docs/docs.test.mjs +158 -4
  31. package/api/docs/docs.type.d.mts +181 -2
  32. package/api/docs/docs.type.mjs +117 -3
  33. package/api/docs/index/index.mjs +11 -3
  34. package/api/docs/index/index.test.mjs +1 -1
  35. package/api/docs/integration-tree.test.mjs +555 -0
  36. package/api/docs/integrationDocs.test.mjs +14 -14
  37. package/api/docs/list/list.mjs +28 -12
  38. package/api/docs/node/node.d.mts +43 -0
  39. package/api/docs/node/node.mjs +192 -0
  40. package/api/docs/reference-blocks.test.mjs +406 -0
  41. package/api/doctor/doctor.d.mts +54 -4
  42. package/api/doctor/doctor.doc.mjs +1 -0
  43. package/api/doctor/doctor.mjs +331 -16
  44. package/api/doctor/doctor.test.mjs +420 -7
  45. package/api/gap-report/gap-report.doc.mjs +1 -0
  46. package/api/hook/_adapter.mjs +19 -5
  47. package/api/hook/hook.doc.mjs +1 -0
  48. package/api/hook/list/list.d.mts +1 -1
  49. package/api/hook/list/list.mjs +69 -17
  50. package/api/index.d.mts +1 -1
  51. package/api/index.mjs +1 -0
  52. package/api/init/init.doc.mjs +2 -1
  53. package/api/integration/add-contribution.d.mts +2 -1
  54. package/api/integration/add-contribution.mjs +114 -12
  55. package/api/integration/add-contribution.test.mjs +174 -3
  56. package/api/integration/add-theme.mjs +34 -64
  57. package/api/integration/add-theme.test.mjs +105 -21
  58. package/api/integration/authoring-checks.mjs +138 -28
  59. package/api/integration/authoring-checks.test.mjs +179 -7
  60. package/api/integration/authoring-checks.type.mjs +6 -1
  61. package/api/integration/integration-authoring.type.d.mts +2 -0
  62. package/api/integration/integration-authoring.type.mjs +2 -0
  63. package/api/integration/integration-block-exports.test.mjs +10 -6
  64. package/api/integration/integrationAdd.doc.mjs +7 -0
  65. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  66. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  67. package/api/integration/integrationAddComponent.doc.mjs +1 -0
  68. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  69. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  70. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  71. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  72. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  73. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  74. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  75. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  76. package/api/integration/pack-check.mjs +34 -0
  77. package/api/integration/pack-check.test.mjs +138 -47
  78. package/api/integration/pack-check.type.d.mts +26 -2
  79. package/api/integration/pack-check.type.mjs +14 -1
  80. package/api/integration/summarizeIssues.doc.mjs +1 -0
  81. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  82. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  83. package/api/integration/validate-integration.mjs +50 -102
  84. package/api/integration/validate-integration.test.mjs +88 -26
  85. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  86. package/api/integration/validateIntegration.doc.mjs +2 -1
  87. package/api/json/assertResponse.doc.mjs +1 -0
  88. package/api/json/index.ts +2 -0
  89. package/api/json/isError.doc.mjs +1 -0
  90. package/api/json/parseResponse.doc.mjs +1 -0
  91. package/api/layout/_adapter.mjs +20 -5
  92. package/api/layout/layoutCheck.doc.mjs +1 -0
  93. package/api/layout/layoutExpand.doc.mjs +1 -0
  94. package/api/layout/layoutGrammar.doc.mjs +1 -0
  95. package/api/search/search.d.mts +59 -1
  96. package/api/search/search.doc.mjs +5 -3
  97. package/api/search/search.mjs +458 -77
  98. package/api/search/search.test.mjs +91 -2
  99. package/api/search/search.type.d.mts +13 -1
  100. package/api/search/search.type.mjs +4 -1
  101. package/api/swizzle/swizzle.doc.mjs +1 -0
  102. package/api/template/list/list.mjs +1 -0
  103. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  104. package/api/template/template-integration.test.mjs +1072 -3
  105. package/api/template/template-suffix.test.mjs +41 -21
  106. package/api/template/template.doc.mjs +28 -7
  107. package/api/template/template.mjs +45 -8
  108. package/api/template/template.type.d.mts +6 -8
  109. package/api/template/template.type.mjs +3 -2
  110. package/api/theme/_adapter.d.mts +2 -3
  111. package/api/theme/_adapter.mjs +4 -5
  112. package/api/theme/add/add.binary.test.mjs +10 -17
  113. package/api/theme/add/add.test.mjs +14 -1
  114. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  115. package/api/theme/integration-themes.test.mjs +39 -28
  116. package/api/theme/list/list.test.mjs +19 -20
  117. package/api/theme/listThemes.doc.mjs +6 -5
  118. package/api/theme/template/template.test.mjs +5 -0
  119. package/api/theme/themeAdd.doc.mjs +4 -3
  120. package/api/theme/themeBuild.doc.mjs +1 -0
  121. package/api/theme/themeList.doc.mjs +6 -3
  122. package/api/theme/themeListAvailable.doc.mjs +5 -3
  123. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  124. package/api/theme/themeTargets.doc.mjs +1 -0
  125. package/api/theme/themeTemplate.doc.mjs +2 -1
  126. package/api/upgrade/_adapter.d.mts +32 -5
  127. package/api/upgrade/_adapter.mjs +97 -69
  128. package/api/upgrade/provider-agreement.test.mjs +152 -0
  129. package/api/upgrade/run/run.mjs +356 -59
  130. package/api/upgrade/upgrade.doc.mjs +6 -1
  131. package/api/upgrade/upgrade.type.d.mts +34 -0
  132. package/api/upgrade/upgrade.type.mjs +15 -0
  133. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  134. package/assets/codemods/integration-discovery.mjs +8 -2
  135. package/assets/codemods/integration-discovery.test.mjs +15 -0
  136. package/assets/codemods/integration-runner.mjs +56 -4
  137. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  138. package/assets/codemods/run-codemod.mjs +177 -34
  139. package/assets/codemods/runner.mjs +350 -102
  140. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  141. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  142. package/assets/codemods/transforms/next/index.mjs +19 -1
  143. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  144. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  145. package/assets/docs/getting-started.doc.mjs +2 -2
  146. package/assets/docs/layout.doc.dense.mjs +2 -2
  147. package/assets/docs/layout.doc.mjs +1 -1
  148. package/assets/docs/principles.doc.mjs +6 -6
  149. package/assets/docs/styling-libraries.doc.mjs +3 -3
  150. package/assets/docs/styling.doc.mjs +4 -4
  151. package/assets/docs/theme.doc.mjs +5 -5
  152. package/assets/docs/tokens.doc.mjs +1 -1
  153. package/assets/docs/tree/api.doc.mjs +30 -0
  154. package/assets/docs/tree/cli.doc.mjs +23 -0
  155. package/assets/docs/tree/commands.doc.mjs +25 -0
  156. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +66 -38
  157. package/assets/docs/tree/integrations.test.mjs +62 -0
  158. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  159. package/assets/docs/working-with-ai.doc.mjs +3 -3
  160. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  161. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  162. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  163. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  164. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  165. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  166. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  167. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  168. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  169. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  170. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  171. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  172. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  173. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  174. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  175. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  176. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  177. package/authoring/codemod/codemod.doc.mjs +1 -1
  178. package/authoring/codemod/type.ts +12 -0
  179. package/authoring/config/config.doc.mjs +1 -1
  180. package/authoring/debug/debug.doc.d.mts +11 -0
  181. package/authoring/debug/debug.doc.mjs +182 -0
  182. package/authoring/debug/parse.d.mts +3 -3
  183. package/authoring/doctypes/_schema.d.mts +119 -117
  184. package/authoring/doctypes/_schema.mjs +54 -3
  185. package/authoring/doctypes/base/graph-fields.doc.mjs +8 -6
  186. package/authoring/doctypes/base/type.ts +6 -5
  187. package/authoring/doctypes/command/command.doc.mjs +1 -1
  188. package/authoring/doctypes/command/type.ts +2 -2
  189. package/authoring/doctypes/component/type.ts +2 -2
  190. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  191. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  192. package/authoring/doctypes/enum/type.ts +1 -1
  193. package/authoring/doctypes/function/function.doc.mjs +3 -2
  194. package/authoring/doctypes/function/type.ts +3 -2
  195. package/authoring/doctypes/hook/type.ts +2 -2
  196. package/authoring/doctypes/load-contract.test.mjs +28 -2
  197. package/authoring/doctypes/namespace/namespace.doc.mjs +6 -10
  198. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  199. package/authoring/doctypes/namespace/type.ts +5 -2
  200. package/authoring/doctypes/parse.d.mts +4 -2
  201. package/authoring/doctypes/parse.mjs +10 -5
  202. package/authoring/doctypes/reference/reference.doc.mjs +35 -6
  203. package/authoring/doctypes/reference/type.ts +30 -13
  204. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  205. package/authoring/doctypes/schema/type.ts +1 -2
  206. package/authoring/doctypes/template/parse.d.mts +2 -0
  207. package/authoring/doctypes/template/parse.mjs +4 -0
  208. package/authoring/doctypes/template/parse.test.mjs +18 -0
  209. package/authoring/doctypes/template/template.doc.mjs +9 -3
  210. package/authoring/doctypes/template/type.ts +8 -0
  211. package/authoring/doctypes/theme/parse.d.mts +35 -0
  212. package/authoring/doctypes/theme/parse.mjs +76 -0
  213. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  214. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  215. package/authoring/doctypes/theme/type.ts +42 -0
  216. package/authoring/doctypes/types.ts +2 -1
  217. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  218. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  219. package/authoring/identity/identity.doc.mjs +2 -2
  220. package/authoring/index.d.mts +1 -0
  221. package/authoring/index.d.ts +7 -4
  222. package/authoring/index.mjs +2 -1
  223. package/authoring/integration/integration.doc.mjs +2 -2
  224. package/authoring/integration/type.ts +4 -10
  225. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  226. package/clients/cli/commands/blog.doc.mjs +1 -1
  227. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  228. package/clients/cli/commands/build-theme.mjs +11 -45
  229. package/clients/cli/commands/build.doc.mjs +12 -7
  230. package/clients/cli/commands/build.mjs +105 -67
  231. package/clients/cli/commands/build.text-fields.test.mjs +41 -0
  232. package/clients/cli/commands/component/index.mjs +1 -1
  233. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  234. package/clients/cli/commands/component.doc.mjs +1 -1
  235. package/clients/cli/commands/discover.broken-integration.test.mjs +7 -8
  236. package/clients/cli/commands/discover.doc.mjs +1 -1
  237. package/clients/cli/commands/discover.mjs +1 -1
  238. package/clients/cli/commands/docs.doc.mjs +21 -9
  239. package/clients/cli/commands/docs.mjs +184 -70
  240. package/clients/cli/commands/docs.test.mjs +120 -16
  241. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  242. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  243. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  244. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  245. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  246. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  247. package/clients/cli/commands/doctor.doc.mjs +1 -1
  248. package/clients/cli/commands/doctor.mjs +53 -16
  249. package/clients/cli/commands/gap-report.doc.mjs +1 -1
  250. package/clients/cli/commands/hook.doc.mjs +1 -1
  251. package/clients/cli/commands/init.doc.mjs +1 -1
  252. package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
  253. package/clients/cli/commands/integration-add.doc.mjs +11 -1
  254. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  255. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  256. package/clients/cli/commands/integration.doc.mjs +1 -1
  257. package/clients/cli/commands/integration.mjs +1 -0
  258. package/clients/cli/commands/layout-check.doc.mjs +1 -1
  259. package/clients/cli/commands/layout-expand.doc.mjs +1 -1
  260. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  261. package/clients/cli/commands/layout.doc.mjs +1 -1
  262. package/clients/cli/commands/manifest.doc.mjs +1 -1
  263. package/clients/cli/commands/search.doc.mjs +1 -1
  264. package/clients/cli/commands/search.mjs +11 -2
  265. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  266. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  267. package/clients/cli/commands/template.doc.mjs +24 -7
  268. package/clients/cli/commands/template.mjs +4 -91
  269. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  270. package/clients/cli/commands/theme-add.doc.mjs +2 -2
  271. package/clients/cli/commands/theme-build.doc.mjs +1 -1
  272. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  273. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  274. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  275. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  276. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  277. package/clients/cli/commands/theme-template.doc.mjs +1 -1
  278. package/clients/cli/commands/theme.doc.mjs +1 -1
  279. package/clients/cli/commands/upgrade.doc.mjs +3 -2
  280. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  281. package/clients/cli/commands/upgrade.mjs +29 -7
  282. package/clients/cli/formatters/index.mjs +2 -0
  283. package/clients/cli/formatters/index.test.mjs +6 -0
  284. package/clients/cli/index.mjs +8 -0
  285. package/clients/cli/lib/hook-format.mjs +14 -5
  286. package/clients/cli/lib/manifest.mjs +9 -2
  287. package/foundation/agent-docs/agent-docs.d.mts +3 -2
  288. package/foundation/agent-docs/agent-docs.mjs +13 -9
  289. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  290. package/foundation/config/project-themes.test.mjs +11 -19
  291. package/foundation/config/project.d.mts +20 -11
  292. package/foundation/config/project.mjs +123 -80
  293. package/foundation/config/project.test.mjs +144 -21
  294. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  295. package/foundation/discovery/authoring-self-docs.mjs +37 -15
  296. package/foundation/discovery/authoring-self-docs.test.mjs +25 -9
  297. package/foundation/discovery/authoring-surface.d.mts +74 -0
  298. package/foundation/discovery/authoring-surface.mjs +525 -0
  299. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  300. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  301. package/foundation/discovery/cli-self-docs.mjs +490 -0
  302. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  303. package/foundation/discovery/component-discovery.d.mts +38 -0
  304. package/foundation/discovery/component-discovery.mjs +48 -0
  305. package/foundation/discovery/component-loader.d.mts +35 -38
  306. package/foundation/discovery/component-loader.mjs +53 -222
  307. package/foundation/discovery/docs-discovery.d.mts +112 -11
  308. package/foundation/discovery/docs-discovery.mjs +231 -36
  309. package/foundation/discovery/docs-discovery.test.mjs +111 -32
  310. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  311. package/foundation/discovery/docs-output-budget.mjs +1 -1
  312. package/foundation/discovery/docs-section-key.d.mts +28 -10
  313. package/foundation/discovery/docs-section-key.mjs +134 -33
  314. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  315. package/foundation/discovery/template-adapter.d.mts +99 -6
  316. package/foundation/discovery/template-adapter.mjs +480 -57
  317. package/foundation/discovery/template-adapter.test.mjs +57 -0
  318. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  319. package/foundation/discovery/template-conflict-release.mjs +40 -0
  320. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  321. package/foundation/discovery/theme-discovery.d.mts +67 -7
  322. package/foundation/discovery/theme-discovery.mjs +916 -186
  323. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  324. package/foundation/doc-compiler/bundle.d.mts +47 -0
  325. package/foundation/doc-compiler/bundle.mjs +278 -0
  326. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  327. package/foundation/doc-compiler/compile.d.mts +220 -39
  328. package/foundation/doc-compiler/compile.mjs +311 -15
  329. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  330. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  331. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  332. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  333. package/foundation/doc-compiler/import.d.mts +24 -0
  334. package/foundation/doc-compiler/import.mjs +59 -0
  335. package/foundation/doc-compiler/inputs.d.mts +102 -0
  336. package/foundation/doc-compiler/inputs.mjs +291 -0
  337. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  338. package/foundation/doc-compiler/ir.d.mts +13 -0
  339. package/foundation/doc-compiler/ir.mjs +196 -12
  340. package/foundation/doc-compiler/lenses.d.mts +8 -5
  341. package/foundation/doc-compiler/lenses.mjs +50 -4
  342. package/foundation/doc-compiler/links.d.mts +162 -0
  343. package/foundation/doc-compiler/links.mjs +294 -0
  344. package/foundation/doc-compiler/links.test.mjs +192 -0
  345. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  346. package/foundation/doc-compiler/overlays.d.mts +37 -0
  347. package/foundation/doc-compiler/overlays.mjs +206 -0
  348. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  349. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  350. package/foundation/doc-compiler/read.d.mts +127 -0
  351. package/foundation/doc-compiler/read.mjs +325 -0
  352. package/foundation/doc-compiler/read.test.mjs +313 -0
  353. package/foundation/doc-compiler/source.d.mts +33 -0
  354. package/foundation/doc-compiler/source.mjs +128 -0
  355. package/foundation/doc-compiler/tree.d.mts +288 -0
  356. package/foundation/doc-compiler/tree.mjs +876 -0
  357. package/foundation/doc-compiler/tree.test.mjs +598 -0
  358. package/foundation/fs/file-protection.d.mts +33 -0
  359. package/foundation/fs/file-protection.mjs +825 -0
  360. package/foundation/fs/file-protection.test.mjs +250 -0
  361. package/foundation/integrations/autolink.d.mts +58 -1
  362. package/foundation/integrations/autolink.mjs +143 -57
  363. package/foundation/integrations/autolink.test.mjs +1 -1
  364. package/foundation/integrations/cli-requirement.d.mts +45 -0
  365. package/foundation/integrations/cli-requirement.mjs +154 -0
  366. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  367. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  368. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  369. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  370. package/foundation/integrations/contribution-inventory.mjs +27 -24
  371. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  372. package/foundation/integrations/integration-warnings.d.mts +9 -2
  373. package/foundation/integrations/integration-warnings.mjs +51 -26
  374. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  375. package/foundation/integrations/integrations.d.mts +3 -0
  376. package/foundation/integrations/integrations.mjs +11 -97
  377. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  378. package/foundation/integrations/provider-resolution.d.mts +152 -0
  379. package/foundation/integrations/provider-resolution.mjs +576 -0
  380. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  381. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  382. package/foundation/integrations/theme-descriptor.mjs +44 -0
  383. package/foundation/integrations/validate-contributions.mjs +121 -29
  384. package/foundation/response/error-codes.d.mts +3 -1
  385. package/foundation/response/error-codes.d.ts +2 -0
  386. package/foundation/response/error-codes.doc.mjs +12 -2
  387. package/foundation/response/error-codes.mjs +7 -1
  388. package/foundation/response/error-codes.test.mjs +55 -11
  389. package/foundation/response/response-types.doc.d.mts +5 -1
  390. package/foundation/response/response-types.doc.mjs +20 -11
  391. package/foundation/response/response.doc.mjs +1 -1
  392. package/foundation/text/string-utils.d.mts +8 -0
  393. package/foundation/text/string-utils.mjs +40 -10
  394. package/foundation/xle/expand.mjs +1 -1
  395. package/foundation/xle/xle.test.mjs +13 -0
  396. package/package.json +10 -9
  397. package/assets/templates/themes/manifest.json +0 -95
@@ -55,6 +55,15 @@ describe('generateCompressedIndex', () => {
55
55
  expect(frameRule).not.toMatch(/https?:/);
56
56
  });
57
57
 
58
+ it('starts every page from a template before any component', () => {
59
+ const lines = generateCompressedIndex('1.0.0').split('\n');
60
+ const workflow = lines.findIndex(l => l.startsWith('WORKFLOW'));
61
+ expect(lines[workflow]).toMatch(/start every page from a template/);
62
+ expect(lines[workflow + 1]).toMatch(/^1\. `astryx build /);
63
+ expect(lines[workflow + 2]).toMatch(/^2\. `astryx template <name> <path>`/);
64
+ expect(lines.join('\n')).not.toMatch(/reference code/);
65
+ });
66
+
58
67
  it('includes the post-generation self-check rule', () => {
59
68
  const result = generateCompressedIndex('1.0.0');
60
69
  expect(result).toContain('SELF-CHECK before you finish');
@@ -134,7 +143,6 @@ describe('generateCompressedIndex', () => {
134
143
  const line = topicLine(generateCompressedIndex('1.0.0'));
135
144
  for (const topic of [
136
145
  'getting-started',
137
- 'cli-integrations',
138
146
  'browser-support',
139
147
  'styling-libraries',
140
148
  'working-with-ai',
@@ -143,6 +151,16 @@ describe('generateCompressedIndex', () => {
143
151
  }
144
152
  });
145
153
 
154
+ it('points to the CLI docs tree on a line of its own', () => {
155
+ // The integration guide lives in the docs tree now (cli/integrations), so
156
+ // the topic line no longer names it; the tree's entry point does.
157
+ const block = generateCompressedIndex('1.0.0');
158
+ expect(block).toContain(
159
+ ' docs cli commands, API reference, integration authoring (one level at a time)',
160
+ );
161
+ expect(topicLine(block)).not.toContain('cli-integrations');
162
+ });
163
+
146
164
  it('lists the topics it is given, so an integration’s reach the agent', () => {
147
165
  const line = topicLine(
148
166
  generateCompressedIndex('1.0.0', {topics: ['tokens', 'deploying']}),
@@ -15,6 +15,7 @@ function installThemeIntegration(packageName, slug) {
15
15
  ...packageName.split('/'),
16
16
  );
17
17
  const themeDir = path.join(packageDir, 'themes', slug);
18
+ const stem = `${slug.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
18
19
  fs.mkdirSync(themeDir, {recursive: true});
19
20
  fs.writeFileSync(
20
21
  path.join(packageDir, 'package.json'),
@@ -22,28 +23,19 @@ function installThemeIntegration(packageName, slug) {
22
23
  );
23
24
  fs.writeFileSync(
24
25
  path.join(packageDir, 'astryx.integration.mjs'),
25
- `export default {themes: './themes'};\n`,
26
+ `export default {themes: './themes'};
27
+ `,
26
28
  );
27
29
  fs.writeFileSync(
28
- path.join(packageDir, 'themes', 'manifest.json'),
29
- JSON.stringify({
30
- version: 1,
31
- themes: [
32
- {
33
- slug,
34
- displayName: 'Ocean',
35
- description: 'Blue and calm.',
36
- maintained: true,
37
- entry: 'oceanTheme.ts',
38
- exportName: 'oceanTheme',
39
- files: ['oceanTheme.ts'],
40
- },
41
- ],
42
- }),
30
+ path.join(themeDir, `${stem}.doc.mjs`),
31
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
32
+ export default {type: 'theme', name: '${slug}', displayName: 'Ocean', description: 'Blue and calm.', maintained: true};
33
+ `,
43
34
  );
44
35
  fs.writeFileSync(
45
- path.join(themeDir, 'oceanTheme.ts'),
46
- `export const oceanTheme = {};\n`,
36
+ path.join(themeDir, `${stem}.ts`),
37
+ `export const ${stem} = {};
38
+ `,
47
39
  );
48
40
  }
49
41
 
@@ -99,7 +91,7 @@ describe('Project themes', () => {
99
91
  ]);
100
92
  });
101
93
 
102
- it('records an invalid integration theme catalog as an issue', async () => {
94
+ it('records an invalid integration theme descriptor as an issue', async () => {
103
95
  installThemeIntegration('@acme/themes', 'ocean');
104
96
  fs.rmSync(
105
97
  path.join(
@@ -9,6 +9,14 @@
9
9
  * @returns {string|null}
10
10
  */
11
11
  export function findConfigPath(startDir?: string): string | null;
12
+ /**
13
+ * The provider ledger a Project resolved at load: one outcome for every
14
+ * package directory configured, autolinked, or authored. Internal: upgrade
15
+ * resolves on top of it, and tests account for every candidate with it.
16
+ * @param {Project} project
17
+ * @returns {import('../integrations/provider-resolution.mjs').ProviderLedger}
18
+ */
19
+ export function providerLedgerOf(project: Project): import("../integrations/provider-resolution.mjs").ProviderLedger;
12
20
  /**
13
21
  * An integration issue tagged with the owner package. The base
14
22
  * {@link import('../integrations/issue').AstryxIntegrationIssue} fields plus the
@@ -87,9 +95,9 @@ export class Project {
87
95
  /**
88
96
  * Core + integration component ownership records. Wraps
89
97
  * discoverOwnedComponents for core and discoverIntegrationComponents (via
90
- * discoverOwnedComponents) for integrations, but applies the skip+warn
91
- * policy per integration: a broken integration's components are skipped and
92
- * its issues collected, never thrown. Memoized per instance.
98
+ * discoverOwnedComponents) for integrations. Invalid component records are
99
+ * omitted and reported; valid component siblings and other contribution kinds
100
+ * remain available. Memoized per instance.
93
101
  *
94
102
  * @returns {Promise<Array<{name: string, package: string, group: string|null, docPath: string|null, sourcePath: string|null, issuesUrl: string|undefined}>>}
95
103
  */
@@ -102,10 +110,11 @@ export class Project {
102
110
  issuesUrl: string | undefined;
103
111
  }>>;
104
112
  /**
105
- * Core + integration templates, type-tagged. Wraps discoverTemplates (core +
106
- * external blocks) and discoverIntegrationTemplatesForOne per integration so
107
- * a broken integration's templates are skipped and its issues collected.
108
- * Memoized per instance.
113
+ * Core + integration templates, type-tagged, with valid integration
114
+ * replacements projected over their Core targets. Wraps raw template discovery
115
+ * (Core + external blocks) and discoverIntegrationTemplatesForOne per integration
116
+ * so unusable template files are reported and omitted while valid siblings
117
+ * remain available. Memoized per instance.
109
118
  *
110
119
  * @returns {Promise<Array<object>>}
111
120
  */
@@ -113,8 +122,8 @@ export class Project {
113
122
  /**
114
123
  * Bundled source themes plus themes contributed by installed integrations.
115
124
  * Each record keeps its package owner and source directory so callers can
116
- * both list and copy it without reconstructing paths. A broken integration's
117
- * themes are skipped under the same issue policy as every other kind.
125
+ * both list and copy it without reconstructing paths. A broken theme
126
+ * contribution is reported without hiding the package's other valid kinds.
118
127
  *
119
128
  * @returns {Promise<import('../discovery/theme-discovery.mjs').DiscoveredTheme[]>}
120
129
  */
@@ -137,8 +146,8 @@ export class Project {
137
146
  /**
138
147
  * Core registry transforms + integration codemods for an upgrade range.
139
148
  * Wraps getTransformsBetween (core) and discoverIntegrationCodemods /
140
- * selectIntegrationCodemods (integrations). A broken integration's codemods
141
- * are skipped (issue collected) rather than failing the whole resolution.
149
+ * selectIntegrationCodemods (integrations). An invalid codemod contribution
150
+ * is reported and omitted without hiding other valid contribution kinds.
142
151
  * Memoized per (from, to) key.
143
152
  *
144
153
  * @param {string} fromVersion exclusive lower bound
@@ -15,14 +15,16 @@
15
15
  * async). It does what loadConfig did — find the config sibling-of
16
16
  * package.json, import + validate it, load the configured integrations —
17
17
  * plus autolink the installed ones no config names, and self-resolve the
18
- * package being authored when it carries a manifest. Discovery is LAZY.
18
+ * package being authored when it carries a manifest. Provider identity is
19
+ * resolved once over all three (see integrations/provider-resolution), and
20
+ * the ledger is kept for {@link providerLedgerOf}. Discovery is LAZY.
19
21
  * - Discovery methods (components/templates/codemods/docs/themes) are MEMOIZED per
20
22
  * instance (via the pluggable cache) and orchestrate the EXISTING discovery
21
23
  * functions — Project never reimplements discovery.
22
- * - SKIP + WARN policy: as a discovery method runs, per-integration work is
23
- * guarded so one broken integration never throws out of discovery. Any
24
- * AstryxIntegrationIssue encountered is collected into a private set and
25
- * that integration's contributions are skipped.
24
+ * - SKIP + WARN policy: discovery records each integration issue. Other valid
25
+ * contribution kinds remain available; invalid template and component files
26
+ * do not hide valid siblings. A manifest load failure still withdraws the
27
+ * package because its roots cannot be trusted.
26
28
  * - `issues()` returns the deduped accumulated set, and (when called
27
29
  * directly) fills in validation for any configured integration not yet
28
30
  * visited by a discovery call, so it is always complete on demand.
@@ -38,10 +40,10 @@ import {parseConfig} from '../../authoring/config/parse.mjs';
38
40
  import {
39
41
  loadIntegrations,
40
42
  loadLocalIntegration,
41
- markProviderConflicts,
42
43
  resolvePackageDir,
43
44
  } from '../integrations/integrations.mjs';
44
- import {autolinkIntegrations} from '../integrations/autolink.mjs';
45
+ import {loadAutolinkCandidates} from '../integrations/autolink.mjs';
46
+ import {resolveProviders} from '../integrations/provider-resolution.mjs';
45
47
  import {
46
48
  setProject as setDebugProject,
47
49
  setEventHandler as setDebugEventHandler,
@@ -50,11 +52,13 @@ import {
50
52
  import {
51
53
  CORE_PACKAGE,
52
54
  discoverOwnedComponents,
53
- discoverIntegrationComponents,
55
+ discoverValidIntegrationComponents,
54
56
  } from '../discovery/component-discovery.mjs';
55
57
  import {findCoreDir} from '../fs/paths.mjs';
56
58
  import {
57
- discoverAll as discoverTemplates,
59
+ applyTemplateReplacements,
60
+ effectiveTemplateDiscovery,
61
+ discoverAllUnresolved as discoverTemplates,
58
62
  discoverIntegrationTemplatesForOne,
59
63
  } from '../discovery/template-adapter.mjs';
60
64
  import {
@@ -70,10 +74,7 @@ import {
70
74
  discoverIntegrationCodemods,
71
75
  selectIntegrationCodemods,
72
76
  } from '../../assets/codemods/integration-discovery.mjs';
73
- import {
74
- INVALID_AGENT_DOCS,
75
- validateLoadedIntegration,
76
- } from '../integrations/validate-contributions.mjs';
77
+ import {validateLoadedIntegration} from '../integrations/validate-contributions.mjs';
77
78
  import {
78
79
  InMemoryConfigCache,
79
80
  cacheKey,
@@ -297,6 +298,24 @@ export function findConfigPath(startDir = process.cwd()) {
297
298
  return present.length === 1 ? present[0] : null;
298
299
  }
299
300
 
301
+ /**
302
+ * The provider ledger each loaded Project resolved, kept off the class so it
303
+ * is not part of the Project API.
304
+ * @type {WeakMap<Project, import('../integrations/provider-resolution.mjs').ProviderLedger>}
305
+ */
306
+ const PROVIDER_LEDGERS = new WeakMap();
307
+
308
+ /**
309
+ * The provider ledger a Project resolved at load: one outcome for every
310
+ * package directory configured, autolinked, or authored. Internal: upgrade
311
+ * resolves on top of it, and tests account for every candidate with it.
312
+ * @param {Project} project
313
+ * @returns {import('../integrations/provider-resolution.mjs').ProviderLedger}
314
+ */
315
+ export function providerLedgerOf(project) {
316
+ return PROVIDER_LEDGERS.get(project) ?? new Map();
317
+ }
318
+
300
319
  /**
301
320
  * The single API for reading resolved project configuration. Construct via the
302
321
  * async {@link Project.load} factory.
@@ -326,6 +345,8 @@ export class Project {
326
345
  * @type {Set<object>}
327
346
  */
328
347
  #visitedIssues = new Set();
348
+ /** @type {Promise<Array<object>> | null} */
349
+ #templatesPromise = null;
329
350
 
330
351
  /**
331
352
  * @param {object} init
@@ -402,17 +423,14 @@ export class Project {
402
423
  // This runs whether or not a config exists, because the projects it reaches
403
424
  // are overwhelmingly the ones with no astryx.config at all: a scaffold adds
404
425
  // the dependency and writes no config, and the integration then contributes
405
- // nothing for want of a line nobody knew to write. Appended AFTER the
426
+ // nothing for want of a line nobody knew to write. Resolved AFTER the
406
427
  // configured ones so an explicit entry keeps its position and its
407
428
  // precedence in every discovery order.
408
- loadedIntegrations = [
409
- ...loadedIntegrations,
410
- ...(await autolinkIntegrations({
411
- projectDir,
412
- loaded: loadedIntegrations,
413
- fresh,
414
- })),
415
- ];
429
+ const autolinked = await loadAutolinkCandidates({
430
+ projectDir,
431
+ loaded: loadedIntegrations,
432
+ fresh,
433
+ });
416
434
 
417
435
  // The package being authored is the one package that cannot install itself.
418
436
  // When it carries a manifest, resolve its working bytes directly so every
@@ -420,17 +438,27 @@ export class Project {
420
438
  // replaces the same installed package in place, preserving configured
421
439
  // precedence while making the source being edited authoritative.
422
440
  const localIntegration = await loadLocalIntegrationSafely(projectDir, fresh);
423
- if (localIntegration) {
424
- const existing = loadedIntegrations.findIndex(
425
- integration => integration.name === localIntegration.name,
426
- );
427
- if (existing === -1) loadedIntegrations.push(localIntegration);
428
- else loadedIntegrations[existing] = localIntegration;
429
- }
430
441
 
431
442
  // Autolinked and local packages can claim a provider ID that a configured
432
443
  // package already holds, so identity is resolved once over the final set.
433
- loadedIntegrations = markProviderConflicts(loadedIntegrations);
444
+ const resolution = resolveProviders([
445
+ ...loadedIntegrations.map(integration => ({
446
+ source: /** @type {const} */ ('configured'),
447
+ integration,
448
+ spec: integration.__spec,
449
+ })),
450
+ ...autolinked,
451
+ ...(localIntegration
452
+ ? [
453
+ {
454
+ source: /** @type {const} */ ('local'),
455
+ integration: localIntegration,
456
+ spec: localIntegration.__spec,
457
+ },
458
+ ]
459
+ : []),
460
+ ]);
461
+ loadedIntegrations = resolution.integrations;
434
462
 
435
463
  // The debug recorder resolves its settings synchronously, long before any
436
464
  // command gets here, so this is where a project's `debug` block gets a
@@ -461,7 +489,7 @@ export class Project {
461
489
  // Never let recording break config loading.
462
490
  }
463
491
 
464
- return new Project({
492
+ const project = new Project({
465
493
  cwd,
466
494
  configPath,
467
495
  config,
@@ -470,6 +498,8 @@ export class Project {
470
498
  cache: resolvedCache,
471
499
  hash,
472
500
  });
501
+ PROVIDER_LEDGERS.set(project, resolution.ledger);
502
+ return project;
473
503
  }
474
504
 
475
505
  /**
@@ -568,22 +598,6 @@ export class Project {
568
598
  return integration?.name ?? integration?.__spec ?? '(integration)';
569
599
  }
570
600
 
571
- /**
572
- * Whether this package has an error that invalidates its regular manifest
573
- * contributions. Invalid `agentDocs` blocks agent-doc writes only; it must not
574
- * withdraw components, templates, docs, or codemods.
575
- * @param {string} pkg
576
- * @returns {boolean}
577
- */
578
- #hasBlockingContributionIssue(pkg) {
579
- return this.#issues.some(
580
- issue =>
581
- issue.package === pkg &&
582
- issue.severity === 'error' &&
583
- issue.code !== INVALID_AGENT_DOCS,
584
- );
585
- }
586
-
587
601
  /**
588
602
  * Validate one loaded integration and collect any issues. Marks the
589
603
  * integration visited so issues() won't redo the work. Best-effort: a
@@ -620,9 +634,9 @@ export class Project {
620
634
  /**
621
635
  * Core + integration component ownership records. Wraps
622
636
  * discoverOwnedComponents for core and discoverIntegrationComponents (via
623
- * discoverOwnedComponents) for integrations, but applies the skip+warn
624
- * policy per integration: a broken integration's components are skipped and
625
- * its issues collected, never thrown. Memoized per instance.
637
+ * discoverOwnedComponents) for integrations. Invalid component records are
638
+ * omitted and reported; valid component siblings and other contribution kinds
639
+ * remain available. Memoized per instance.
626
640
  *
627
641
  * @returns {Promise<Array<{name: string, package: string, group: string|null, docPath: string|null, sourcePath: string|null, issuesUrl: string|undefined}>>}
628
642
  */
@@ -642,18 +656,17 @@ export class Project {
642
656
  }
643
657
  }
644
658
 
645
- // Each integration in isolation so one broken integration is skipped.
659
+ // Each integration is discovered independently. Invalid records are
660
+ // omitted below without hiding valid siblings or other contribution kinds.
646
661
  for (const integration of this.#loadedIntegrations) {
647
662
  await this.#collectIssues(integration);
648
663
  const pkg = this.#pkgLabel(integration);
649
- if (this.#hasBlockingContributionIssue(pkg)) continue;
650
664
  try {
651
- // discoverOwnedComponents owns the core+integration record shape;
652
- // here we add only this integration's records (core is handled
653
- // above) so a single broken integration can be skipped in isolation.
654
- for (const rec of discoverIntegrationComponents(integration)) {
655
- records.push(rec);
656
- }
665
+ // #collectIssues (above) already reported each withdrawn record,
666
+ // with its fix, through the same discovery.
667
+ const {components} =
668
+ await discoverValidIntegrationComponents(integration);
669
+ records.push(...components);
657
670
  } catch (err) {
658
671
  this.#pushIssue(pkg, {
659
672
  code: 'invalid_component',
@@ -668,17 +681,21 @@ export class Project {
668
681
  }
669
682
 
670
683
  /**
671
- * Core + integration templates, type-tagged. Wraps discoverTemplates (core +
672
- * external blocks) and discoverIntegrationTemplatesForOne per integration so
673
- * a broken integration's templates are skipped and its issues collected.
674
- * Memoized per instance.
684
+ * Core + integration templates, type-tagged, with valid integration
685
+ * replacements projected over their Core targets. Wraps raw template discovery
686
+ * (Core + external blocks) and discoverIntegrationTemplatesForOne per integration
687
+ * so unusable template files are reported and omitted while valid siblings
688
+ * remain available. Memoized per instance.
675
689
  *
676
690
  * @returns {Promise<Array<object>>}
677
691
  */
678
692
  async templates() {
679
- return this.#memo('templates', async () => {
693
+ if (this.#templatesPromise) return this.#templatesPromise;
694
+ this.#templatesPromise = (async () => {
680
695
  /** @type {any[]} */
681
696
  const templates = [];
697
+ /** @type {import('../discovery/template-adapter.mjs').TemplateDiscoveryError[]} */
698
+ const replacementErrors = [];
682
699
 
683
700
  // Core + external-package templates (discoverTemplates internally also
684
701
  // loads integration templates via loadConfig today; we intentionally
@@ -699,20 +716,24 @@ export class Project {
699
716
  for (const integration of this.#loadedIntegrations) {
700
717
  await this.#collectIssues(integration);
701
718
  const pkg = this.#pkgLabel(integration);
702
- if (this.#hasBlockingContributionIssue(pkg)) continue;
719
+ // Template discovery already isolates invalid template files and returns
720
+ // every valid sibling. Do not withdraw templates because another
721
+ // contribution kind in this package is broken.
703
722
  try {
704
723
  const {templates: ts, errors} =
705
724
  await discoverIntegrationTemplatesForOne(integration);
706
725
  for (const e of errors) {
707
726
  this.#pushIssue(pkg, {
708
- code: 'invalid_template',
709
- severity: 'error',
727
+ code: e.code ?? 'invalid_template',
728
+ severity: e.severity ?? 'error',
710
729
  message: e.message,
711
730
  });
731
+ if (e.replacementTarget != null) replacementErrors.push(e);
712
732
  }
713
- // Only contribute templates when the integration had no per-template
714
- // errors (skip the whole integration's templates on any error).
715
- if (errors.length === 0) templates.push(...ts);
733
+ // Discovery already omits each unusable template from `ts`. Keep all
734
+ // valid siblings, while the collected errors remain visible through
735
+ // issues() and replacement errors disable only their own targets.
736
+ templates.push(...ts);
716
737
  } catch (err) {
717
738
  this.#pushIssue(pkg, {
718
739
  code: 'invalid_template',
@@ -722,15 +743,24 @@ export class Project {
722
743
  }
723
744
  }
724
745
 
725
- return templates.sort((a, b) => a.name.localeCompare(b.name));
726
- });
746
+ const resolved = applyTemplateReplacements(templates, replacementErrors);
747
+ for (const error of resolved.errors) {
748
+ this.#pushIssue(error.package, {
749
+ code: error.code,
750
+ severity: error.severity,
751
+ message: error.message,
752
+ });
753
+ }
754
+ return effectiveTemplateDiscovery(resolved.templates);
755
+ })();
756
+ return this.#templatesPromise;
727
757
  }
728
758
 
729
759
  /**
730
760
  * Bundled source themes plus themes contributed by installed integrations.
731
761
  * Each record keeps its package owner and source directory so callers can
732
- * both list and copy it without reconstructing paths. A broken integration's
733
- * themes are skipped under the same issue policy as every other kind.
762
+ * both list and copy it without reconstructing paths. A broken theme
763
+ * contribution is reported without hiding the package's other valid kinds.
734
764
  *
735
765
  * @returns {Promise<import('../discovery/theme-discovery.mjs').DiscoveredTheme[]>}
736
766
  */
@@ -741,7 +771,6 @@ export class Project {
741
771
  for (const integration of this.#loadedIntegrations) {
742
772
  await this.#collectIssues(integration);
743
773
  const pkg = this.#pkgLabel(integration);
744
- if (this.#hasBlockingContributionIssue(pkg)) continue;
745
774
  if (!integration?.themes) continue;
746
775
  try {
747
776
  themes.push(...(await discoverIntegrationThemes(integration)));
@@ -775,14 +804,16 @@ export class Project {
775
804
  async docs() {
776
805
  return this.#memo('docs', async () => {
777
806
  const catalog = DocsCatalog.fromBuiltins();
807
+ let rank = 0;
778
808
 
779
809
  for (const integration of this.#loadedIntegrations) {
810
+ rank += 1;
780
811
  await this.#collectIssues(integration);
781
812
  const pkg = this.#pkgLabel(integration);
782
- if (this.#hasBlockingContributionIssue(pkg)) continue;
783
813
  if (!integration?.docs) continue;
784
814
  try {
785
- const {records, errors} = await discoverIntegrationDocs(integration);
815
+ const {records, errors, namespaces, guides} =
816
+ await discoverIntegrationDocs(integration);
786
817
  for (const e of errors) {
787
818
  this.#pushIssue(pkg, {
788
819
  code: 'invalid_doc',
@@ -794,11 +825,20 @@ export class Project {
794
825
  // how a bad template withdraws its package's templates: a partial
795
826
  // docs contribution is the state where a `replaces` silently does
796
827
  // nothing and a reader gets the topic it was meant to replace.
797
- if (errors.length > 0) continue;
828
+ if (errors.length > 0) {
829
+ for (const e of errors) {
830
+ catalog.addIssue({package: integration.name ?? pkg, message: e.message});
831
+ }
832
+ continue;
833
+ }
798
834
  for (const record of records) {
799
835
  const issue = catalog.add(record);
800
836
  if (issue) this.#pushIssue(pkg, issue);
801
837
  }
838
+ catalog.addTreeInputs({
839
+ namespaces: namespaces.map(input => ({...input, rank})),
840
+ guides: guides.map(input => ({...input, rank})),
841
+ });
802
842
  } catch (err) {
803
843
  this.#pushIssue(pkg, {
804
844
  code: 'invalid_doc',
@@ -815,8 +855,8 @@ export class Project {
815
855
  /**
816
856
  * Core registry transforms + integration codemods for an upgrade range.
817
857
  * Wraps getTransformsBetween (core) and discoverIntegrationCodemods /
818
- * selectIntegrationCodemods (integrations). A broken integration's codemods
819
- * are skipped (issue collected) rather than failing the whole resolution.
858
+ * selectIntegrationCodemods (integrations). An invalid codemod contribution
859
+ * is reported and omitted without hiding other valid contribution kinds.
820
860
  * Memoized per (from, to) key.
821
861
  *
822
862
  * @param {string} fromVersion exclusive lower bound
@@ -834,7 +874,6 @@ export class Project {
834
874
  for (const integration of this.#loadedIntegrations) {
835
875
  await this.#collectIssues(integration);
836
876
  const pkg = this.#pkgLabel(integration);
837
- if (this.#hasBlockingContributionIssue(pkg)) continue;
838
877
  if (!integration?.codemods) continue;
839
878
  try {
840
879
  // Validate this integration's codemods discover cleanly in
@@ -889,6 +928,10 @@ export class Project {
889
928
  * @returns {Promise<ProjectIntegrationIssue[]>}
890
929
  */
891
930
  async issues() {
931
+ // Template replacement validity depends on the combined Core + integration
932
+ // catalog. Resolve it first so issue results never depend on which discovery
933
+ // method the caller happened to invoke earlier.
934
+ await this.templates();
892
935
  for (const integration of this.#loadedIntegrations) {
893
936
  await this.#collectIssues(integration);
894
937
  }