@astryxdesign/cli 0.6.3-canary.ebaebc4 → 0.6.3-canary.ee13359

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 (501) hide show
  1. package/README.md +114 -77
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +4 -3
  4. package/api/build/build.test.mjs +14 -3
  5. package/api/build/build.type.d.mts +35 -1
  6. package/api/build/build.type.mjs +24 -3
  7. package/api/build/help/help.d.mts +8 -5
  8. package/api/build/help/help.mjs +56 -6
  9. package/api/component/_adapter.d.mts +6 -12
  10. package/api/component/_adapter.mjs +20 -10
  11. package/api/component/component.doc.mjs +13 -3
  12. package/api/component/component.mjs +91 -14
  13. package/api/component/component.test.mjs +38 -0
  14. package/api/component/component.type.d.mts +16 -5
  15. package/api/component/component.type.mjs +13 -5
  16. package/api/component/detail/blocks/blocks.d.mts +2 -1
  17. package/api/component/detail/blocks/blocks.mjs +4 -3
  18. package/api/component/list/list.d.mts +0 -5
  19. package/api/component/list/list.mjs +40 -11
  20. package/api/discover/discover.doc.mjs +2 -1
  21. package/api/docs/_adapter.d.mts +210 -34
  22. package/api/docs/_adapter.mjs +674 -134
  23. package/api/docs/detail/detail.mjs +11 -3
  24. package/api/docs/detail/section/section.mjs +24 -13
  25. package/api/docs/detail/section/section.test.mjs +15 -6
  26. package/api/docs/docs.d.mts +5 -3
  27. package/api/docs/docs.doc.mjs +36 -15
  28. package/api/docs/docs.mjs +44 -8
  29. package/api/docs/docs.test.mjs +158 -4
  30. package/api/docs/docs.type.d.mts +165 -2
  31. package/api/docs/docs.type.mjs +101 -3
  32. package/api/docs/index/index.mjs +11 -3
  33. package/api/docs/index/index.test.mjs +1 -1
  34. package/api/docs/integration-tree.test.mjs +547 -0
  35. package/api/docs/integrationDocs.test.mjs +14 -14
  36. package/api/docs/list/list.mjs +28 -12
  37. package/api/docs/node/node.d.mts +43 -0
  38. package/api/docs/node/node.mjs +192 -0
  39. package/api/doctor/doctor.d.mts +54 -4
  40. package/api/doctor/doctor.doc.mjs +1 -0
  41. package/api/doctor/doctor.mjs +327 -16
  42. package/api/doctor/doctor.test.mjs +420 -7
  43. package/api/gap-report/gap-report.doc.mjs +8 -4
  44. package/api/hook/_adapter.mjs +19 -5
  45. package/api/hook/hook.doc.mjs +1 -0
  46. package/api/hook/list/list.d.mts +1 -1
  47. package/api/hook/list/list.mjs +69 -17
  48. package/api/index.d.mts +1 -1
  49. package/api/index.mjs +1 -0
  50. package/api/init/init.doc.mjs +6 -1
  51. package/api/init/init.test.mjs +41 -1
  52. package/api/init/remove/remove.mjs +1 -1
  53. package/api/init/run/run.mjs +20 -10
  54. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  55. package/api/integration/add-contribution.d.mts +2 -1
  56. package/api/integration/add-contribution.mjs +125 -12
  57. package/api/integration/add-contribution.test.mjs +254 -3
  58. package/api/integration/add-theme.mjs +34 -64
  59. package/api/integration/add-theme.test.mjs +105 -21
  60. package/api/integration/authoring-checks.mjs +108 -31
  61. package/api/integration/authoring-checks.test.mjs +171 -6
  62. package/api/integration/authoring-checks.type.d.mts +3 -1
  63. package/api/integration/authoring-checks.type.mjs +3 -1
  64. package/api/integration/integration-authoring.type.d.mts +2 -0
  65. package/api/integration/integration-authoring.type.mjs +2 -0
  66. package/api/integration/integration-block-exports.test.mjs +10 -6
  67. package/api/integration/integrationAdd.doc.mjs +14 -4
  68. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  69. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  70. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  71. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  72. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  73. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  74. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  75. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  76. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  77. package/api/integration/integrationTemplateConflicts.doc.mjs +7 -5
  78. package/api/integration/pack-check.mjs +34 -0
  79. package/api/integration/pack-check.test.mjs +138 -47
  80. package/api/integration/pack-check.type.d.mts +26 -2
  81. package/api/integration/pack-check.type.mjs +14 -1
  82. package/api/integration/summarizeIssues.doc.mjs +1 -0
  83. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  84. package/api/integration/validate-integration.mjs +52 -102
  85. package/api/integration/validate-integration.test.mjs +179 -26
  86. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  87. package/api/integration/validateIntegration.doc.mjs +3 -2
  88. package/api/json/assertResponse.doc.mjs +1 -0
  89. package/api/json/envelope-types.test.mjs +76 -0
  90. package/api/json/index.ts +2 -0
  91. package/api/json/isError.doc.mjs +1 -0
  92. package/api/json/parseResponse.doc.mjs +3 -2
  93. package/api/layout/_adapter.mjs +20 -5
  94. package/api/layout/expand/expand.mjs +7 -5
  95. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  96. package/api/layout/grammar/grammar.mjs +2 -1
  97. package/api/layout/layoutCheck.doc.mjs +1 -0
  98. package/api/layout/layoutExpand.doc.mjs +2 -1
  99. package/api/layout/layoutGrammar.doc.mjs +1 -0
  100. package/api/search/search-return-type.test.mjs +54 -0
  101. package/api/search/search.d.mts +28 -10
  102. package/api/search/search.doc.mjs +8 -2
  103. package/api/search/search.mjs +334 -38
  104. package/api/search/search.test.mjs +124 -1
  105. package/api/search/search.type.d.mts +13 -1
  106. package/api/search/search.type.mjs +4 -1
  107. package/api/swizzle/copy/copy.mjs +28 -11
  108. package/api/swizzle/swizzle.doc.mjs +2 -1
  109. package/api/template/copy/copy.mjs +17 -23
  110. package/api/template/copy/copy.test.mjs +17 -0
  111. package/api/template/list/list.mjs +1 -0
  112. package/api/template/template-integration.test.mjs +1022 -3
  113. package/api/template/template-suffix.test.mjs +41 -21
  114. package/api/template/template.doc.mjs +30 -8
  115. package/api/template/template.mjs +45 -8
  116. package/api/template/template.type.d.mts +6 -8
  117. package/api/template/template.type.mjs +3 -2
  118. package/api/theme/_adapter.d.mts +2 -3
  119. package/api/theme/_adapter.mjs +4 -5
  120. package/api/theme/add/add.binary.test.mjs +84 -0
  121. package/api/theme/add/add.mjs +20 -3
  122. package/api/theme/add/add.staging.test.mjs +66 -0
  123. package/api/theme/add/add.test.mjs +14 -1
  124. package/api/theme/build/build.mjs +114 -37
  125. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  126. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  127. package/api/theme/build/font-warning.mjs +3 -3
  128. package/api/theme/build/font-warning.test.mjs +5 -2
  129. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  130. package/api/theme/integration-themes.test.mjs +39 -28
  131. package/api/theme/list/list.test.mjs +19 -20
  132. package/api/theme/listThemes.doc.mjs +6 -5
  133. package/api/theme/palette/generate/generate.mjs +7 -2
  134. package/api/theme/palette/generate/generate.test.mjs +96 -0
  135. package/api/theme/palette/generate/generator.mjs +8 -1
  136. package/api/theme/palette/generate/generator.test.mjs +10 -0
  137. package/api/theme/template/template.mjs +11 -2
  138. package/api/theme/template/template.test.mjs +20 -0
  139. package/api/theme/themeAdd.doc.mjs +4 -3
  140. package/api/theme/themeBuild.doc.mjs +8 -4
  141. package/api/theme/themeList.doc.mjs +6 -3
  142. package/api/theme/themeListAvailable.doc.mjs +5 -3
  143. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  144. package/api/theme/themeTargets.doc.mjs +1 -0
  145. package/api/theme/themeTemplate.doc.mjs +6 -2
  146. package/api/upgrade/_adapter.d.mts +32 -5
  147. package/api/upgrade/_adapter.mjs +124 -73
  148. package/api/upgrade/list/list.mjs +2 -1
  149. package/api/upgrade/list/list.test.mjs +73 -0
  150. package/api/upgrade/provider-agreement.test.mjs +152 -0
  151. package/api/upgrade/run/run.mjs +356 -59
  152. package/api/upgrade/status/status.mjs +2 -2
  153. package/api/upgrade/upgrade.doc.mjs +8 -2
  154. package/api/upgrade/upgrade.type.d.mts +38 -0
  155. package/api/upgrade/upgrade.type.mjs +16 -0
  156. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  157. package/assets/codemods/integration-discovery.mjs +8 -2
  158. package/assets/codemods/integration-discovery.test.mjs +15 -0
  159. package/assets/codemods/integration-runner.mjs +56 -4
  160. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  161. package/assets/codemods/run-codemod.mjs +177 -34
  162. package/assets/codemods/runner.mjs +350 -102
  163. package/assets/codemods/term-log.mjs +32 -8
  164. package/assets/codemods/term-log.test.mjs +19 -1
  165. package/assets/codemods/transform-prop.mjs +109 -0
  166. package/assets/codemods/transform-prop.test.mjs +95 -0
  167. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  168. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  169. package/assets/codemods/transforms/next/index.mjs +19 -1
  170. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  171. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  172. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  173. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  174. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  175. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  176. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  177. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  178. package/assets/docs/getting-started.doc.mjs +2 -2
  179. package/assets/docs/principles.doc.mjs +6 -6
  180. package/assets/docs/styling-libraries.doc.mjs +2 -2
  181. package/assets/docs/styling.doc.mjs +4 -4
  182. package/assets/docs/theme.doc.mjs +4 -4
  183. package/assets/docs/tokens.doc.mjs +1 -1
  184. package/assets/docs/tree/api.doc.mjs +30 -0
  185. package/assets/docs/tree/cli.doc.mjs +23 -0
  186. package/assets/docs/tree/commands.doc.mjs +25 -0
  187. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +66 -38
  188. package/assets/docs/tree/integrations.test.mjs +62 -0
  189. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  190. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  191. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  192. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  193. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  194. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  195. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  196. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  197. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  198. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  199. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  200. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  201. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  202. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  203. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  204. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  205. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  206. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  207. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  208. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  209. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  210. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  211. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  212. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  213. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  214. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  215. package/authoring/codemod/codemod.doc.mjs +1 -1
  216. package/authoring/codemod/type.ts +12 -0
  217. package/authoring/config/config.doc.mjs +2 -2
  218. package/authoring/config/debug-composition.test.mjs +92 -0
  219. package/authoring/config/type.ts +15 -3
  220. package/authoring/debug/debug.doc.d.mts +11 -0
  221. package/authoring/debug/debug.doc.mjs +182 -0
  222. package/authoring/debug/parse.d.mts +3 -3
  223. package/authoring/doctypes/_schema.d.mts +71 -141
  224. package/authoring/doctypes/_schema.mjs +29 -2
  225. package/authoring/doctypes/base/graph-fields.doc.mjs +8 -6
  226. package/authoring/doctypes/base/type.ts +6 -5
  227. package/authoring/doctypes/command/command.doc.mjs +1 -1
  228. package/authoring/doctypes/command/type.ts +2 -2
  229. package/authoring/doctypes/component/type.ts +2 -2
  230. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  231. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  232. package/authoring/doctypes/enum/type.ts +1 -1
  233. package/authoring/doctypes/function/function.doc.mjs +3 -2
  234. package/authoring/doctypes/function/type.ts +3 -2
  235. package/authoring/doctypes/hook/type.ts +2 -2
  236. package/authoring/doctypes/load-contract.test.mjs +3 -2
  237. package/authoring/doctypes/namespace/namespace.doc.mjs +6 -10
  238. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  239. package/authoring/doctypes/namespace/type.ts +5 -2
  240. package/authoring/doctypes/parse.d.mts +4 -2
  241. package/authoring/doctypes/parse.mjs +10 -5
  242. package/authoring/doctypes/reference/reference.doc.mjs +7 -5
  243. package/authoring/doctypes/reference/type.ts +12 -10
  244. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  245. package/authoring/doctypes/schema/type.ts +1 -2
  246. package/authoring/doctypes/template/parse.d.mts +2 -0
  247. package/authoring/doctypes/template/parse.mjs +4 -0
  248. package/authoring/doctypes/template/parse.test.mjs +18 -0
  249. package/authoring/doctypes/template/template.doc.mjs +9 -3
  250. package/authoring/doctypes/template/type.ts +8 -0
  251. package/authoring/doctypes/theme/parse.d.mts +35 -0
  252. package/authoring/doctypes/theme/parse.mjs +76 -0
  253. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  254. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  255. package/authoring/doctypes/theme/type.ts +42 -0
  256. package/authoring/doctypes/types.ts +2 -1
  257. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  258. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  259. package/authoring/identity/identity.doc.mjs +2 -2
  260. package/authoring/index.d.mts +1 -0
  261. package/authoring/index.d.ts +7 -4
  262. package/authoring/index.mjs +2 -1
  263. package/authoring/integration/integration.doc.mjs +2 -2
  264. package/authoring/integration/type.ts +4 -10
  265. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  266. package/clients/cli/command-load-failure.test.mjs +83 -0
  267. package/clients/cli/commands/blog.doc.mjs +1 -1
  268. package/clients/cli/commands/blog.mjs +23 -8
  269. package/clients/cli/commands/blog.test.mjs +42 -1
  270. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  271. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  272. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  273. package/clients/cli/commands/build-theme.mjs +16 -50
  274. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  275. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  276. package/clients/cli/commands/build.doc.mjs +5 -2
  277. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  278. package/clients/cli/commands/build.mjs +37 -49
  279. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  280. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  281. package/clients/cli/commands/component/index.mjs +3 -8
  282. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  283. package/clients/cli/commands/component-package.test.mjs +46 -0
  284. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  285. package/clients/cli/commands/component.doc.mjs +1 -1
  286. package/clients/cli/commands/component.test.mjs +19 -0
  287. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  288. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  289. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  290. package/clients/cli/commands/discover.doc.mjs +5 -3
  291. package/clients/cli/commands/discover.mjs +4 -4
  292. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  293. package/clients/cli/commands/docs.doc.mjs +21 -9
  294. package/clients/cli/commands/docs.mjs +182 -68
  295. package/clients/cli/commands/docs.test.mjs +120 -16
  296. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  297. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  298. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  299. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  300. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  301. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  302. package/clients/cli/commands/doctor-integration.test.mjs +83 -8
  303. package/clients/cli/commands/doctor.doc.mjs +1 -1
  304. package/clients/cli/commands/doctor.mjs +30 -25
  305. package/clients/cli/commands/doctor.test.mjs +42 -0
  306. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  307. package/clients/cli/commands/gap-report.test.mjs +72 -0
  308. package/clients/cli/commands/hook/index.mjs +7 -17
  309. package/clients/cli/commands/hook.doc.mjs +1 -1
  310. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  311. package/clients/cli/commands/init.doc.mjs +20 -9
  312. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  313. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  314. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  315. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  316. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  317. package/clients/cli/commands/integration.doc.mjs +1 -1
  318. package/clients/cli/commands/integration.mjs +1 -0
  319. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  320. package/clients/cli/commands/json-contract.test.mjs +33 -0
  321. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  322. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  323. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  324. package/clients/cli/commands/layout.doc.mjs +3 -3
  325. package/clients/cli/commands/layout.mjs +21 -9
  326. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  327. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  328. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  329. package/clients/cli/commands/manifest.doc.mjs +1 -1
  330. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  331. package/clients/cli/commands/search.doc.mjs +7 -4
  332. package/clients/cli/commands/search.mjs +28 -9
  333. package/clients/cli/commands/search.test.mjs +75 -0
  334. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  335. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  336. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  337. package/clients/cli/commands/template.doc.mjs +52 -13
  338. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  339. package/clients/cli/commands/template.mjs +4 -91
  340. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  341. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  342. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  343. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  344. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  345. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  346. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  347. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  348. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  349. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  350. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  351. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  352. package/clients/cli/commands/theme.doc.mjs +1 -1
  353. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  354. package/clients/cli/commands/upgrade.doc.mjs +20 -8
  355. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  356. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  357. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  358. package/clients/cli/commands/upgrade.mjs +29 -7
  359. package/clients/cli/formatters/index.mjs +2 -0
  360. package/clients/cli/formatters/index.test.mjs +6 -0
  361. package/clients/cli/index.mjs +21 -30
  362. package/clients/cli/latest-version-env.test.mjs +50 -0
  363. package/clients/cli/lib/cli-error.test.mjs +7 -0
  364. package/clients/cli/lib/component-format.mjs +9 -9
  365. package/clients/cli/lib/component-format.test.mjs +1 -1
  366. package/clients/cli/lib/define-command.mjs +32 -6
  367. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  368. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  369. package/clients/cli/lib/hook-format.mjs +19 -10
  370. package/clients/cli/lib/json-shim.mjs +38 -2
  371. package/clients/cli/lib/json-shim.test.mjs +83 -0
  372. package/clients/cli/lib/manifest.d.ts +2 -0
  373. package/clients/cli/lib/manifest.mjs +31 -2
  374. package/clients/cli/lib/manifest.test.mjs +17 -0
  375. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  376. package/foundation/agent-docs/agent-docs.mjs +70 -3
  377. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  378. package/foundation/agent-docs/agent-docs.test.mjs +10 -1
  379. package/foundation/config/integration-debug.test.mjs +28 -3
  380. package/foundation/config/project-themes.test.mjs +11 -19
  381. package/foundation/config/project.d.mts +20 -11
  382. package/foundation/config/project.mjs +246 -89
  383. package/foundation/config/project.test.mjs +270 -21
  384. package/foundation/discovery/authoring-self-docs.d.mts +6 -0
  385. package/foundation/discovery/authoring-self-docs.mjs +17 -7
  386. package/foundation/discovery/authoring-self-docs.test.mjs +20 -9
  387. package/foundation/discovery/authoring-surface.d.mts +74 -0
  388. package/foundation/discovery/authoring-surface.mjs +525 -0
  389. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  390. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  391. package/foundation/discovery/cli-self-docs.mjs +490 -0
  392. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  393. package/foundation/discovery/component-discovery.d.mts +38 -0
  394. package/foundation/discovery/component-discovery.mjs +48 -0
  395. package/foundation/discovery/component-loader.d.mts +35 -38
  396. package/foundation/discovery/component-loader.mjs +53 -222
  397. package/foundation/discovery/docs-discovery.d.mts +108 -10
  398. package/foundation/discovery/docs-discovery.mjs +191 -30
  399. package/foundation/discovery/docs-discovery.test.mjs +71 -32
  400. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  401. package/foundation/discovery/docs-output-budget.mjs +1 -1
  402. package/foundation/discovery/docs-section-key.d.mts +28 -10
  403. package/foundation/discovery/docs-section-key.mjs +134 -33
  404. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  405. package/foundation/discovery/template-adapter.d.mts +113 -11
  406. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  407. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  408. package/foundation/discovery/template-adapter.mjs +772 -82
  409. package/foundation/discovery/template-adapter.test.mjs +57 -0
  410. package/foundation/discovery/theme-discovery.d.mts +67 -7
  411. package/foundation/discovery/theme-discovery.mjs +916 -186
  412. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  413. package/foundation/doc-compiler/bundle.d.mts +47 -0
  414. package/foundation/doc-compiler/bundle.mjs +278 -0
  415. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  416. package/foundation/doc-compiler/compile.d.mts +220 -39
  417. package/foundation/doc-compiler/compile.mjs +311 -15
  418. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  419. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  420. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  421. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  422. package/foundation/doc-compiler/import.d.mts +24 -0
  423. package/foundation/doc-compiler/import.mjs +59 -0
  424. package/foundation/doc-compiler/inputs.d.mts +102 -0
  425. package/foundation/doc-compiler/inputs.mjs +291 -0
  426. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  427. package/foundation/doc-compiler/ir.d.mts +13 -0
  428. package/foundation/doc-compiler/ir.mjs +196 -12
  429. package/foundation/doc-compiler/lenses.d.mts +3 -2
  430. package/foundation/doc-compiler/lenses.mjs +2 -1
  431. package/foundation/doc-compiler/links.d.mts +135 -0
  432. package/foundation/doc-compiler/links.mjs +253 -0
  433. package/foundation/doc-compiler/links.test.mjs +139 -0
  434. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  435. package/foundation/doc-compiler/overlays.d.mts +37 -0
  436. package/foundation/doc-compiler/overlays.mjs +206 -0
  437. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  438. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  439. package/foundation/doc-compiler/read.d.mts +127 -0
  440. package/foundation/doc-compiler/read.mjs +325 -0
  441. package/foundation/doc-compiler/read.test.mjs +313 -0
  442. package/foundation/doc-compiler/source.d.mts +33 -0
  443. package/foundation/doc-compiler/source.mjs +128 -0
  444. package/foundation/doc-compiler/tree.d.mts +288 -0
  445. package/foundation/doc-compiler/tree.mjs +876 -0
  446. package/foundation/doc-compiler/tree.test.mjs +598 -0
  447. package/foundation/fs/file-protection.d.mts +33 -0
  448. package/foundation/fs/file-protection.mjs +825 -0
  449. package/foundation/fs/file-protection.test.mjs +250 -0
  450. package/foundation/fs/module-loader.d.mts +1 -0
  451. package/foundation/fs/module-loader.mjs +50 -1
  452. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  453. package/foundation/fs/path-safety.d.mts +3 -2
  454. package/foundation/fs/path-safety.mjs +49 -19
  455. package/foundation/fs/path-safety.test.mjs +50 -0
  456. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  457. package/foundation/integrations/autolink.d.mts +58 -1
  458. package/foundation/integrations/autolink.mjs +143 -52
  459. package/foundation/integrations/autolink.test.mjs +1 -1
  460. package/foundation/integrations/cli-requirement.d.mts +45 -0
  461. package/foundation/integrations/cli-requirement.mjs +154 -0
  462. package/foundation/integrations/cli-requirement.test.mjs +109 -0
  463. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  464. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  465. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  466. package/foundation/integrations/contribution-inventory.mjs +27 -24
  467. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  468. package/foundation/integrations/integration-warnings.d.mts +9 -2
  469. package/foundation/integrations/integration-warnings.mjs +51 -26
  470. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  471. package/foundation/integrations/integrations.d.mts +3 -0
  472. package/foundation/integrations/integrations.mjs +11 -97
  473. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  474. package/foundation/integrations/provider-resolution.d.mts +152 -0
  475. package/foundation/integrations/provider-resolution.mjs +576 -0
  476. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  477. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  478. package/foundation/integrations/theme-descriptor.mjs +44 -0
  479. package/foundation/integrations/validate-contributions.mjs +121 -29
  480. package/foundation/response/base.d.ts +8 -4
  481. package/foundation/response/error-codes.d.mts +3 -1
  482. package/foundation/response/error-codes.d.ts +2 -0
  483. package/foundation/response/error-codes.doc.mjs +13 -4
  484. package/foundation/response/error-codes.mjs +8 -2
  485. package/foundation/response/error-codes.test.mjs +137 -10
  486. package/foundation/response/json-contract.test.mjs +11 -0
  487. package/foundation/response/json.d.mts +4 -2
  488. package/foundation/response/json.mjs +8 -10
  489. package/foundation/response/response-types.doc.mjs +22 -17
  490. package/foundation/response/response-types.doc.test.mjs +158 -0
  491. package/foundation/response/response.doc.mjs +1 -1
  492. package/foundation/text/string-utils.mjs +22 -10
  493. package/foundation/xle/expand.d.mts +2 -0
  494. package/foundation/xle/expand.mjs +4 -3
  495. package/foundation/xle/expand.test.mjs +54 -0
  496. package/foundation/xle/xle.test.mjs +13 -0
  497. package/package.json +10 -9
  498. package/assets/templates/themes/manifest.json +0 -95
  499. package/clients/cli/lib/update-check.mjs +0 -83
  500. package/clients/cli/lib/update-check.test.mjs +0 -137
  501. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -34,7 +34,10 @@ const SOURCE_TITLE = Symbol('astryx.docs.sourceTitle');
34
34
  * @returns {T}
35
35
  */
36
36
  export function withSourceTitle(section, title) {
37
- Object.defineProperty(section, SOURCE_TITLE, {value: title, configurable: true});
37
+ Object.defineProperty(section, SOURCE_TITLE, {
38
+ value: title,
39
+ configurable: true,
40
+ });
38
41
  return section;
39
42
  }
40
43
 
@@ -77,9 +80,77 @@ export function sectionKey(section) {
77
80
  }
78
81
 
79
82
  /**
80
- * Problems with the keys of a topic's sections: an authored id that is not a
81
- * stable key, a title no key derives from, and two sections sharing a key.
82
- * Keys are never suffixed to make them unique, because readers link to them.
83
+ * The first section the 0.6.x title-substring lookup would return for a query.
84
+ * @param {any[]} sections
85
+ * @param {string} query
86
+ * @returns {number}
87
+ */
88
+ function legacyTitleMatchIndex(sections, query) {
89
+ const lower = query.toLowerCase();
90
+ return sections.findIndex(section => {
91
+ const title = sourceTitle(section);
92
+ return typeof title === 'string' && title.toLowerCase().includes(lower);
93
+ });
94
+ }
95
+
96
+ /**
97
+ * A name as a docs-tree route segment: lowercase words joined by hyphens, so
98
+ * `integrationPackCheck` and `integration pack` both read naturally.
99
+ * @param {string} name
100
+ * @returns {string}
101
+ */
102
+ export function routeSegment(name) {
103
+ return String(name)
104
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
105
+ .toLowerCase()
106
+ .replace(/[^a-z0-9]+/g, '-')
107
+ .replace(/^-+|-+$/g, '');
108
+ }
109
+
110
+ /**
111
+ * Fatal key problems: only an explicitly authored `id` can make a previously
112
+ * readable topic invalid. Derived-key collisions and titles with no Latin
113
+ * letters or digits are handled by {@link withSectionKeys} for 0.6.x
114
+ * compatibility.
115
+ * @param {any[]} sections
116
+ * @returns {string[]}
117
+ */
118
+ export function sectionKeyErrors(sections) {
119
+ /** @type {string[]} */
120
+ const problems = [];
121
+ /** @type {Map<string, number>} */
122
+ const seen = new Map();
123
+ sections.forEach((section, s) => {
124
+ if (section?.id == null) return;
125
+ const at = `sections[${s}]`;
126
+ if (typeof section.id !== 'string' || !SECTION_KEY_RE.test(section.id)) {
127
+ problems.push(
128
+ `${at}.id: ${JSON.stringify(section.id)} is not a stable key. Use lowercase letters and digits joined by single hyphens.`,
129
+ );
130
+ return;
131
+ }
132
+ const first = seen.get(section.id);
133
+ if (first != null) {
134
+ problems.push(
135
+ `${at}: the key "${section.id}" is already used by sections[${first}]. Give one of them a distinct id.`,
136
+ );
137
+ return;
138
+ }
139
+ const legacyOwner = legacyTitleMatchIndex(sections, section.id);
140
+ if (legacyOwner !== -1 && legacyOwner !== s) {
141
+ problems.push(
142
+ `${at}.id: the key "${section.id}" is already a legacy title query for sections[${legacyOwner}]. Choose an id that resolves to this section.`,
143
+ );
144
+ return;
145
+ }
146
+ seen.set(section.id, s);
147
+ });
148
+ return problems;
149
+ }
150
+
151
+ /**
152
+ * Compatibility notices for section keys. These inputs loaded in 0.6.x, so
153
+ * readers keep accepting them and assign deterministic fallback keys.
83
154
  * @param {any[]} sections
84
155
  * @returns {string[]}
85
156
  */
@@ -90,7 +161,6 @@ export function sectionKeyProblems(sections) {
90
161
  const seen = new Map();
91
162
  sections.forEach((section, s) => {
92
163
  const at = `sections[${s}]`;
93
- // A missing title is reported where titles are checked; no key to judge.
94
164
  if (
95
165
  section?.id == null &&
96
166
  (typeof section?.title !== 'string' || section.title === '')
@@ -109,14 +179,14 @@ export function sectionKeyProblems(sections) {
109
179
  const key = sectionKey(section);
110
180
  if (key === '') {
111
181
  problems.push(
112
- `${at}: no key derives from the title ${JSON.stringify(section?.title)}. Give the section an id.`,
182
+ `${at}: no key derives from the title ${JSON.stringify(section?.title)}. A deterministic section-N compatibility key is used; add an explicit id.`,
113
183
  );
114
184
  return;
115
185
  }
116
186
  const first = seen.get(key);
117
187
  if (first != null) {
118
188
  problems.push(
119
- `${at}: the key "${key}" is already used by sections[${first}]. Give one of them a distinct id or title.`,
189
+ `${at}: the key "${key}" is already used by sections[${first}]. A suffixed compatibility key is used for title-derived collisions; give one of them a distinct id or title.`,
120
190
  );
121
191
  return;
122
192
  }
@@ -133,48 +203,79 @@ export function sectionKeyProblems(sections) {
133
203
  * @returns {T}
134
204
  */
135
205
  export function withSectionKeys(doc) {
206
+ const reserved = new Set(
207
+ doc.sections
208
+ .map(section => section?.id)
209
+ .filter(id => typeof id === 'string' && SECTION_KEY_RE.test(id)),
210
+ );
211
+ const used = new Set();
136
212
  return {
137
213
  ...doc,
138
- sections: doc.sections.map(section =>
139
- section.id != null
140
- ? section
141
- : withSourceTitle(
142
- {...section, id: sectionKey(section)},
143
- sourceTitle(section),
144
- ),
145
- ),
214
+ sections: doc.sections.map((section, index) => {
215
+ if (section.id != null) {
216
+ used.add(section.id);
217
+ return section;
218
+ }
219
+ const base =
220
+ sectionTitleKey(sourceTitle(section)) || `section-${index + 1}`;
221
+ let key = base;
222
+ let suffix = 2;
223
+ while (
224
+ reserved.has(key) ||
225
+ used.has(key) ||
226
+ (legacyTitleMatchIndex(doc.sections, key) !== -1 &&
227
+ legacyTitleMatchIndex(doc.sections, key) !== index)
228
+ ) {
229
+ key = `${base}-${suffix}`;
230
+ suffix += 1;
231
+ }
232
+ used.add(key);
233
+ return withSourceTitle({...section, id: key}, sourceTitle(section));
234
+ }),
146
235
  };
147
236
  }
148
237
 
149
238
  /**
150
- * Find the section a reader asked for: by key, then by exact title (or the
151
- * key the query derives), then by a title that contains the query. More than
152
- * one match is refused rather than guessed.
239
+ * Find the section a reader asked for. The 0.6.x first-match title-substring
240
+ * lookup remains first in the authored-title view. In a localized view, an
241
+ * exact stable key resolves before translated title substrings because those
242
+ * translations cannot participate in language-stable key allocation. Generated
243
+ * keys avoid authored-title conflicts, and authored IDs that would shadow an
244
+ * authored legacy query are rejected.
153
245
  * @param {any[]} sections
154
246
  * @param {string} query
155
- * @returns {{section: any | null, candidates: any[]}} `candidates` lists the
156
- * matches when the query is ambiguous, and is empty when nothing matches
247
+ * @returns {{section: any | null, candidates: any[]}} `candidates` lists every
248
+ * legacy title match when the query is ambiguous
157
249
  */
158
250
  export function findDocSection(sections, query) {
159
251
  const wanted = query.trim();
160
252
  const byKey = sections.find(section => sectionKey(section) === wanted);
161
- if (byKey) return {section: byKey, candidates: []};
253
+ const hasLocalizedTitles = sections.some(
254
+ section => sourceTitle(section) !== section.title,
255
+ );
256
+ if (byKey && hasLocalizedTitles) {
257
+ return {section: byKey, candidates: []};
258
+ }
162
259
 
163
260
  const lower = wanted.toLowerCase();
164
- const derived = sectionTitleKey(wanted);
165
- const exact = sections.filter(
166
- section =>
167
- section.title.toLowerCase() === lower ||
168
- (derived !== '' && sectionTitleKey(sourceTitle(section)) === derived),
261
+ const legacy = sections.filter(section =>
262
+ section.title.toLowerCase().includes(lower),
169
263
  );
170
- if (exact.length === 1) return {section: exact[0], candidates: []};
171
- if (exact.length > 1) return {section: null, candidates: exact};
264
+ if (legacy.length > 0) {
265
+ return {section: legacy[0], candidates: legacy.length > 1 ? legacy : []};
266
+ }
172
267
 
173
- const partial = sections.filter(section =>
174
- section.title.toLowerCase().includes(lower),
268
+ const byFallbackKey = sections.find(
269
+ section => sectionKey(section) === wanted,
270
+ );
271
+ if (byFallbackKey) return {section: byFallbackKey, candidates: []};
272
+
273
+ const derived = sectionTitleKey(wanted);
274
+ const byDerivedKey = sections.find(
275
+ section =>
276
+ derived !== '' && sectionTitleKey(sourceTitle(section)) === derived,
175
277
  );
176
- if (partial.length === 1) return {section: partial[0], candidates: []};
177
- return {section: null, candidates: partial};
278
+ return {section: byDerivedKey ?? null, candidates: []};
178
279
  }
179
280
 
180
281
  /**
@@ -205,7 +306,7 @@ export function sectionSummary(section, max = SECTION_SUMMARY_MAX) {
205
306
  * The index a topic-only read returns: what the topic is, and one entry per
206
307
  * section with the key to read it by.
207
308
  * @param {{name: string, title: string, description: string, sections: any[]}} doc
208
- * @returns {import('../../api/docs/docs.type.mjs').DocsIndex}
309
+ * @returns {Omit<import('../../api/docs/docs.type.mjs').DocsIndex, 'links'>}
209
310
  */
210
311
  export function buildDocsIndexData(doc) {
211
312
  return {
@@ -7,6 +7,7 @@ import {
7
7
  buildDocsIndexData,
8
8
  findDocSection,
9
9
  sectionKey,
10
+ sectionKeyErrors,
10
11
  sectionKeyProblems,
11
12
  sectionSummary,
12
13
  sectionTitleKey,
@@ -68,12 +69,17 @@ describe('sectionKeyProblems', () => {
68
69
  section('Quick-start'),
69
70
  ]);
70
71
  expect(problems).toHaveLength(1);
71
- expect(problems[0]).toContain('"quick-start" is already used by sections[0]');
72
+ expect(problems[0]).toContain(
73
+ '"quick-start" is already used by sections[0]',
74
+ );
72
75
  });
73
76
 
74
77
  it('rejects an authored id that collides with a derived key', () => {
75
78
  expect(
76
- sectionKeyProblems([section('Install'), section('Setup', {id: 'install'})]),
79
+ sectionKeyProblems([
80
+ section('Install'),
81
+ section('Setup', {id: 'install'}),
82
+ ]),
77
83
  ).toHaveLength(1);
78
84
  });
79
85
 
@@ -85,13 +91,13 @@ describe('sectionKeyProblems', () => {
85
91
  }
86
92
  });
87
93
 
88
- it('rejects a title no key derives from', () => {
94
+ it('reports a title no key derives from', () => {
89
95
  expect(sectionKeyProblems([section('亮/暗模式')])[0]).toContain(
90
- 'Give the section an id',
91
- );
92
- expect(sectionKeyProblems([section('亮/暗模式', {id: 'light-dark'})])).toEqual(
93
- [],
96
+ 'compatibility key is used',
94
97
  );
98
+ expect(
99
+ sectionKeyProblems([section('亮/暗模式', {id: 'light-dark'})]),
100
+ ).toEqual([]);
95
101
  });
96
102
 
97
103
  it('leaves a missing title to the title check', () => {
@@ -107,12 +113,21 @@ describe('withSectionKeys', () => {
107
113
  expect(doc.sections.map(s => s.id)).toEqual(['quick-start', 'use']);
108
114
  });
109
115
 
110
- it('keeps the authored title of a translated section', () => {
116
+ it('keeps authored titles and keys stable for translated sections', () => {
111
117
  const doc = withSectionKeys({
112
- sections: [withSourceTitle(section('快速开始'), 'Quick Start')],
118
+ sections: [
119
+ withSourceTitle(section('高级安装'), 'Install advanced'),
120
+ withSourceTitle(section('安装'), 'Install'),
121
+ ],
113
122
  });
114
- expect(doc.sections[0].id).toBe('quick-start');
115
- expect(sourceTitle(doc.sections[0])).toBe('Quick Start');
123
+ expect(doc.sections.map(s => s.id)).toEqual([
124
+ 'install-advanced',
125
+ 'install-2',
126
+ ]);
127
+ for (const target of doc.sections) {
128
+ expect(findDocSection(doc.sections, target.id).section).toBe(target);
129
+ }
130
+ expect(sourceTitle(doc.sections[0])).toBe('Install advanced');
116
131
  });
117
132
  });
118
133
 
@@ -127,7 +142,14 @@ describe('findDocSection', () => {
127
142
  ],
128
143
  }).sections;
129
144
 
130
- it('finds a section by key first', () => {
145
+ it('finds every emitted key without changing a legacy query', () => {
146
+ const colliding = withSectionKeys({
147
+ sections: [section('Install advanced'), section('Install')],
148
+ }).sections;
149
+ expect(findDocSection(colliding, 'install').section).toBe(colliding[0]);
150
+ for (const target of colliding) {
151
+ expect(findDocSection(colliding, target.id).section).toBe(target);
152
+ }
131
153
  expect(findDocSection(sections, 'tokens').section.title).toBe(
132
154
  'Theme Tokens',
133
155
  );
@@ -149,15 +171,15 @@ describe('findDocSection', () => {
149
171
  expect(findDocSection(sections, 'props').section.id).toBe('theme-props');
150
172
  });
151
173
 
152
- it('refuses an ambiguous exact title and lists the candidates', () => {
174
+ it('keeps the first ambiguous exact-title match and lists the candidates', () => {
153
175
  const {section: match, candidates} = findDocSection(sections, 'Overview');
154
- expect(match).toBeNull();
176
+ expect(match?.id).toBe('overview-a');
155
177
  expect(candidates.map(s => s.id)).toEqual(['overview-a', 'overview-b']);
156
178
  });
157
179
 
158
- it('refuses an ambiguous partial title', () => {
180
+ it('keeps the first ambiguous partial-title match', () => {
159
181
  const {section: match, candidates} = findDocSection(sections, 'theme');
160
- expect(match).toBeNull();
182
+ expect(match?.id).toBe('theme-props');
161
183
  expect(candidates.map(s => s.id)).toEqual(['theme-props', 'tokens']);
162
184
  });
163
185
 
@@ -185,9 +207,9 @@ describe('sectionSummary', () => {
185
207
  });
186
208
 
187
209
  it('is empty when the section has no text', () => {
188
- expect(sectionSummary({content: [{type: 'table', headers: [], rows: []}]})).toBe(
189
- '',
190
- );
210
+ expect(
211
+ sectionSummary({content: [{type: 'table', headers: [], rows: []}]}),
212
+ ).toBe('');
191
213
  });
192
214
 
193
215
  it('cuts a long summary at a word boundary', () => {
@@ -11,11 +11,39 @@ export function pkgOf(t: {
11
11
  package?: string;
12
12
  }): string;
13
13
  /**
14
- * Replace demo asset references with a placeholder so scaffolded pages
15
- * render with zero setup. Images get a self-contained data URI; videos
16
- * (which have no equivalent inline placeholder — see VIDEO_EXTENSIONS) are
17
- * stripped to an empty src instead of being mis-replaced with image data.
18
- * Builders drop in their own media either way.
14
+ * Every id that should resolve to a discovered template. Replacements keep
15
+ * their own integration id and also own the Core id they replace.
16
+ * @param {{dirName: string, replaces?: string}} template
17
+ * @returns {string[]}
18
+ */
19
+ export function templateLookupIds(template: {
20
+ dirName: string;
21
+ replaces?: string;
22
+ }): string[];
23
+ /**
24
+ * Remove entries shadowed in the default discovery view while retaining them in
25
+ * package-scoped views. An active replacement owns its target id. A rejected
26
+ * same-id declaration falls back to Core when a Core template of the same kind
27
+ * owns that id; otherwise the integration template remains available by kind.
28
+ * @param {DiscoveredTemplate[]} templates
29
+ * @returns {DiscoveredTemplate[]}
30
+ */
31
+ export function effectiveTemplateDiscovery(templates: DiscoveredTemplate[]): DiscoveredTemplate[];
32
+ /**
33
+ * Replace each Astryx template fixture reference with a placeholder so
34
+ * scaffolded pages render with zero setup. Images get a self-contained data
35
+ * URI; videos (which have no equivalent inline placeholder — see
36
+ * VIDEO_EXTENSIONS) are stripped to an empty src instead of being
37
+ * mis-replaced with image data. Builders drop in their own media either way.
38
+ *
39
+ * A reference is a URL token that resolves to a root-relative path under
40
+ * FIXTURE_SEGMENT. It is replaced whole, query and fragment included, and
41
+ * classified by the suffix of its last path segment. A reference that cannot
42
+ * be replaced safely throws with its path rather than being guessed at or
43
+ * left behind. Prose is left as written: in text (JSX text, a word inside a
44
+ * longer string) trailing punctuation is not part of a path and a path with
45
+ * no suffix, such as the bare directory, is a mention; inside a comment
46
+ * nothing throws.
19
47
  *
20
48
  * @param {string} source - Template source code.
21
49
  * @returns {string} Source with demo asset references replaced.
@@ -28,6 +56,13 @@ export function stripTemplateAssetRefs(source: string): string;
28
56
  * @returns {string[]}
29
57
  */
30
58
  export function listTemplates(): string[];
59
+ /**
60
+ * Resolve the template-spec file for a core page directory: the first existing
61
+ * metadata file in {@link ALL_TEMPLATE_SUFFIXES} precedence, or null.
62
+ * @param {string} dirPath
63
+ * @returns {string | null}
64
+ */
65
+ export function findPageDocFile(dirPath: string): string | null;
31
66
  /**
32
67
  * Discover only the templates built into @astryxdesign/core. Integration
33
68
  * authoring checks use this narrower surface so a broken project config or a
@@ -35,22 +70,54 @@ export function listTemplates(): string[];
35
70
  * @returns {Promise<DiscoveredTemplate[]>}
36
71
  */
37
72
  export function discoverCoreTemplates(): Promise<DiscoveredTemplate[]>;
73
+ /**
74
+ * Apply valid integration replacements to a raw template set.
75
+ *
76
+ * One declaration owns its Core target. When different configured packages
77
+ * replace the same target, the later package wins and discovery returns a
78
+ * warning, matching integration-doc replacement order. Multiple declarations
79
+ * inside one package are invalid and fail closed. Missing targets and kind
80
+ * mismatches also fail closed: Core stays selected and every integration
81
+ * template remains addressable by its own id.
82
+ *
83
+ * @param {DiscoveredTemplate[]} templates
84
+ * @param {TemplateDiscoveryError[]} [declarationErrors]
85
+ * @returns {{templates: DiscoveredTemplate[], errors: TemplateReplacementError[]}}
86
+ */
87
+ export function applyTemplateReplacements(templates: DiscoveredTemplate[], declarationErrors?: TemplateDiscoveryError[]): {
88
+ templates: DiscoveredTemplate[];
89
+ errors: TemplateReplacementError[];
90
+ };
91
+ /**
92
+ * Discover every template without hiding replaced Core originals. Internal
93
+ * package-qualified selection uses this view.
94
+ * @param {string} [cwd]
95
+ * @returns {Promise<DiscoveredTemplate[]>}
96
+ */
97
+ export function discoverAllUnresolved(cwd?: string): Promise<DiscoveredTemplate[]>;
98
+ /**
99
+ * Discover the resolved catalog before default-view shadowing. Internal
100
+ * package-qualified selection uses this view.
101
+ * @param {string} [cwd]
102
+ * @returns {Promise<DiscoveredTemplate[]>}
103
+ */
104
+ export function discoverAllResolved(cwd?: string): Promise<DiscoveredTemplate[]>;
38
105
  /**
39
106
  * @param {string} [cwd]
40
107
  * @returns {Promise<DiscoveredTemplate[]>}
41
108
  */
42
109
  export function discoverAll(cwd?: string): Promise<DiscoveredTemplate[]>;
43
110
  /**
44
- * Like {@link discoverAll} but also returns integration-template discovery
45
- * errors (missing same-stem source, missing `type`, load failure). Use this
46
- * when the caller wants to warn about malformed integration templates.
111
+ * Like {@link discoverAll} but also returns integration-template discovery and
112
+ * replacement-declaration errors. Use this when the caller wants to warn about
113
+ * malformed integration templates or inactive replacement declarations.
47
114
  *
48
115
  * @param {string} [cwd]
49
- * @returns {Promise<{templates: DiscoveredTemplate[], errors: TemplateDiscoveryError[]}>}
116
+ * @returns {Promise<{templates: DiscoveredTemplate[], errors: Array<TemplateDiscoveryError | TemplateReplacementError>}>}
50
117
  */
51
118
  export function discoverAllWithErrors(cwd?: string): Promise<{
52
119
  templates: DiscoveredTemplate[];
53
- errors: TemplateDiscoveryError[];
120
+ errors: Array<TemplateDiscoveryError | TemplateReplacementError>;
54
121
  }>;
55
122
  /**
56
123
  * Discover the templates contributed by a SINGLE integration. Same per-template
@@ -58,12 +125,13 @@ export function discoverAllWithErrors(cwd?: string): Promise<{
58
125
  * page|block type required); broken templates are recorded in `errors` rather
59
126
  * than thrown. Exposed for `doctor integration validate` and template authoring checks.
60
127
  *
61
- * @param {{name?: string, __spec?: string, templates?: string}} integration
128
+ * @param {{name?: string, __spec?: string, __autolinked?: boolean, templates?: string}} integration
62
129
  * @returns {Promise<{templates: DiscoveredTemplate[], errors: TemplateDiscoveryError[]}>}
63
130
  */
64
131
  export function discoverIntegrationTemplatesForOne(integration: {
65
132
  name?: string;
66
133
  __spec?: string;
134
+ __autolinked?: boolean;
67
135
  templates?: string;
68
136
  }): Promise<{
69
137
  templates: DiscoveredTemplate[];
@@ -117,6 +185,23 @@ export type DiscoveredTemplate = {
117
185
  filePath: string;
118
186
  docPath: string;
119
187
  package?: string | undefined;
188
+ /**
189
+ * whether the owning integration was discovered
190
+ * from package.json rather than named in astryx.config
191
+ */
192
+ autolinked?: boolean | undefined;
193
+ /**
194
+ * active Core template id this integration template replaces
195
+ */
196
+ replaces?: string | undefined;
197
+ /**
198
+ * whether an invalid declaration was disabled
199
+ */
200
+ replacementRejected?: boolean | undefined;
201
+ /**
202
+ * disabled declaration target
203
+ */
204
+ replacementTarget?: string | undefined;
120
205
  };
121
206
  /**
122
207
  * An integration-template discovery error.
@@ -125,6 +210,23 @@ export type TemplateDiscoveryError = {
125
210
  package: string;
126
211
  template?: string | undefined;
127
212
  message: string;
213
+ code?: string | undefined;
214
+ severity?: "error" | "warning" | undefined;
215
+ /**
216
+ * Core target whose replacement set is invalid
217
+ */
218
+ replacementTarget?: string | undefined;
219
+ /**
220
+ * whether the declaration came from an autolinked integration
221
+ */
222
+ autolinked?: boolean | undefined;
223
+ };
224
+ /**
225
+ * A semantic error in an integration template replacement declaration.
226
+ */
227
+ export type TemplateReplacementError = TemplateDiscoveryError & {
228
+ code: "missing_template_replacement_target" | "ambiguous_template_replacement" | "invalid_template_replacement";
229
+ severity: "warning" | "error";
128
230
  };
129
231
  /**
130
232
  * The loaded metadata object from a template spec (loose — authored shape).