@astryxdesign/cli 0.6.3 → 0.6.4-canary.078fd25

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 (728) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +152 -107
  3. package/api/blog/blog.doc.mjs +1 -0
  4. package/api/build/_adapter.d.mts +50 -0
  5. package/api/build/_adapter.mjs +60 -0
  6. package/api/build/build.doc.mjs +22 -10
  7. package/api/build/build.test.mjs +219 -8
  8. package/api/build/build.type.d.mts +91 -2
  9. package/api/build/build.type.mjs +52 -8
  10. package/api/build/help/help.d.mts +12 -5
  11. package/api/build/help/help.mjs +69 -6
  12. package/api/build/kit/kit.d.mts +4 -1
  13. package/api/build/kit/kit.mjs +208 -53
  14. package/api/build/kit/rank.d.mts +44 -0
  15. package/api/build/kit/rank.mjs +432 -0
  16. package/api/build/kit/rank.test.mjs +196 -0
  17. package/api/component/_adapter.d.mts +31 -12
  18. package/api/component/_adapter.mjs +79 -15
  19. package/api/component/component.d.mts +6 -3
  20. package/api/component/component.doc.mjs +49 -19
  21. package/api/component/component.mjs +339 -22
  22. package/api/component/component.test.mjs +38 -0
  23. package/api/component/component.type.d.mts +47 -11
  24. package/api/component/component.type.mjs +76 -24
  25. package/api/component/detail/blocks/blocks.d.mts +2 -1
  26. package/api/component/detail/blocks/blocks.mjs +4 -3
  27. package/api/component/list/list.d.mts +0 -5
  28. package/api/component/list/list.mjs +40 -11
  29. package/api/discover/_adapter.d.mts +114 -6
  30. package/api/discover/_adapter.mjs +372 -17
  31. package/api/discover/_adapter.test.mjs +215 -0
  32. package/api/discover/_catalog-view.d.mts +115 -0
  33. package/api/discover/_catalog-view.mjs +203 -0
  34. package/api/discover/_catalog-view.test.mjs +128 -0
  35. package/api/discover/detail/detail.d.mts +18 -6
  36. package/api/discover/detail/detail.mjs +67 -13
  37. package/api/discover/detail/detail.test.mjs +85 -0
  38. package/api/discover/detail/item/item.d.mts +26 -0
  39. package/api/discover/detail/item/item.mjs +78 -0
  40. package/api/discover/detail/item/item.test.mjs +73 -0
  41. package/api/discover/discover.d.mts +3 -9
  42. package/api/discover/discover.doc.mjs +62 -18
  43. package/api/discover/discover.mjs +220 -36
  44. package/api/discover/discover.test.mjs +11 -2
  45. package/api/discover/discover.type.d.mts +150 -11
  46. package/api/discover/discover.type.mjs +107 -17
  47. package/api/discover/list/list.d.mts +20 -6
  48. package/api/discover/list/list.mjs +45 -12
  49. package/api/discover/list/list.test.mjs +46 -0
  50. package/api/discover/search/search.d.mts +18 -16
  51. package/api/discover/search/search.mjs +102 -56
  52. package/api/discover/search/search.test.mjs +144 -10
  53. package/api/docs/_adapter.d.mts +277 -41
  54. package/api/docs/_adapter.mjs +993 -108
  55. package/api/docs/compiled-topics.test.mjs +78 -0
  56. package/api/docs/detail/detail.mjs +22 -63
  57. package/api/docs/detail/section/section.d.mts +1 -1
  58. package/api/docs/detail/section/section.mjs +54 -19
  59. package/api/docs/detail/section/section.test.mjs +50 -0
  60. package/api/docs/docOverlays.test.mjs +27 -1
  61. package/api/docs/docs.d.mts +10 -3
  62. package/api/docs/docs.doc.mjs +55 -16
  63. package/api/docs/docs.mjs +53 -10
  64. package/api/docs/docs.type.d.mts +221 -5
  65. package/api/docs/docs.type.mjs +153 -11
  66. package/api/docs/index/index.d.mts +18 -0
  67. package/api/docs/index/index.mjs +40 -0
  68. package/api/docs/index/index.test.mjs +62 -0
  69. package/api/docs/list/list.mjs +28 -12
  70. package/api/docs/node/node.d.mts +43 -0
  71. package/api/docs/node/node.mjs +192 -0
  72. package/api/docs/reference-blocks.test.mjs +406 -0
  73. package/api/doctor/doctor.d.mts +104 -1
  74. package/api/doctor/doctor.doc.mjs +18 -8
  75. package/api/doctor/doctor.mjs +635 -7
  76. package/api/doctor/doctor.test.mjs +732 -11
  77. package/api/doctor/doctor.type.d.mts +1 -1
  78. package/api/doctor/doctor.type.mjs +1 -1
  79. package/api/gap-report/gap-report.doc.mjs +27 -14
  80. package/api/hook/_adapter.mjs +19 -5
  81. package/api/hook/hook.doc.mjs +7 -3
  82. package/api/hook/hook.type.d.mts +3 -3
  83. package/api/hook/hook.type.mjs +11 -11
  84. package/api/hook/list/list.d.mts +2 -2
  85. package/api/hook/list/list.mjs +69 -17
  86. package/api/index.d.mts +2 -1
  87. package/api/index.mjs +6 -3
  88. package/api/init/init.doc.mjs +22 -12
  89. package/api/init/init.test.mjs +41 -1
  90. package/api/init/remove/remove.mjs +1 -1
  91. package/api/init/run/run.mjs +20 -10
  92. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  93. package/api/integration/add-contribution.d.mts +2 -1
  94. package/api/integration/add-contribution.mjs +130 -15
  95. package/api/integration/add-contribution.test.mjs +258 -7
  96. package/api/integration/add-helpers.d.mts +5 -2
  97. package/api/integration/add-helpers.mjs +36 -9
  98. package/api/integration/add-theme.mjs +56 -65
  99. package/api/integration/add-theme.test.mjs +139 -21
  100. package/api/integration/authoring-checks.mjs +138 -28
  101. package/api/integration/authoring-checks.test.mjs +179 -7
  102. package/api/integration/authoring-checks.type.mjs +6 -1
  103. package/api/integration/integration-authoring.type.d.mts +3 -1
  104. package/api/integration/integration-authoring.type.mjs +2 -0
  105. package/api/integration/integration-block-exports.test.mjs +10 -6
  106. package/api/integration/integrationAdd.doc.mjs +14 -4
  107. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  108. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  109. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  110. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  111. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  112. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  113. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  114. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  115. package/api/integration/integrationPackCheck.doc.mjs +5 -4
  116. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  117. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  118. package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
  119. package/api/integration/pack-check.mjs +160 -11
  120. package/api/integration/pack-check.test.mjs +477 -47
  121. package/api/integration/pack-check.type.d.mts +26 -2
  122. package/api/integration/pack-check.type.mjs +15 -2
  123. package/api/integration/summarizeIssues.doc.mjs +1 -0
  124. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  125. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  126. package/api/integration/validate-integration.mjs +52 -102
  127. package/api/integration/validate-integration.test.mjs +179 -26
  128. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  129. package/api/integration/validateIntegration.doc.mjs +3 -2
  130. package/api/json/assertResponse.doc.mjs +2 -1
  131. package/api/json/envelope-types.test.mjs +76 -0
  132. package/api/json/index.ts +2 -0
  133. package/api/json/isError.doc.mjs +2 -1
  134. package/api/json/parseResponse.doc.mjs +3 -2
  135. package/api/layout/_adapter.mjs +20 -5
  136. package/api/layout/expand/expand.mjs +7 -5
  137. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  138. package/api/layout/grammar/grammar.mjs +2 -1
  139. package/api/layout/layoutCheck.doc.mjs +1 -0
  140. package/api/layout/layoutExpand.doc.mjs +2 -1
  141. package/api/layout/layoutGrammar.doc.mjs +1 -0
  142. package/api/search/search-return-type.test.mjs +54 -0
  143. package/api/search/search.d.mts +89 -12
  144. package/api/search/search.doc.mjs +8 -2
  145. package/api/search/search.mjs +697 -97
  146. package/api/search/search.type.d.mts +15 -3
  147. package/api/search/search.type.mjs +5 -2
  148. package/api/swizzle/copy/copy.mjs +28 -11
  149. package/api/swizzle/swizzle.doc.mjs +8 -5
  150. package/api/swizzle/swizzle.type.d.mts +2 -2
  151. package/api/swizzle/swizzle.type.mjs +2 -2
  152. package/api/template/copy/copy.mjs +18 -24
  153. package/api/template/copy/copy.test.mjs +26 -0
  154. package/api/template/list/list.mjs +1 -0
  155. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  156. package/api/template/template-integration.test.mjs +1072 -3
  157. package/api/template/template-suffix.test.mjs +41 -21
  158. package/api/template/template.d.mts +1 -1
  159. package/api/template/template.doc.mjs +32 -9
  160. package/api/template/template.mjs +45 -8
  161. package/api/template/template.type.d.mts +12 -14
  162. package/api/template/template.type.mjs +15 -14
  163. package/api/theme/_adapter.d.mts +2 -3
  164. package/api/theme/_adapter.mjs +4 -5
  165. package/api/theme/add/add.binary.test.mjs +84 -0
  166. package/api/theme/add/add.mjs +31 -22
  167. package/api/theme/add/add.rollback.test.mjs +158 -0
  168. package/api/theme/add/add.staging.test.mjs +83 -0
  169. package/api/theme/add/add.test.mjs +14 -1
  170. package/api/theme/build/build.family.test.mjs +7 -12
  171. package/api/theme/build/build.mjs +140 -59
  172. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  173. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  174. package/api/theme/build/build.rollback.test.mjs +148 -0
  175. package/api/theme/build/build.test.mjs +127 -0
  176. package/api/theme/build/font-warning.mjs +3 -3
  177. package/api/theme/build/font-warning.test.mjs +5 -2
  178. package/api/theme/generateTonalPalette.doc.mjs +2 -2
  179. package/api/theme/integration-themes.test.mjs +39 -28
  180. package/api/theme/list/list.test.mjs +19 -20
  181. package/api/theme/listThemes.doc.mjs +6 -5
  182. package/api/theme/palette/generate/generate.mjs +8 -3
  183. package/api/theme/palette/generate/generate.test.mjs +96 -0
  184. package/api/theme/palette/generate/generator.d.mts +10 -13
  185. package/api/theme/palette/generate/generator.mjs +15 -4
  186. package/api/theme/palette/generate/generator.test.mjs +10 -0
  187. package/api/theme/template/template.mjs +11 -2
  188. package/api/theme/template/template.test.mjs +20 -0
  189. package/api/theme/theme.type.d.mts +170 -11
  190. package/api/theme/theme.type.mjs +94 -27
  191. package/api/theme/themeAdd.doc.mjs +12 -12
  192. package/api/theme/themeBuild.doc.mjs +21 -17
  193. package/api/theme/themeList.doc.mjs +6 -3
  194. package/api/theme/themeListAvailable.doc.mjs +6 -3
  195. package/api/theme/themePaletteGenerate.doc.mjs +16 -8
  196. package/api/theme/themeTargets.doc.mjs +4 -2
  197. package/api/theme/themeTemplate.doc.mjs +8 -3
  198. package/api/upgrade/_adapter.d.mts +32 -5
  199. package/api/upgrade/_adapter.mjs +139 -22
  200. package/api/upgrade/list/list.mjs +2 -1
  201. package/api/upgrade/list/list.test.mjs +73 -0
  202. package/api/upgrade/project-context.test.mjs +272 -0
  203. package/api/upgrade/provider-agreement.test.mjs +152 -0
  204. package/api/upgrade/run/files-changed.test.mjs +111 -0
  205. package/api/upgrade/run/run.mjs +358 -59
  206. package/api/upgrade/status/status.mjs +2 -2
  207. package/api/upgrade/upgrade.doc.mjs +32 -23
  208. package/api/upgrade/upgrade.type.d.mts +43 -5
  209. package/api/upgrade/upgrade.type.mjs +29 -13
  210. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  211. package/assets/codemods/__tests__/runner.test.mjs +332 -8
  212. package/assets/codemods/file-count.test.mjs +163 -0
  213. package/assets/codemods/integration-discovery.mjs +48 -4
  214. package/assets/codemods/integration-discovery.test.mjs +73 -0
  215. package/assets/codemods/integration-runner.mjs +59 -7
  216. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  217. package/assets/codemods/registry.mjs +1 -0
  218. package/assets/codemods/run-codemod.mjs +177 -34
  219. package/assets/codemods/runner.mjs +353 -104
  220. package/assets/codemods/term-log.mjs +32 -8
  221. package/assets/codemods/term-log.test.mjs +19 -1
  222. package/assets/codemods/transform-prop.mjs +109 -0
  223. package/assets/codemods/transform-prop.test.mjs +95 -0
  224. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  225. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  226. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  227. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  228. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  229. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  230. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  231. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  232. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  233. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  234. package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
  235. package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
  236. package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
  237. package/assets/docs/README.md +12 -1
  238. package/assets/docs/authoring.doc.mjs +14 -0
  239. package/assets/docs/browser-support.doc.mjs +11 -11
  240. package/assets/docs/color.doc.mjs +8 -2
  241. package/assets/docs/elevation.doc.mjs +6 -4
  242. package/assets/docs/getting-started.doc.mjs +6 -17
  243. package/assets/docs/icons.doc.mjs +2 -21
  244. package/assets/docs/illustrations.doc.mjs +7 -15
  245. package/assets/docs/internationalization.doc.mjs +7 -5
  246. package/assets/docs/layout.doc.dense.mjs +132 -84
  247. package/assets/docs/layout.doc.mjs +134 -78
  248. package/assets/docs/migration.doc.mjs +19 -21
  249. package/assets/docs/motion.doc.mjs +16 -3
  250. package/assets/docs/principles.doc.dense.mjs +5 -5
  251. package/assets/docs/principles.doc.mjs +14 -6
  252. package/assets/docs/principles.doc.zh.mjs +6 -6
  253. package/assets/docs/shape.doc.mjs +8 -3
  254. package/assets/docs/spacing.doc.mjs +7 -2
  255. package/assets/docs/styling-libraries.doc.mjs +10 -6
  256. package/assets/docs/styling.doc.mjs +22 -26
  257. package/assets/docs/theme.doc.dense.mjs +58 -18
  258. package/assets/docs/theme.doc.mjs +60 -50
  259. package/assets/docs/theme.doc.zh.mjs +9 -8
  260. package/assets/docs/tokens.doc.dense.mjs +2 -2
  261. package/assets/docs/tokens.doc.mjs +390 -9
  262. package/assets/docs/tokens.doc.zh.mjs +2 -2
  263. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  264. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  265. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  266. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  267. package/assets/docs/tree/api.doc.mjs +30 -0
  268. package/assets/docs/tree/block-template.doc.mjs +130 -0
  269. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  270. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  271. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  272. package/assets/docs/tree/checks.doc.mjs +119 -0
  273. package/assets/docs/tree/cli.doc.mjs +23 -0
  274. package/assets/docs/tree/codemods.doc.mjs +147 -0
  275. package/assets/docs/tree/commands.doc.mjs +25 -0
  276. package/assets/docs/tree/component-family.doc.mjs +113 -0
  277. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  278. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  279. package/assets/docs/tree/components.doc.mjs +23 -0
  280. package/assets/docs/tree/configuration.doc.mjs +23 -0
  281. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  282. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  283. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  284. package/assets/docs/tree/docs.doc.mjs +21 -0
  285. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  286. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  287. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  288. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  289. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  290. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  291. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  292. package/assets/docs/tree/help.doc.mjs +16 -0
  293. package/assets/docs/tree/integrations.doc.mjs +40 -0
  294. package/assets/docs/tree/links.doc.mjs +98 -0
  295. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  296. package/assets/docs/tree/page-template.doc.mjs +71 -0
  297. package/assets/docs/tree/publishing.doc.mjs +111 -0
  298. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  299. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  300. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  301. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  302. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  303. package/assets/docs/tree/ship.doc.mjs +16 -0
  304. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  305. package/assets/docs/tree/single-component.doc.mjs +165 -0
  306. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  307. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  308. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  309. package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
  310. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  311. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  312. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  313. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  314. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  315. package/assets/docs/tree/templates.doc.mjs +34 -0
  316. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  317. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  318. package/assets/docs/tree/themes.doc.mjs +39 -0
  319. package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
  320. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  321. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  322. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  323. package/assets/docs/tree/versioning.doc.mjs +161 -0
  324. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  325. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  326. package/assets/docs/typography.doc.mjs +24 -4
  327. package/assets/docs/working-with-ai.doc.mjs +34 -26
  328. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  329. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  330. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  331. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  332. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  333. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  334. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  335. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  336. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  337. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  338. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  339. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  340. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  341. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  342. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  343. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  344. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  345. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  346. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  347. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  348. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  349. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  350. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  351. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
  352. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
  353. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
  354. package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
  355. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
  356. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
  357. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
  358. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
  359. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
  360. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
  361. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  362. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  363. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  364. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  365. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  366. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  367. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  368. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  369. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  370. package/authoring/_shared/contract.ts +22 -0
  371. package/authoring/codemod/codemod.doc.mjs +7 -2
  372. package/authoring/codemod/parse.d.mts +8 -8
  373. package/authoring/codemod/parse.mjs +8 -6
  374. package/authoring/codemod/type.ts +12 -0
  375. package/authoring/config/config.doc.mjs +11 -3
  376. package/authoring/config/debug-composition.test.mjs +92 -0
  377. package/authoring/config/parse.d.mts +15 -13
  378. package/authoring/config/parse.mjs +27 -8
  379. package/authoring/config/parse.test.mjs +8 -0
  380. package/authoring/config/type.ts +29 -6
  381. package/authoring/debug/debug.doc.d.mts +11 -0
  382. package/authoring/debug/debug.doc.mjs +182 -0
  383. package/authoring/debug/parse.d.mts +8 -8
  384. package/authoring/debug/parse.mjs +3 -3
  385. package/authoring/discover/discover.doc.d.mts +13 -0
  386. package/authoring/discover/discover.doc.mjs +138 -0
  387. package/authoring/discover/parse.d.mts +24 -0
  388. package/authoring/discover/parse.mjs +128 -0
  389. package/authoring/discover/parse.test.mjs +124 -0
  390. package/authoring/discover/type.ts +87 -0
  391. package/authoring/doctypes/_schema.d.mts +792 -24
  392. package/authoring/doctypes/_schema.mjs +549 -39
  393. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  394. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  395. package/authoring/doctypes/base/type.ts +43 -0
  396. package/authoring/doctypes/command/command.doc.mjs +4 -3
  397. package/authoring/doctypes/command/parse.d.mts +2 -2
  398. package/authoring/doctypes/command/parse.mjs +1 -1
  399. package/authoring/doctypes/command/type.ts +5 -4
  400. package/authoring/doctypes/component/component.doc.mjs +12 -3
  401. package/authoring/doctypes/component/parse.d.mts +2 -2
  402. package/authoring/doctypes/component/parse.mjs +1 -1
  403. package/authoring/doctypes/component/type.ts +14 -5
  404. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  405. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  406. package/authoring/doctypes/enum/parse.d.mts +2 -2
  407. package/authoring/doctypes/enum/parse.mjs +1 -1
  408. package/authoring/doctypes/enum/type.ts +4 -2
  409. package/authoring/doctypes/function/function.doc.mjs +7 -2
  410. package/authoring/doctypes/function/parse.d.mts +2 -2
  411. package/authoring/doctypes/function/parse.mjs +1 -1
  412. package/authoring/doctypes/function/type.ts +9 -4
  413. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  414. package/authoring/doctypes/hook/parse.d.mts +2 -2
  415. package/authoring/doctypes/hook/parse.mjs +1 -1
  416. package/authoring/doctypes/hook/type.ts +5 -4
  417. package/authoring/doctypes/legacy.d.mts +8 -6
  418. package/authoring/doctypes/legacy.mjs +5 -4
  419. package/authoring/doctypes/load-contract.test.mjs +233 -0
  420. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  421. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  422. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  423. package/authoring/doctypes/namespace/parse.mjs +25 -0
  424. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  425. package/authoring/doctypes/namespace/type.ts +74 -0
  426. package/authoring/doctypes/parse.d.mts +22 -18
  427. package/authoring/doctypes/parse.mjs +22 -11
  428. package/authoring/doctypes/parse.test.mjs +77 -3
  429. package/authoring/doctypes/reference/parse.d.mts +2 -2
  430. package/authoring/doctypes/reference/parse.mjs +8 -5
  431. package/authoring/doctypes/reference/reference.doc.mjs +55 -6
  432. package/authoring/doctypes/reference/type.ts +75 -7
  433. package/authoring/doctypes/schema/parse.d.mts +2 -2
  434. package/authoring/doctypes/schema/parse.mjs +1 -1
  435. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  436. package/authoring/doctypes/schema/type.ts +4 -4
  437. package/authoring/doctypes/template/parse.d.mts +94 -1
  438. package/authoring/doctypes/template/parse.mjs +40 -2
  439. package/authoring/doctypes/template/parse.test.mjs +26 -2
  440. package/authoring/doctypes/template/template.doc.mjs +13 -3
  441. package/authoring/doctypes/template/type.ts +13 -2
  442. package/authoring/doctypes/theme/parse.d.mts +35 -0
  443. package/authoring/doctypes/theme/parse.mjs +76 -0
  444. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  445. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  446. package/authoring/doctypes/theme/type.ts +42 -0
  447. package/authoring/doctypes/types.ts +12 -10
  448. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  449. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  450. package/authoring/gap-report/parse.d.mts +10 -10
  451. package/authoring/gap-report/parse.mjs +6 -6
  452. package/authoring/gap-report/type.ts +1 -1
  453. package/authoring/identity/identity.doc.d.mts +9 -0
  454. package/authoring/identity/identity.doc.mjs +61 -0
  455. package/authoring/identity/type.ts +132 -0
  456. package/authoring/index.d.mts +3 -0
  457. package/authoring/index.d.ts +62 -17
  458. package/authoring/index.mjs +4 -1
  459. package/authoring/integration/integration.doc.mjs +22 -13
  460. package/authoring/integration/parse.d.mts +2 -2
  461. package/authoring/integration/parse.mjs +1 -1
  462. package/authoring/integration/parse.test.mjs +10 -1
  463. package/authoring/integration/schema.d.mts +6 -4
  464. package/authoring/integration/schema.mjs +9 -3
  465. package/authoring/integration/type.ts +19 -8
  466. package/authoring/shadcn/receipt.d.mts +6 -6
  467. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  468. package/clients/cli/command-load-failure.test.mjs +83 -0
  469. package/clients/cli/commands/blog.doc.mjs +1 -1
  470. package/clients/cli/commands/blog.mjs +23 -8
  471. package/clients/cli/commands/blog.test.mjs +42 -1
  472. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  473. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  474. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  475. package/clients/cli/commands/build-theme.mjs +16 -50
  476. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  477. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  478. package/clients/cli/commands/build.doc.mjs +16 -8
  479. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  480. package/clients/cli/commands/build.mjs +137 -114
  481. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  482. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  483. package/clients/cli/commands/component/index.mjs +153 -61
  484. package/clients/cli/commands/component-batch.test.mjs +341 -0
  485. package/clients/cli/commands/component-ownership.test.mjs +92 -3
  486. package/clients/cli/commands/component-package.test.mjs +46 -0
  487. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  488. package/clients/cli/commands/component.doc.mjs +28 -10
  489. package/clients/cli/commands/component.test.mjs +19 -0
  490. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  491. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  492. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  493. package/clients/cli/commands/discover.doc.mjs +55 -9
  494. package/clients/cli/commands/discover.mjs +393 -118
  495. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  496. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  497. package/clients/cli/commands/docs.doc.mjs +28 -6
  498. package/clients/cli/commands/docs.mjs +295 -38
  499. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  500. package/clients/cli/commands/doctor-integration-docs.doc.mjs +6 -5
  501. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  502. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  503. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  504. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  505. package/clients/cli/commands/doctor-integration.test.mjs +143 -8
  506. package/clients/cli/commands/doctor.doc.mjs +4 -2
  507. package/clients/cli/commands/doctor.mjs +108 -37
  508. package/clients/cli/commands/doctor.test.mjs +42 -0
  509. package/clients/cli/commands/gap-report.doc.mjs +27 -15
  510. package/clients/cli/commands/gap-report.test.mjs +72 -0
  511. package/clients/cli/commands/hook/index.mjs +7 -17
  512. package/clients/cli/commands/hook.doc.mjs +1 -1
  513. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  514. package/clients/cli/commands/init.doc.mjs +24 -10
  515. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  516. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  517. package/clients/cli/commands/integration-add.doc.mjs +39 -13
  518. package/clients/cli/commands/integration-authoring.test.mjs +74 -19
  519. package/clients/cli/commands/integration-pack.doc.mjs +6 -10
  520. package/clients/cli/commands/integration-real-world.test.mjs +4 -10
  521. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  522. package/clients/cli/commands/integration.doc.mjs +5 -5
  523. package/clients/cli/commands/integration.mjs +75 -43
  524. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  525. package/clients/cli/commands/json-contract.test.mjs +33 -0
  526. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  527. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  528. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  529. package/clients/cli/commands/layout.doc.mjs +3 -3
  530. package/clients/cli/commands/layout.mjs +21 -9
  531. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  532. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  533. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  534. package/clients/cli/commands/manifest.doc.mjs +2 -2
  535. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  536. package/clients/cli/commands/search.doc.mjs +16 -6
  537. package/clients/cli/commands/search.mjs +49 -11
  538. package/clients/cli/commands/search.test.mjs +92 -0
  539. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  540. package/clients/cli/commands/swizzle.doc.mjs +4 -3
  541. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  542. package/clients/cli/commands/template.doc.mjs +53 -14
  543. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  544. package/clients/cli/commands/template.mjs +4 -91
  545. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  546. package/clients/cli/commands/text-json-parity.test.mjs +725 -0
  547. package/clients/cli/commands/theme-add.doc.mjs +5 -4
  548. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  549. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  550. package/clients/cli/commands/theme-palette-generate.doc.mjs +12 -7
  551. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  552. package/clients/cli/commands/theme-palette.doc.mjs +2 -3
  553. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  554. package/clients/cli/commands/theme-targets.doc.mjs +3 -3
  555. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  556. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  557. package/clients/cli/commands/theme.doc.mjs +3 -2
  558. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  559. package/clients/cli/commands/upgrade.doc.mjs +83 -12
  560. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  561. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  562. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  563. package/clients/cli/commands/upgrade.mjs +29 -7
  564. package/clients/cli/formatters/index.mjs +164 -1
  565. package/clients/cli/formatters/index.test.mjs +97 -0
  566. package/clients/cli/index.mjs +47 -34
  567. package/clients/cli/latest-version-env.test.mjs +50 -0
  568. package/clients/cli/lib/cli-error.test.mjs +7 -0
  569. package/clients/cli/lib/component-format.mjs +9 -9
  570. package/clients/cli/lib/component-format.test.mjs +1 -1
  571. package/clients/cli/lib/define-command.mjs +56 -6
  572. package/clients/cli/lib/define-command.test.mjs +54 -0
  573. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  574. package/clients/cli/lib/exit-codes.test.mjs +113 -0
  575. package/clients/cli/lib/hook-format.mjs +19 -10
  576. package/clients/cli/lib/json-shim.mjs +62 -16
  577. package/clients/cli/lib/json-shim.test.mjs +83 -0
  578. package/clients/cli/lib/manifest.d.ts +2 -0
  579. package/clients/cli/lib/manifest.mjs +53 -6
  580. package/clients/cli/lib/manifest.test.mjs +22 -2
  581. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  582. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  583. package/foundation/agent-docs/agent-docs.mjs +83 -13
  584. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  585. package/foundation/config/integration-debug.test.mjs +28 -3
  586. package/foundation/config/project-themes.test.mjs +11 -19
  587. package/foundation/config/project.d.mts +20 -11
  588. package/foundation/config/project.mjs +263 -91
  589. package/foundation/config/project.test.mjs +270 -21
  590. package/foundation/discovery/authoring-self-docs.d.mts +87 -0
  591. package/foundation/discovery/authoring-self-docs.mjs +237 -0
  592. package/foundation/discovery/authoring-self-docs.test.mjs +174 -0
  593. package/foundation/discovery/authoring-surface.d.mts +74 -0
  594. package/foundation/discovery/authoring-surface.mjs +525 -0
  595. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  596. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  597. package/foundation/discovery/cli-self-docs.mjs +504 -0
  598. package/foundation/discovery/cli-self-docs.test.mjs +395 -0
  599. package/foundation/discovery/component-discovery.d.mts +39 -1
  600. package/foundation/discovery/component-discovery.mjs +50 -1
  601. package/foundation/discovery/component-loader.d.mts +35 -38
  602. package/foundation/discovery/component-loader.mjs +53 -222
  603. package/foundation/discovery/docs-discovery.d.mts +119 -11
  604. package/foundation/discovery/docs-discovery.mjs +427 -108
  605. package/foundation/discovery/docs-discovery.test.mjs +386 -20
  606. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  607. package/foundation/discovery/docs-output-budget.mjs +50 -0
  608. package/foundation/discovery/docs-section-key.d.mts +116 -0
  609. package/foundation/discovery/docs-section-key.mjs +322 -0
  610. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  611. package/foundation/discovery/template-adapter.d.mts +113 -11
  612. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  613. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  614. package/foundation/discovery/template-adapter.mjs +774 -83
  615. package/foundation/discovery/template-adapter.test.mjs +57 -0
  616. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  617. package/foundation/discovery/template-conflict-release.mjs +40 -0
  618. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  619. package/foundation/discovery/theme-discovery.d.mts +67 -7
  620. package/foundation/discovery/theme-discovery.mjs +916 -186
  621. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  622. package/foundation/discovery/theming-targets.test.mjs +4 -0
  623. package/foundation/doc-compiler/bundle.d.mts +47 -0
  624. package/foundation/doc-compiler/bundle.mjs +278 -0
  625. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  626. package/foundation/doc-compiler/compile.d.mts +343 -0
  627. package/foundation/doc-compiler/compile.mjs +558 -0
  628. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  629. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  630. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  631. package/foundation/doc-compiler/doc-loads.test.mjs +1643 -0
  632. package/foundation/doc-compiler/import.d.mts +24 -0
  633. package/foundation/doc-compiler/import.mjs +59 -0
  634. package/foundation/doc-compiler/inputs.d.mts +102 -0
  635. package/foundation/doc-compiler/inputs.mjs +291 -0
  636. package/foundation/doc-compiler/inputs.test.mjs +298 -0
  637. package/foundation/doc-compiler/ir.d.mts +22 -0
  638. package/foundation/doc-compiler/ir.mjs +471 -0
  639. package/foundation/doc-compiler/lenses.d.mts +36 -0
  640. package/foundation/doc-compiler/lenses.mjs +173 -0
  641. package/foundation/doc-compiler/links.d.mts +162 -0
  642. package/foundation/doc-compiler/links.mjs +294 -0
  643. package/foundation/doc-compiler/links.test.mjs +192 -0
  644. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  645. package/foundation/doc-compiler/overlays.d.mts +37 -0
  646. package/foundation/doc-compiler/overlays.mjs +206 -0
  647. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  648. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  649. package/foundation/doc-compiler/read.d.mts +127 -0
  650. package/foundation/doc-compiler/read.mjs +325 -0
  651. package/foundation/doc-compiler/read.test.mjs +313 -0
  652. package/foundation/doc-compiler/source.d.mts +33 -0
  653. package/foundation/doc-compiler/source.mjs +128 -0
  654. package/foundation/doc-compiler/tree.d.mts +292 -0
  655. package/foundation/doc-compiler/tree.mjs +881 -0
  656. package/foundation/fs/file-protection.d.mts +33 -0
  657. package/foundation/fs/file-protection.mjs +825 -0
  658. package/foundation/fs/file-protection.test.mjs +250 -0
  659. package/foundation/fs/module-loader.d.mts +1 -0
  660. package/foundation/fs/module-loader.mjs +50 -1
  661. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  662. package/foundation/fs/path-safety.d.mts +3 -2
  663. package/foundation/fs/path-safety.mjs +49 -19
  664. package/foundation/fs/path-safety.test.mjs +50 -0
  665. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  666. package/foundation/identity/provider-identity.d.mts +90 -0
  667. package/foundation/identity/provider-identity.mjs +320 -0
  668. package/foundation/identity/provider-identity.test.mjs +254 -0
  669. package/foundation/identity/providers.d.mts +7 -0
  670. package/foundation/identity/providers.mjs +16 -0
  671. package/foundation/integrations/autolink.d.mts +58 -1
  672. package/foundation/integrations/autolink.mjs +143 -45
  673. package/foundation/integrations/autolink.test.mjs +1 -1
  674. package/foundation/integrations/cli-requirement.d.mts +65 -0
  675. package/foundation/integrations/cli-requirement.mjs +189 -0
  676. package/foundation/integrations/cli-requirement.test.mjs +89 -0
  677. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  678. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  679. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  680. package/foundation/integrations/contribution-inventory.mjs +28 -25
  681. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  682. package/foundation/integrations/integration-warnings.d.mts +9 -2
  683. package/foundation/integrations/integration-warnings.mjs +52 -21
  684. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  685. package/foundation/integrations/integrations.d.mts +63 -3
  686. package/foundation/integrations/integrations.mjs +122 -9
  687. package/foundation/integrations/integrations.test.mjs +415 -1
  688. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  689. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  690. package/foundation/integrations/provider-resolution.d.mts +152 -0
  691. package/foundation/integrations/provider-resolution.mjs +576 -0
  692. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  693. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  694. package/foundation/integrations/theme-descriptor.mjs +44 -0
  695. package/foundation/integrations/validate-contributions.d.mts +2 -0
  696. package/foundation/integrations/validate-contributions.mjs +131 -29
  697. package/foundation/response/base.d.ts +8 -4
  698. package/foundation/response/batch.type.d.mts +33 -0
  699. package/foundation/response/batch.type.mjs +34 -0
  700. package/foundation/response/error-codes.d.mts +3 -1
  701. package/foundation/response/error-codes.d.ts +2 -0
  702. package/foundation/response/error-codes.doc.mjs +19 -12
  703. package/foundation/response/error-codes.mjs +8 -2
  704. package/foundation/response/error-codes.test.mjs +166 -14
  705. package/foundation/response/json-contract.test.mjs +57 -17
  706. package/foundation/response/json.d.mts +4 -2
  707. package/foundation/response/json.mjs +8 -10
  708. package/foundation/response/response-types.doc.d.mts +7 -2
  709. package/foundation/response/response-types.doc.mjs +69 -25
  710. package/foundation/response/response-types.doc.test.mjs +181 -0
  711. package/foundation/response/response.doc.mjs +12 -11
  712. package/foundation/text/string-utils.d.mts +8 -0
  713. package/foundation/text/string-utils.mjs +40 -10
  714. package/foundation/xle/expand.d.mts +2 -0
  715. package/foundation/xle/expand.mjs +4 -3
  716. package/foundation/xle/expand.test.mjs +54 -0
  717. package/foundation/xle/xle.test.mjs +13 -0
  718. package/package.json +10 -11
  719. package/api/docs/docs.test.mjs +0 -83
  720. package/api/docs/integrationDocs.test.mjs +0 -208
  721. package/api/search/search.test.mjs +0 -389
  722. package/assets/docs/cli-integrations.doc.mjs +0 -367
  723. package/assets/templates/themes/manifest.json +0 -95
  724. package/clients/cli/commands/docs.test.mjs +0 -102
  725. package/clients/cli/lib/update-check.mjs +0 -83
  726. package/clients/cli/lib/update-check.test.mjs +0 -137
  727. package/clients/cli/update-hint-commands.test.mjs +0 -54
  728. package/foundation/agent-docs/agent-docs.test.mjs +0 -1141
@@ -23,14 +23,17 @@
23
23
 
24
24
  import * as fs from 'node:fs';
25
25
  import * as path from 'node:path';
26
- import {createJiti} from 'jiti';
27
- import {loadModuleWithParser} from '../fs/module-loader.mjs';
28
- import {parseTemplate} from '../../authoring/doctypes/template/parse.mjs';
26
+ import {createRequire} from 'node:module';
27
+ import {readDocView} from '../doc-compiler/read.mjs';
28
+ import {importDocModule} from '../doc-compiler/import.mjs';
29
29
  import {CLI_ROOT, discoverExternalPackages} from '../fs/paths.mjs';
30
+ import {CORE_PROVIDER_ID} from '../identity/providers.mjs';
30
31
  import {Project} from '../config/project.mjs';
31
32
 
33
+ const require = createRequire(import.meta.url);
34
+
32
35
  /** Identity used for core (built-in) templates in package-scoped listings. */
33
- const CORE_PACKAGE = '@astryxdesign/core';
36
+ const CORE_PACKAGE = CORE_PROVIDER_ID;
34
37
 
35
38
  /**
36
39
  * Identity for a template in package-scoped views. Core (built-in) templates
@@ -42,6 +45,53 @@ export function pkgOf(t) {
42
45
  return t.package ?? CORE_PACKAGE;
43
46
  }
44
47
 
48
+ /**
49
+ * Every id that should resolve to a discovered template. Replacements keep
50
+ * their own integration id and also own the Core id they replace.
51
+ * @param {{dirName: string, replaces?: string}} template
52
+ * @returns {string[]}
53
+ */
54
+ export function templateLookupIds(template) {
55
+ if (template.replaces && template.replaces !== template.dirName) {
56
+ return [template.dirName, template.replaces];
57
+ }
58
+ return [template.dirName];
59
+ }
60
+
61
+ /**
62
+ * Remove entries shadowed in the default discovery view while retaining them in
63
+ * package-scoped views. An active replacement owns its target id. A rejected
64
+ * same-id declaration falls back to Core when a Core template of the same kind
65
+ * owns that id; otherwise the integration template remains available by kind.
66
+ * @param {DiscoveredTemplate[]} templates
67
+ * @returns {DiscoveredTemplate[]}
68
+ */
69
+ export function effectiveTemplateDiscovery(templates) {
70
+ const activeTargets = new Set(
71
+ templates
72
+ .filter(template => template.replaces != null)
73
+ .map(template => `${template.type}:${template.replaces}`),
74
+ );
75
+ const coreIds = new Set(
76
+ templates
77
+ .filter(template => pkgOf(template) === CORE_PACKAGE)
78
+ .map(template => `${template.type}:${template.dirName}`),
79
+ );
80
+ return templates.filter(template => {
81
+ if (
82
+ template.replacementRejected &&
83
+ template.replacementTarget === template.dirName &&
84
+ coreIds.has(`${template.type}:${template.dirName}`)
85
+ ) {
86
+ return false;
87
+ }
88
+ return (
89
+ !activeTargets.has(`${template.type}:${template.dirName}`) ||
90
+ template.replaces != null
91
+ );
92
+ });
93
+ }
94
+
45
95
  /**
46
96
  * A discovered template (page or block), normalized across core, external, and
47
97
  * integration sources. Not every source populates every field, so
@@ -64,6 +114,11 @@ export function pkgOf(t) {
64
114
  * @property {string} filePath
65
115
  * @property {string} docPath
66
116
  * @property {string} [package]
117
+ * @property {boolean} [autolinked] whether the owning integration was discovered
118
+ * from package.json rather than named in astryx.config
119
+ * @property {string} [replaces] active Core template id this integration template replaces
120
+ * @property {boolean} [replacementRejected] whether an invalid declaration was disabled
121
+ * @property {string} [replacementTarget] disabled declaration target
67
122
  */
68
123
 
69
124
  /**
@@ -72,6 +127,15 @@ export function pkgOf(t) {
72
127
  * @property {string} package
73
128
  * @property {string} [template]
74
129
  * @property {string} message
130
+ * @property {string} [code]
131
+ * @property {'warning' | 'error'} [severity]
132
+ * @property {string} [replacementTarget] Core target whose replacement set is invalid
133
+ * @property {boolean} [autolinked] whether the declaration came from an autolinked integration
134
+ */
135
+
136
+ /**
137
+ * A semantic error in an integration template replacement declaration.
138
+ * @typedef {TemplateDiscoveryError & {code: 'missing_template_replacement_target' | 'ambiguous_template_replacement' | 'invalid_template_replacement', severity: 'warning' | 'error'}} TemplateReplacementError
75
139
  */
76
140
 
77
141
  /**
@@ -80,31 +144,28 @@ export function pkgOf(t) {
80
144
  */
81
145
 
82
146
  /**
83
- * Canonical basename suffixes for template-spec files, in precedence order.
84
- * A template spec is a scaffoldable TEMPLATE (a plain object stamped with a
85
- * `type` of `'page'` or `'block'`), so `.template.*` is the descriptive family
86
- * name.
147
+ * Released compatibility suffixes, in precedence order. Stable 0.6.0
148
+ * documented `.template.*`, so discovery keeps reading those files while all
149
+ * new authoring uses `.doc.mjs`.
87
150
  */
88
151
  const TEMPLATE_SUFFIXES = ['.template.ts', '.template.mjs', '.template.js'];
89
152
 
90
153
  /**
91
- * Legacy basename suffixes for template-spec files, in precedence order.
92
- * `.doc.*` was inherited from the component-doc convention before templates
93
- * had their own name; it is still accepted during the transition window.
154
+ * Descriptor suffixes for templates, in precedence order. New authoring always
155
+ * emits `.doc.mjs`; the TypeScript and JavaScript variants remain readable.
94
156
  */
95
157
  const DOC_SUFFIXES = ['.doc.ts', '.doc.mjs', '.doc.js'];
96
158
 
97
159
  /**
98
- * The union of canonical + legacy template-spec suffixes, canonical first so
99
- * `.template.*` wins over `.doc.*` when both stems exist. All template
100
- * discovery matches this union so a `Foo.template.ts` file is treated exactly
101
- * like a legacy `Foo.doc.mjs`.
160
+ * Every template-spec suffix, in the released precedence a core page directory
161
+ * uses to pick one file. Integration discovery never picks: every match is a
162
+ * template, so two specs for one stem list twice and read as ambiguous.
102
163
  */
103
164
  const ALL_TEMPLATE_SUFFIXES = [...TEMPLATE_SUFFIXES, ...DOC_SUFFIXES];
104
165
 
105
166
  /**
106
167
  * The template-spec suffix present on `file`, or null if none matches.
107
- * Recognizes both the canonical `.template.*` and legacy `.doc.*` families.
168
+ * Recognizes both the canonical `.doc.*` and released `.template.*` families.
108
169
  * @param {string} file
109
170
  * @returns {string | null}
110
171
  */
@@ -118,16 +179,6 @@ function matchedTemplateSuffix(file) {
118
179
  */
119
180
  const TEMPLATE_SUFFIX_RE = /\.(template|doc)\.(ts|mjs|js)$/;
120
181
 
121
- /** @type {ReturnType<typeof createJiti> | undefined} */
122
- let jitiInstance;
123
- /** Lazily-created jiti for loading `.ts` template specs (JSX-capable). */
124
- function getJiti() {
125
- if (!jitiInstance) {
126
- jitiInstance = createJiti(import.meta.url, {jsx: true});
127
- }
128
- return jitiInstance;
129
- }
130
-
131
182
  /**
132
183
  * Load an integration template doc module and validate it against the template
133
184
  * envelope at the load boundary. Default export only — `.ts` via jiti,
@@ -140,7 +191,13 @@ function getJiti() {
140
191
  * @param {string} [label]
141
192
  */
142
193
  async function loadIntegrationDoc(file, label) {
143
- return loadModuleWithParser(file, parseTemplate, {label});
194
+ return readDocView(file, {
195
+ root: 'templates',
196
+ exports: ['default'],
197
+ label: label ?? file,
198
+ strict: true,
199
+ value: 'parsed',
200
+ });
144
201
  }
145
202
 
146
203
  const TEMPLATES_DIR = path.join(CLI_ROOT, 'assets', 'templates');
@@ -184,17 +241,53 @@ const IMAGE_EXTENSIONS = new Set([
184
241
  ]);
185
242
 
186
243
  /**
187
- * Demo-asset sources to strip from scaffolded projects. Template demo imagery
244
+ * First path segment of every Astryx template fixture. Template demo imagery
188
245
  * is self-hosted under the docsite's `/template-assets/*` dir (committed there,
189
- * mirrored into the sandbox preview by scripts/sync-templates.js). Those paths
190
- * only resolve inside the Astryx docsite/sandbox, so on scaffold they're
191
- * replaced — a scaffolded project has no `/template-assets/` dir and would
192
- * otherwise 404. Genuine third-party URLs (e.g. brand logos from
193
- * paypalobjects.com) are intentionally left untouched.
194
- *
195
- * @type {RegExp}
246
+ * mirrored into the sandbox preview by scripts/sync-templates.js), so those
247
+ * paths only resolve inside the Astryx docsite/sandbox and are replaced on
248
+ * scaffold. Only a root-relative URL whose first segment this is counts: the
249
+ * same text inside a third-party URL or a product path is left untouched.
196
250
  */
197
- const DEMO_ASSET_PATTERN = /\/template-assets\/[\w.-]+\.(\w+)/g;
251
+ const FIXTURE_SEGMENT = 'template-assets';
252
+
253
+ /** Characters that end a URL token in template source, besides whitespace. */
254
+ const TOKEN_DELIMITERS = new Set([
255
+ "'",
256
+ '"',
257
+ '`',
258
+ '(',
259
+ ')',
260
+ '<',
261
+ '>',
262
+ '{',
263
+ '}',
264
+ '[',
265
+ ']',
266
+ '\\',
267
+ '|',
268
+ '^',
269
+ ]);
270
+
271
+ /** The closing delimiter each opening delimiter must pair with. */
272
+ const CLOSING_DELIMITERS = new Map([
273
+ ["'", "'"],
274
+ ['"', '"'],
275
+ ['`', '`'],
276
+ ['(', ')'],
277
+ ]);
278
+ const CLOSERS = new Set(CLOSING_DELIMITERS.values());
279
+
280
+ /** A URL with a scheme: absolute, so never a fixture reference. */
281
+ const ABSOLUTE_URL = /^[a-z][a-z\d+.-]*:/iu;
282
+
283
+ /** What may lead up to the fixture segment inside a relative product path. */
284
+ const RELATIVE_PATH_PREFIX = /^[\w.~%@/-]+$/u;
285
+
286
+ /** Punctuation that ends a sentence or list item after a path in text. */
287
+ const PROSE_PUNCTUATION = new Set(['.', ',', ';', ':', '!', '?']);
288
+
289
+ /** `from`, `import` or `require` right before a quoted module specifier. */
290
+ const MODULE_SPECIFIER_LEAD = /(?:^|[^\w$])(?:from|import|require)\s*\(?$/u;
198
291
 
199
292
  /**
200
293
  * Normalize path into Unix path (using forward slashes) for consistent comparison
@@ -208,36 +301,255 @@ function toPosixPath(p) {
208
301
  }
209
302
 
210
303
  /**
211
- * Replace demo asset references with a placeholder so scaffolded pages
212
- * render with zero setup. Images get a self-contained data URI; videos
213
- * (which have no equivalent inline placeholder — see VIDEO_EXTENSIONS) are
214
- * stripped to an empty src instead of being mis-replaced with image data.
215
- * Builders drop in their own media either way.
304
+ * Replace each Astryx template fixture reference with a placeholder so
305
+ * scaffolded pages render with zero setup. Images get a self-contained data
306
+ * URI; videos (which have no equivalent inline placeholder — see
307
+ * VIDEO_EXTENSIONS) are stripped to an empty src instead of being
308
+ * mis-replaced with image data. Builders drop in their own media either way.
309
+ *
310
+ * A reference is a URL token that resolves to a root-relative path under
311
+ * FIXTURE_SEGMENT. It is replaced whole, query and fragment included, and
312
+ * classified by the suffix of its last path segment. A reference that cannot
313
+ * be replaced safely throws with its path rather than being guessed at or
314
+ * left behind. Prose is left as written: in text (JSX text, a word inside a
315
+ * longer string) trailing punctuation is not part of a path and a path with
316
+ * no suffix, such as the bare directory, is a mention; inside a comment
317
+ * nothing throws.
216
318
  *
217
319
  * @param {string} source - Template source code.
218
320
  * @returns {string} Source with demo asset references replaced.
219
321
  */
220
322
  export function stripTemplateAssetRefs(source) {
221
- return source.replace(DEMO_ASSET_PATTERN, (match, extension) => {
222
- const ext = extension.toLowerCase();
223
- if (VIDEO_EXTENSIONS.has(ext)) {
224
- return '';
323
+ const needle = `/${FIXTURE_SEGMENT}`;
324
+ let output = '';
325
+ let copied = 0;
326
+ /** @type {Array<[number, number]> | undefined} */
327
+ let comments;
328
+ let at = source.indexOf(needle);
329
+ while (at !== -1) {
330
+ let start = at;
331
+ while (start > 0 && !isTokenDelimiter(source[start - 1])) start--;
332
+ let end = at + needle.length;
333
+ while (end < source.length && !isTokenDelimiter(source[end])) end++;
334
+ /** @type {{text: string, end: number} | null} */
335
+ let edit;
336
+ try {
337
+ edit = fixtureEdit(source, start, at, end);
338
+ } catch (err) {
339
+ comments ??= commentRanges(source);
340
+ if (!comments.some(([from, to]) => from <= at && at < to)) throw err;
341
+ edit = null;
225
342
  }
226
- if (IMAGE_EXTENSIONS.has(ext)) {
227
- return PLACEHOLDER_IMAGE;
343
+ if (edit) {
344
+ output += source.slice(copied, start) + edit.text;
345
+ copied = edit.end;
228
346
  }
229
- throw new Error(`Unrecognized template asset format ${ext} for ${match}`);
230
- });
347
+ at = source.indexOf(needle, end);
348
+ }
349
+ return output + source.slice(copied);
350
+ }
351
+
352
+ /** @param {string | undefined} char */
353
+ function isTokenDelimiter(char) {
354
+ return char === undefined || /\s/u.test(char) || TOKEN_DELIMITERS.has(char);
355
+ }
356
+
357
+ /**
358
+ * Whitespace, the source edge, or a tag bracket: what bounds a word of text.
359
+ * @param {string | undefined} char
360
+ */
361
+ function isTextDelimiter(char) {
362
+ return char === undefined || /\s/u.test(char) || char === '<' || char === '>';
363
+ }
364
+
365
+ /**
366
+ * The path segments of a root-relative URL under FIXTURE_SEGMENT, or null.
367
+ * @param {string} reference
368
+ * @returns {string[] | null}
369
+ */
370
+ function fixtureSegments(reference) {
371
+ if (!reference.startsWith('/') || reference.startsWith('//')) return null;
372
+ const segments = new URL(reference, 'http://template.invalid').pathname.split(
373
+ '/',
374
+ );
375
+ return segments[1] === FIXTURE_SEGMENT ? segments : null;
376
+ }
377
+
378
+ /**
379
+ * The replacement for the fixture reference in the URL token [start, end),
380
+ * which contains FIXTURE_SEGMENT's path at `at`; null when the token is not a
381
+ * fixture reference or is a prose mention.
382
+ * @param {string} source
383
+ * @param {number} start
384
+ * @param {number} at
385
+ * @param {number} end
386
+ * @returns {{text: string, end: number} | null}
387
+ */
388
+ function fixtureEdit(source, start, at, end) {
389
+ const token = source.slice(start, end);
390
+ if (ABSOLUTE_URL.test(token)) return null;
391
+ if (!token.startsWith('/')) {
392
+ if (!fixtureSegments(source.slice(at, end))) return null;
393
+ if (
394
+ source[start - 1] !== '\\' &&
395
+ RELATIVE_PATH_PREFIX.test(source.slice(start, at))
396
+ ) {
397
+ return null;
398
+ }
399
+ throw unsafeFixtureReference(
400
+ source,
401
+ at,
402
+ 'it is joined to text the copy cannot parse',
403
+ );
404
+ }
405
+
406
+ const before = source[start - 1];
407
+ const after = source[end];
408
+ if (after === '{' && token.endsWith('$')) {
409
+ if (!fixtureSegments(token.slice(0, -1))) return null;
410
+ throw unsafeFixtureReference(
411
+ source,
412
+ at,
413
+ 'it is built by a template-literal interpolation',
414
+ );
415
+ }
416
+ const quoted =
417
+ before !== undefined && CLOSING_DELIMITERS.get(before) === after;
418
+ const escapedQuoted =
419
+ (before === "'" || before === '"') &&
420
+ source[start - 2] === '\\' &&
421
+ after === '\\' &&
422
+ source[end + 1] === before;
423
+ const whole = quoted || escapedQuoted;
424
+ let referenceEnd = end;
425
+ if (!whole) {
426
+ while (
427
+ referenceEnd > at &&
428
+ PROSE_PUNCTUATION.has(source[referenceEnd - 1])
429
+ ) {
430
+ referenceEnd--;
431
+ }
432
+ }
433
+ const segments = fixtureSegments(source.slice(start, referenceEnd));
434
+ if (!segments) return null;
435
+
436
+ const inText =
437
+ (isTextDelimiter(before) || CLOSING_DELIMITERS.has(before)) &&
438
+ (isTextDelimiter(after) || CLOSERS.has(after)) &&
439
+ (isTextDelimiter(before) || isTextDelimiter(after));
440
+ if (!whole && !inText) {
441
+ throw unsafeFixtureReference(
442
+ source,
443
+ at,
444
+ 'it is not a whole quoted, url(), or text value',
445
+ );
446
+ }
447
+ if (quoted && before !== '(') {
448
+ const use = expressionUse(source, start - 1, end);
449
+ if (use) throw unsafeFixtureReference(source, at, use);
450
+ }
451
+
452
+ const ext = path.posix
453
+ .extname(segments[segments.length - 1])
454
+ .slice(1)
455
+ .toLowerCase();
456
+ if (VIDEO_EXTENSIONS.has(ext)) return {text: '', end: referenceEnd};
457
+ if (IMAGE_EXTENSIONS.has(ext)) {
458
+ return {text: PLACEHOLDER_IMAGE, end: referenceEnd};
459
+ }
460
+ if (whole || ext) {
461
+ throw new Error(
462
+ `Unrecognized template asset format ${ext || '(none)'} for ${displayReference(source, at)}`,
463
+ );
464
+ }
465
+ return null;
466
+ }
467
+
468
+ /**
469
+ * Why the string quoted at `open` and `close` cannot be replaced on its own,
470
+ * or null when it is a plain value.
471
+ * @param {string} source
472
+ * @param {number} open
473
+ * @param {number} close
474
+ * @returns {string | null}
475
+ */
476
+ function expressionUse(source, open, close) {
477
+ let prev = open - 1;
478
+ while (prev >= 0 && /\s/u.test(source[prev])) prev--;
479
+ let next = close + 1;
480
+ while (next < source.length && /\s/u.test(source[next])) next++;
481
+ if (
482
+ source[prev] === '+' ||
483
+ (source[prev] === '=' && source[prev - 1] === '+') ||
484
+ source[next] === '+'
485
+ ) {
486
+ return 'the string is concatenated with another value';
487
+ }
488
+ if (source[next] === '.' && /[A-Za-z_$]/u.test(source[next + 1] ?? '')) {
489
+ return 'a method is called on the string';
490
+ }
491
+ if (
492
+ MODULE_SPECIFIER_LEAD.test(source.slice(Math.max(0, prev - 16), prev + 1))
493
+ ) {
494
+ return 'it is imported as a module';
495
+ }
496
+ return null;
497
+ }
498
+
499
+ /**
500
+ * The [start, end) range of every comment in `source`, or none when it does
501
+ * not parse as TSX.
502
+ * @param {string} source
503
+ * @returns {Array<[number, number]>}
504
+ */
505
+ function commentRanges(source) {
506
+ try {
507
+ const {parse} = require('@babel/parser');
508
+ const {comments} = parse(source, {
509
+ sourceType: 'module',
510
+ plugins: ['jsx', 'typescript'],
511
+ });
512
+ return (comments ?? []).map(
513
+ comment =>
514
+ /** @type {[number, number]} */ ([
515
+ comment.start ?? 0,
516
+ comment.end ?? 0,
517
+ ]),
518
+ );
519
+ } catch {
520
+ return [];
521
+ }
522
+ }
523
+
524
+ /**
525
+ * The fixture path at `at`, up to the next whitespace, quote, or tag bracket.
526
+ * @param {string} source
527
+ * @param {number} at
528
+ */
529
+ function displayReference(source, at) {
530
+ let end = at;
531
+ while (end < source.length && !/[\s'"`<>]/u.test(source[end])) end++;
532
+ return source.slice(at, end);
533
+ }
534
+
535
+ /**
536
+ * @param {string} source
537
+ * @param {number} at
538
+ * @param {string} reason
539
+ */
540
+ function unsafeFixtureReference(source, at, reason) {
541
+ return new Error(
542
+ `Template asset reference ${displayReference(source, at)} cannot be replaced safely: ${reason}. Use the complete path as one static string.`,
543
+ );
231
544
  }
232
545
  /**
233
546
  * Load a template-spec module and return its metadata object. Supports both
234
547
  * families of suffix:
235
- * - Legacy `.doc.*` core/external specs export `export const doc = {...}`.
236
- * - Canonical `.template.*` specs export the stamped object (`type: 'page' |
237
- * 'block'`) as the default export.
238
- * Prefers the default export, falling back to the named `doc` export, so a
239
- * `Foo.template.ts` (default export) is read identically to a legacy
240
- * `Foo.doc.mjs` (`doc` export). `.ts` is loaded via jiti; `.mjs`/`.js` via a
548
+ * - Canonical `.doc.*` specs may export the stamped object (`type: 'page' |
549
+ * 'block'`) as the default export or use the historical named `doc` export.
550
+ * - Released `.template.*` compatibility specs use the same object shape.
551
+ * Prefers the default export, falling back to the named `doc` export. `.ts` is
552
+ * loaded via jiti; `.mjs`/`.js` via a
241
553
  * native dynamic import. Returns null if the file does not exist.
242
554
  *
243
555
  * @param {string} docPath absolute path to the spec file
@@ -245,10 +557,7 @@ export function stripTemplateAssetRefs(source) {
245
557
  */
246
558
  async function loadDocModule(docPath) {
247
559
  if (!fs.existsSync(docPath)) return null;
248
- const docModule = docPath.endsWith('.ts')
249
- ? await getJiti().import(docPath)
250
- : await import(`file://${docPath}`);
251
- return docModule.default ?? docModule.doc;
560
+ return readDocView(docPath, {root: 'templates', loader: 'template'});
252
561
  }
253
562
 
254
563
  /**
@@ -293,11 +602,11 @@ function findDocFiles(dir, pattern) {
293
602
 
294
603
  /**
295
604
  * Resolve the template-spec file for a core page directory: the first existing
296
- * `template.<suffix>` in canonical-then-legacy precedence, or null.
605
+ * metadata file in {@link ALL_TEMPLATE_SUFFIXES} precedence, or null.
297
606
  * @param {string} dirPath
298
607
  * @returns {string | null}
299
608
  */
300
- function findPageDocFile(dirPath) {
609
+ export function findPageDocFile(dirPath) {
301
610
  for (const suffix of ALL_TEMPLATE_SUFFIXES) {
302
611
  const candidate = path.join(dirPath, `template${suffix}`);
303
612
  if (fs.existsSync(candidate)) return candidate;
@@ -436,44 +745,297 @@ export async function discoverCoreTemplates() {
436
745
  }
437
746
 
438
747
  /**
748
+ * Apply valid integration replacements to a raw template set.
749
+ *
750
+ * One declaration owns its Core target. When different configured packages
751
+ * replace the same target, the later package wins and discovery returns a
752
+ * warning, matching integration-doc replacement order. Multiple declarations
753
+ * inside one package are invalid and fail closed. Missing targets and kind
754
+ * mismatches also fail closed: Core stays selected and every integration
755
+ * template remains addressable by its own id.
756
+ *
757
+ * @param {DiscoveredTemplate[]} templates
758
+ * @param {TemplateDiscoveryError[]} [declarationErrors]
759
+ * @returns {{templates: DiscoveredTemplate[], errors: TemplateReplacementError[]}}
760
+ */
761
+ export function applyTemplateReplacements(templates, declarationErrors = []) {
762
+ /** @type {Map<string, DiscoveredTemplate[]>} */
763
+ const coreById = new Map();
764
+ /** @type {Map<string, DiscoveredTemplate[]>} */
765
+ const replacementsByTarget = new Map();
766
+
767
+ for (const template of templates) {
768
+ if (pkgOf(template) === CORE_PACKAGE) {
769
+ const matches = coreById.get(template.dirName) ?? [];
770
+ matches.push(template);
771
+ coreById.set(template.dirName, matches);
772
+ }
773
+ if (template.replaces != null) {
774
+ const replacements = replacementsByTarget.get(template.replaces) ?? [];
775
+ replacements.push(template);
776
+ replacementsByTarget.set(template.replaces, replacements);
777
+ }
778
+ }
779
+
780
+ const activeReplacements = new Set();
781
+ const replacedCore = new Set();
782
+ /** @type {TemplateReplacementError[]} */
783
+ const errors = declarationErrors.map(error => ({
784
+ ...error,
785
+ code: /** @type {TemplateReplacementError['code']} */ (
786
+ error.code ?? 'invalid_template_replacement'
787
+ ),
788
+ severity: error.severity ?? 'error',
789
+ }));
790
+ /** @param {TemplateReplacementError} error */
791
+ const pushError = error => {
792
+ if (
793
+ errors.some(
794
+ existing =>
795
+ existing.code === error.code &&
796
+ existing.package === error.package &&
797
+ existing.template === error.template &&
798
+ existing.message === error.message,
799
+ )
800
+ ) {
801
+ return;
802
+ }
803
+ errors.push(error);
804
+ };
805
+ for (const [target, replacements] of replacementsByTarget) {
806
+ const targetErrors = errors.filter(
807
+ error => error.replacementTarget === target,
808
+ );
809
+ const hasExplicitIntent =
810
+ replacements.some(replacement => !replacement.autolinked) ||
811
+ targetErrors.some(error => !error.autolinked);
812
+ const contenders = hasExplicitIntent
813
+ ? replacements.filter(replacement => !replacement.autolinked)
814
+ : replacements;
815
+ let targetInvalid = targetErrors.some(
816
+ error =>
817
+ error.severity === 'error' && (!hasExplicitIntent || !error.autolinked),
818
+ );
819
+
820
+ /** @type {Map<string, DiscoveredTemplate[]>} */
821
+ const byPackage = new Map();
822
+ for (const replacement of replacements) {
823
+ const pkg = pkgOf(replacement);
824
+ const fromPackage = byPackage.get(pkg) ?? [];
825
+ fromPackage.push(replacement);
826
+ byPackage.set(pkg, fromPackage);
827
+ }
828
+ for (const [pkg, declarations] of byPackage) {
829
+ if (declarations.length < 2) continue;
830
+ if (!hasExplicitIntent || !declarations[0].autolinked) {
831
+ targetInvalid = true;
832
+ }
833
+ const message =
834
+ `${pkg} declares ${declarations.length} templates as replacements for Core ` +
835
+ `template "${target}" (${declarations.map(template => template.dirName).join(', ')}). ` +
836
+ 'One package must declare at most one replacement for a Core target.';
837
+ for (const declaration of declarations) {
838
+ pushError({
839
+ code: 'ambiguous_template_replacement',
840
+ severity: 'error',
841
+ package: pkg,
842
+ template: declaration.dirName,
843
+ replacementTarget: target,
844
+ autolinked: declaration.autolinked,
845
+ message,
846
+ });
847
+ }
848
+ }
849
+
850
+ const coreMatches = coreById.get(target) ?? [];
851
+ /** @type {Map<DiscoveredTemplate, DiscoveredTemplate>} */
852
+ const coreMatchByReplacement = new Map();
853
+ for (const replacement of replacements) {
854
+ const invalidAffectsTarget =
855
+ !hasExplicitIntent || !replacement.autolinked;
856
+ if (coreMatches.length === 0) {
857
+ if (invalidAffectsTarget) targetInvalid = true;
858
+ pushError({
859
+ code: 'missing_template_replacement_target',
860
+ severity: 'error',
861
+ package: pkgOf(replacement),
862
+ template: replacement.dirName,
863
+ replacementTarget: target,
864
+ autolinked: replacement.autolinked,
865
+ message: `Template "${replacement.dirName}" replaces "${target}", which is not a Core template id.`,
866
+ });
867
+ continue;
868
+ }
869
+ const sameType = coreMatches.filter(
870
+ core => core.type === replacement.type,
871
+ );
872
+ if (sameType.length !== 1) {
873
+ if (invalidAffectsTarget) targetInvalid = true;
874
+ const kinds = coreMatches.map(core => core.type).join(', ');
875
+ pushError({
876
+ code: 'invalid_template_replacement',
877
+ severity: 'error',
878
+ package: pkgOf(replacement),
879
+ template: replacement.dirName,
880
+ replacementTarget: target,
881
+ autolinked: replacement.autolinked,
882
+ message:
883
+ `Template "${replacement.dirName}" is a ${replacement.type} template, but Core ` +
884
+ `template "${target}" is ${kinds || 'not available'}. A replacement must have the same type.`,
885
+ });
886
+ continue;
887
+ }
888
+ coreMatchByReplacement.set(replacement, sameType[0]);
889
+ }
890
+
891
+ const validContenders = contenders.filter(replacement =>
892
+ coreMatchByReplacement.has(replacement),
893
+ );
894
+ if (targetInvalid || validContenders.length === 0) continue;
895
+
896
+ const replacement = validContenders[validContenders.length - 1];
897
+ const validReplacements = replacements.filter(candidate =>
898
+ coreMatchByReplacement.has(candidate),
899
+ );
900
+ if (validReplacements.length > 1) {
901
+ const autolinkedLost =
902
+ hasExplicitIntent &&
903
+ validReplacements.some(candidate => candidate.autolinked);
904
+ const allAutolinked = validReplacements.every(
905
+ candidate => candidate.autolinked,
906
+ );
907
+ pushError({
908
+ code: 'ambiguous_template_replacement',
909
+ severity: 'warning',
910
+ package: pkgOf(replacement),
911
+ template: replacement.dirName,
912
+ replacementTarget: target,
913
+ autolinked: replacement.autolinked,
914
+ message: autolinkedLost
915
+ ? `Core template "${target}" is replaced by ${validReplacements.map(candidate => pkgOf(candidate)).join(', ')}. ${pkgOf(replacement)} is explicitly configured, so it wins over autolinked integrations.`
916
+ : allAutolinked
917
+ ? `Core template "${target}" is replaced by autolinked dependencies ${validReplacements.map(candidate => pkgOf(candidate)).join(', ')}. ${pkgOf(replacement)} is listed later in package.json dependencies, so it wins. Add the intended package to astryx.config integrations to make precedence explicit.`
918
+ : `Core template "${target}" is replaced by ${validReplacements.map(candidate => pkgOf(candidate)).join(', ')}. ${pkgOf(replacement)} is configured later, so it wins.`,
919
+ });
920
+ }
921
+
922
+ activeReplacements.add(replacement);
923
+ const coreMatch = coreMatchByReplacement.get(replacement);
924
+ if (coreMatch) replacedCore.add(coreMatch);
925
+ }
926
+
927
+ const effective = templates.flatMap(template => {
928
+ if (replacedCore.has(template)) return [];
929
+ if (template.replaces != null && !activeReplacements.has(template)) {
930
+ const fallback = {
931
+ ...template,
932
+ replacementRejected: true,
933
+ replacementTarget: template.replaces,
934
+ };
935
+ delete fallback.replaces;
936
+ return [fallback];
937
+ }
938
+ return [template];
939
+ });
940
+
941
+ return {
942
+ templates: effective.sort((a, b) => a.name.localeCompare(b.name)),
943
+ errors,
944
+ };
945
+ }
946
+
947
+ /**
948
+ * Discover the raw Core, external, and integration template set before
949
+ * replacement declarations are applied.
439
950
  * @param {string} [cwd]
440
- * @returns {Promise<DiscoveredTemplate[]>}
951
+ * @returns {Promise<{templates: DiscoveredTemplate[], errors: TemplateDiscoveryError[]}>}
441
952
  */
442
- export async function discoverAll(cwd = process.cwd()) {
953
+ async function discoverAllSources(cwd = process.cwd()) {
443
954
  const [core, external, integration] = await Promise.all([
444
955
  discoverCoreTemplates(),
445
956
  discoverExternalBlocks(cwd),
446
957
  discoverIntegrationTemplates(cwd),
447
958
  ]);
448
- return [...core, ...external, ...integration.templates].sort((a, b) =>
959
+ return {
960
+ templates: [...core, ...external, ...integration.templates],
961
+ errors: integration.errors,
962
+ };
963
+ }
964
+
965
+ /**
966
+ * Discover every template without hiding replaced Core originals. Internal
967
+ * package-qualified selection uses this view.
968
+ * @param {string} [cwd]
969
+ * @returns {Promise<DiscoveredTemplate[]>}
970
+ */
971
+ export async function discoverAllUnresolved(cwd = process.cwd()) {
972
+ return (await discoverAllSources(cwd)).templates.sort((a, b) =>
449
973
  a.name.localeCompare(b.name),
450
974
  );
451
975
  }
452
976
 
453
977
  /**
454
- * Like {@link discoverAll} but also returns integration-template discovery
455
- * errors (missing same-stem source, missing `type`, load failure). Use this
456
- * when the caller wants to warn about malformed integration templates.
978
+ * Resolve replacement declarations while retaining package-addressable entries
979
+ * that are shadowed or rejected in the default discovery view.
980
+ * @param {string} [cwd]
981
+ * @returns {Promise<{templates: DiscoveredTemplate[], errors: Array<TemplateDiscoveryError | TemplateReplacementError>}>}
982
+ */
983
+ async function resolveAllSources(cwd = process.cwd()) {
984
+ const discovered = await discoverAllSources(cwd);
985
+ const replacementErrors = discovered.errors.filter(
986
+ error => error.replacementTarget != null,
987
+ );
988
+ const resolved = applyTemplateReplacements(
989
+ discovered.templates,
990
+ replacementErrors,
991
+ );
992
+ return {
993
+ templates: resolved.templates,
994
+ errors: [
995
+ ...discovered.errors.filter(error => error.replacementTarget == null),
996
+ ...resolved.errors,
997
+ ],
998
+ };
999
+ }
1000
+
1001
+ /**
1002
+ * Discover the resolved catalog before default-view shadowing. Internal
1003
+ * package-qualified selection uses this view.
1004
+ * @param {string} [cwd]
1005
+ * @returns {Promise<DiscoveredTemplate[]>}
1006
+ */
1007
+ export async function discoverAllResolved(cwd = process.cwd()) {
1008
+ return (await resolveAllSources(cwd)).templates;
1009
+ }
1010
+
1011
+ /**
1012
+ * @param {string} [cwd]
1013
+ * @returns {Promise<DiscoveredTemplate[]>}
1014
+ */
1015
+ export async function discoverAll(cwd = process.cwd()) {
1016
+ return effectiveTemplateDiscovery(await discoverAllResolved(cwd));
1017
+ }
1018
+
1019
+ /**
1020
+ * Like {@link discoverAll} but also returns integration-template discovery and
1021
+ * replacement-declaration errors. Use this when the caller wants to warn about
1022
+ * malformed integration templates or inactive replacement declarations.
457
1023
  *
458
1024
  * @param {string} [cwd]
459
- * @returns {Promise<{templates: DiscoveredTemplate[], errors: TemplateDiscoveryError[]}>}
1025
+ * @returns {Promise<{templates: DiscoveredTemplate[], errors: Array<TemplateDiscoveryError | TemplateReplacementError>}>}
460
1026
  */
461
1027
  export async function discoverAllWithErrors(cwd = process.cwd()) {
462
- const [pages, blocks, integration] = await Promise.all([
463
- discoverPages(),
464
- discoverAllBlocks(cwd),
465
- discoverIntegrationTemplates(cwd),
466
- ]);
467
- const templates = [...pages, ...blocks, ...integration.templates].sort(
468
- (a, b) => a.name.localeCompare(b.name),
469
- );
470
- return {templates, errors: integration.errors};
1028
+ const resolved = await resolveAllSources(cwd);
1029
+ return {
1030
+ templates: effectiveTemplateDiscovery(resolved.templates),
1031
+ errors: resolved.errors,
1032
+ };
471
1033
  }
472
1034
 
473
1035
  /**
474
1036
  * Recursively collect integration template-spec files under `root`.
475
1037
  * Returns absolute paths to files ending in one of ALL_TEMPLATE_SUFFIXES
476
- * (canonical `.template.*` or legacy `.doc.*`).
1038
+ * (canonical `.doc.*` or released `.template.*` compatibility files).
477
1039
  *
478
1040
  * @param {string} root
479
1041
  * @returns {string[]}
@@ -503,7 +1065,7 @@ function findIntegrationDocFiles(root) {
503
1065
  * Discover templates contributed by configured integrations.
504
1066
  *
505
1067
  * For each integration with a resolved `templates` root, every
506
- * `<id>.template.{ts,mjs,js}` (or legacy `<id>.doc.{ts,mjs,js}`) file is a
1068
+ * canonical `<id>.doc.{mjs,ts,js}` (or released `<id>.template.{ts,mjs,js}`) file is a
507
1069
  * template whose id is its path relative to the templates root with the
508
1070
  * matched suffix stripped (kebab-case, may be nested). The doc's `type`
509
1071
  * (page|block) decides scaffolding — there is no `/pages` vs `/blocks`
@@ -544,21 +1106,67 @@ async function discoverIntegrationTemplates(cwd = process.cwd()) {
544
1106
  }
545
1107
 
546
1108
  for (const integration of loadedIntegrations) {
547
- const result = await discoverIntegrationTemplatesForOne(integration);
548
- templates.push(...result.templates);
549
- errors.push(...result.errors);
1109
+ // One integration's unreadable root must not cost core or the others theirs.
1110
+ try {
1111
+ const result = await discoverIntegrationTemplatesForOne(integration);
1112
+ templates.push(...result.templates);
1113
+ errors.push(...result.errors);
1114
+ } catch (err) {
1115
+ errors.push({
1116
+ package: integration?.name ?? integration?.__spec ?? 'integration',
1117
+ message: err instanceof Error ? err.message : String(err),
1118
+ });
1119
+ }
550
1120
  }
551
1121
 
552
1122
  return {templates, errors};
553
1123
  }
554
1124
 
1125
+ /**
1126
+ * Report replacement declarations that cannot hold inside one package: two of
1127
+ * its templates replacing the same Core target. Cross-package precedence and
1128
+ * target checks happen in {@link applyTemplateReplacements}.
1129
+ * @param {string} pkg
1130
+ * @param {boolean | undefined} autolinked
1131
+ * @param {DiscoveredTemplate[]} templates
1132
+ * @param {TemplateDiscoveryError[]} errors
1133
+ */
1134
+ function reportSamePackageReplacements(pkg, autolinked, templates, errors) {
1135
+ /** @type {Map<string, string[]>} */
1136
+ const idsByTarget = new Map();
1137
+ for (const template of templates) {
1138
+ if (template.replaces == null) continue;
1139
+ const ids = idsByTarget.get(template.replaces) ?? [];
1140
+ ids.push(template.dirName);
1141
+ idsByTarget.set(template.replaces, ids);
1142
+ }
1143
+ for (const [target, ids] of idsByTarget) {
1144
+ if (ids.length < 2) continue;
1145
+ const message =
1146
+ `${pkg} declares ${ids.length} templates as replacements for Core template ` +
1147
+ `"${target}" (${ids.join(', ')}). One package must declare at most one ` +
1148
+ 'replacement for a Core target.';
1149
+ for (const template of ids) {
1150
+ errors.push({
1151
+ code: 'ambiguous_template_replacement',
1152
+ severity: 'error',
1153
+ package: pkg,
1154
+ autolinked,
1155
+ template,
1156
+ replacementTarget: target,
1157
+ message,
1158
+ });
1159
+ }
1160
+ }
1161
+ }
1162
+
555
1163
  /**
556
1164
  * Discover the templates contributed by a SINGLE integration. Same per-template
557
1165
  * rules as {@link discoverIntegrationTemplates} (same-stem source required,
558
1166
  * page|block type required); broken templates are recorded in `errors` rather
559
1167
  * than thrown. Exposed for `doctor integration validate` and template authoring checks.
560
1168
  *
561
- * @param {{name?: string, __spec?: string, templates?: string}} integration
1169
+ * @param {{name?: string, __spec?: string, __autolinked?: boolean, templates?: string}} integration
562
1170
  * @returns {Promise<{templates: DiscoveredTemplate[], errors: TemplateDiscoveryError[]}>}
563
1171
  */
564
1172
  export async function discoverIntegrationTemplatesForOne(integration) {
@@ -587,6 +1195,20 @@ export async function discoverIntegrationTemplatesForOne(integration) {
587
1195
  template: id,
588
1196
  message: `Template "${id}" is missing its same-stem source file ${path.basename(sourcePath)}.`,
589
1197
  });
1198
+ // A replacement this unusable template declares still counts, so its
1199
+ // target fails closed instead of going to a sibling.
1200
+ const declared = await declaredReplacement(docPath, id);
1201
+ if (declared != null) {
1202
+ errors.push({
1203
+ code: 'invalid_template_replacement',
1204
+ severity: 'error',
1205
+ package: pkgLabel,
1206
+ autolinked: integration.__autolinked,
1207
+ template: id,
1208
+ replacementTarget: declared,
1209
+ message: `Template "${id}" replaces "${declared}", but it cannot be used: it is missing its same-stem source file ${path.basename(sourcePath)}.`,
1210
+ });
1211
+ }
590
1212
  continue;
591
1213
  }
592
1214
 
@@ -599,6 +1221,20 @@ export async function discoverIntegrationTemplatesForOne(integration) {
599
1221
  template: id,
600
1222
  message: `Template "${id}" failed to load: ${/** @type {any} */ (err).message}`,
601
1223
  });
1224
+ // A replacement this unusable template declares still counts, so its
1225
+ // target fails closed instead of going to a sibling (spec:AST-035 FR4).
1226
+ const declared = await declaredReplacement(docPath, id);
1227
+ if (declared != null) {
1228
+ errors.push({
1229
+ code: 'invalid_template_replacement',
1230
+ severity: 'error',
1231
+ package: pkgLabel,
1232
+ autolinked: integration.__autolinked,
1233
+ template: id,
1234
+ replacementTarget: declared,
1235
+ message: `Template "${id}" replaces "${declared}", but it cannot be used: its metadata does not load.`,
1236
+ });
1237
+ }
602
1238
  continue;
603
1239
  }
604
1240
 
@@ -612,6 +1248,18 @@ export async function discoverIntegrationTemplatesForOne(integration) {
612
1248
  template: id,
613
1249
  message: `Template "${id}" is missing a "type" of "page" or "block". Stamp the default export with type: 'page' or type: 'block'.`,
614
1250
  });
1251
+ const declared = doc?.replaces ?? (await declaredReplacement(docPath, id));
1252
+ if (declared != null) {
1253
+ errors.push({
1254
+ code: 'invalid_template_replacement',
1255
+ severity: 'error',
1256
+ package: pkgLabel,
1257
+ autolinked: integration.__autolinked,
1258
+ template: id,
1259
+ replacementTarget: declared,
1260
+ message: `Template "${id}" replaces "${declared}", but it cannot be used: it has no "type".`,
1261
+ });
1262
+ }
615
1263
  continue;
616
1264
  }
617
1265
 
@@ -639,12 +1287,55 @@ export async function discoverIntegrationTemplatesForOne(integration) {
639
1287
  filePath: sourcePath,
640
1288
  docPath,
641
1289
  package: pkgLabel,
1290
+ autolinked: integration.__autolinked,
1291
+ replaces: doc?.replaces,
642
1292
  });
643
1293
  }
644
1294
 
1295
+ reportSamePackageReplacements(
1296
+ pkgLabel,
1297
+ integration.__autolinked,
1298
+ templates,
1299
+ errors,
1300
+ );
645
1301
  return {templates, errors};
646
1302
  }
647
1303
 
1304
+ /**
1305
+ * The replacement a template doc declares, even when the doc does not validate
1306
+ * or load: an unusable template's declaration still counts, so its target
1307
+ * fails closed (spec:AST-035 FR4). Null when it declares none.
1308
+ * @param {string} docPath
1309
+ * @param {string} id
1310
+ * @returns {Promise<string | null>}
1311
+ */
1312
+ async function declaredReplacement(docPath, id) {
1313
+ try {
1314
+ const doc = await loadIntegrationDoc(docPath, `Template "${id}"`);
1315
+ return doc?.replaces ?? null;
1316
+ } catch {
1317
+ // The doc does not validate; read what it declares without validating.
1318
+ }
1319
+ try {
1320
+ // The guarded importer: anything the doc writes to stdout as it loads
1321
+ // goes to stderr, so `--json` output stays clean.
1322
+ const raw = (await importDocModule(docPath))?.default;
1323
+ if (raw != null && typeof raw === 'object') {
1324
+ return typeof raw.replaces === 'string' ? raw.replaces : null;
1325
+ }
1326
+ } catch {
1327
+ // The module does not load at all; its text may still name a target.
1328
+ }
1329
+ try {
1330
+ const match = /\breplaces\s*:\s*['"]([^'"\n]+)['"]/u.exec(
1331
+ fs.readFileSync(docPath, 'utf8'),
1332
+ );
1333
+ return match ? match[1] : null;
1334
+ } catch {
1335
+ return null;
1336
+ }
1337
+ }
1338
+
648
1339
  /**
649
1340
  * @param {string} componentName
650
1341
  * @param {string} [cwd]