@astryxdesign/cli 0.6.3-canary.98a2e4e → 0.6.3-canary.9c4d44d

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 (612) hide show
  1. package/README.md +117 -79
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/_adapter.d.mts +50 -0
  4. package/api/build/_adapter.mjs +60 -0
  5. package/api/build/build.doc.mjs +16 -9
  6. package/api/build/build.test.mjs +197 -8
  7. package/api/build/build.type.d.mts +91 -2
  8. package/api/build/build.type.mjs +52 -8
  9. package/api/build/help/help.d.mts +12 -5
  10. package/api/build/help/help.mjs +69 -6
  11. package/api/build/kit/kit.d.mts +4 -1
  12. package/api/build/kit/kit.mjs +165 -49
  13. package/api/build/kit/rank.d.mts +44 -0
  14. package/api/build/kit/rank.mjs +432 -0
  15. package/api/build/kit/rank.test.mjs +196 -0
  16. package/api/component/_adapter.d.mts +6 -12
  17. package/api/component/_adapter.mjs +20 -10
  18. package/api/component/component.doc.mjs +13 -3
  19. package/api/component/component.mjs +91 -14
  20. package/api/component/component.test.mjs +38 -0
  21. package/api/component/component.type.d.mts +22 -11
  22. package/api/component/component.type.mjs +32 -24
  23. package/api/component/detail/blocks/blocks.d.mts +2 -1
  24. package/api/component/detail/blocks/blocks.mjs +4 -3
  25. package/api/component/list/list.d.mts +0 -5
  26. package/api/component/list/list.mjs +40 -11
  27. package/api/discover/_adapter.d.mts +114 -6
  28. package/api/discover/_adapter.mjs +372 -17
  29. package/api/discover/_adapter.test.mjs +215 -0
  30. package/api/discover/_catalog-view.d.mts +115 -0
  31. package/api/discover/_catalog-view.mjs +203 -0
  32. package/api/discover/_catalog-view.test.mjs +128 -0
  33. package/api/discover/detail/detail.d.mts +18 -6
  34. package/api/discover/detail/detail.mjs +67 -13
  35. package/api/discover/detail/detail.test.mjs +85 -0
  36. package/api/discover/detail/item/item.d.mts +26 -0
  37. package/api/discover/detail/item/item.mjs +78 -0
  38. package/api/discover/detail/item/item.test.mjs +73 -0
  39. package/api/discover/discover.d.mts +3 -9
  40. package/api/discover/discover.doc.mjs +62 -18
  41. package/api/discover/discover.mjs +220 -36
  42. package/api/discover/discover.test.mjs +11 -2
  43. package/api/discover/discover.type.d.mts +150 -11
  44. package/api/discover/discover.type.mjs +107 -17
  45. package/api/discover/list/list.d.mts +20 -6
  46. package/api/discover/list/list.mjs +45 -12
  47. package/api/discover/list/list.test.mjs +46 -0
  48. package/api/discover/search/search.d.mts +18 -16
  49. package/api/discover/search/search.mjs +102 -56
  50. package/api/discover/search/search.test.mjs +144 -10
  51. package/api/docs/_adapter.d.mts +268 -47
  52. package/api/docs/_adapter.mjs +970 -149
  53. package/api/docs/compiled-topics.test.mjs +78 -0
  54. package/api/docs/detail/detail.d.mts +0 -15
  55. package/api/docs/detail/detail.mjs +22 -78
  56. package/api/docs/detail/section/section.mjs +39 -24
  57. package/api/docs/detail/section/section.test.mjs +19 -9
  58. package/api/docs/docs.d.mts +5 -3
  59. package/api/docs/docs.doc.mjs +39 -17
  60. package/api/docs/docs.mjs +44 -8
  61. package/api/docs/docs.test.mjs +158 -4
  62. package/api/docs/docs.type.d.mts +185 -6
  63. package/api/docs/docs.type.mjs +127 -13
  64. package/api/docs/index/index.mjs +15 -6
  65. package/api/docs/index/index.test.mjs +1 -1
  66. package/api/docs/integration-tree.test.mjs +555 -0
  67. package/api/docs/integrationDocs.test.mjs +14 -14
  68. package/api/docs/list/list.mjs +28 -12
  69. package/api/docs/node/node.d.mts +43 -0
  70. package/api/docs/node/node.mjs +192 -0
  71. package/api/docs/reference-blocks.test.mjs +406 -0
  72. package/api/doctor/doctor.d.mts +54 -4
  73. package/api/doctor/doctor.doc.mjs +1 -0
  74. package/api/doctor/doctor.mjs +332 -21
  75. package/api/doctor/doctor.test.mjs +420 -7
  76. package/api/gap-report/gap-report.doc.mjs +8 -4
  77. package/api/hook/_adapter.mjs +19 -5
  78. package/api/hook/hook.doc.mjs +1 -0
  79. package/api/hook/hook.type.d.mts +3 -3
  80. package/api/hook/hook.type.mjs +11 -11
  81. package/api/hook/list/list.d.mts +1 -1
  82. package/api/hook/list/list.mjs +69 -17
  83. package/api/index.d.mts +1 -1
  84. package/api/index.mjs +1 -0
  85. package/api/init/init.doc.mjs +6 -1
  86. package/api/init/init.test.mjs +41 -1
  87. package/api/init/remove/remove.mjs +1 -1
  88. package/api/init/run/run.mjs +20 -10
  89. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  90. package/api/integration/add-contribution.d.mts +2 -1
  91. package/api/integration/add-contribution.mjs +130 -15
  92. package/api/integration/add-contribution.test.mjs +258 -7
  93. package/api/integration/add-helpers.d.mts +5 -2
  94. package/api/integration/add-helpers.mjs +36 -9
  95. package/api/integration/add-theme.mjs +34 -64
  96. package/api/integration/add-theme.test.mjs +105 -21
  97. package/api/integration/authoring-checks.mjs +138 -28
  98. package/api/integration/authoring-checks.test.mjs +179 -7
  99. package/api/integration/authoring-checks.type.mjs +6 -1
  100. package/api/integration/integration-authoring.type.d.mts +2 -0
  101. package/api/integration/integration-authoring.type.mjs +2 -0
  102. package/api/integration/integration-block-exports.test.mjs +10 -6
  103. package/api/integration/integrationAdd.doc.mjs +14 -4
  104. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  105. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  106. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  107. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  108. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  109. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  110. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  111. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  112. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  113. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  114. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  115. package/api/integration/pack-check.mjs +83 -7
  116. package/api/integration/pack-check.test.mjs +387 -47
  117. package/api/integration/pack-check.type.d.mts +26 -2
  118. package/api/integration/pack-check.type.mjs +14 -1
  119. package/api/integration/summarizeIssues.doc.mjs +1 -0
  120. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  121. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  122. package/api/integration/validate-integration.mjs +52 -102
  123. package/api/integration/validate-integration.test.mjs +179 -26
  124. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  125. package/api/integration/validateIntegration.doc.mjs +3 -2
  126. package/api/json/assertResponse.doc.mjs +1 -0
  127. package/api/json/envelope-types.test.mjs +76 -0
  128. package/api/json/index.ts +2 -0
  129. package/api/json/isError.doc.mjs +1 -0
  130. package/api/json/parseResponse.doc.mjs +3 -2
  131. package/api/layout/_adapter.mjs +20 -5
  132. package/api/layout/expand/expand.mjs +7 -5
  133. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  134. package/api/layout/grammar/grammar.mjs +2 -1
  135. package/api/layout/layoutCheck.doc.mjs +1 -0
  136. package/api/layout/layoutExpand.doc.mjs +2 -1
  137. package/api/layout/layoutGrammar.doc.mjs +1 -0
  138. package/api/search/search-return-type.test.mjs +54 -0
  139. package/api/search/search.d.mts +61 -10
  140. package/api/search/search.doc.mjs +8 -2
  141. package/api/search/search.mjs +471 -83
  142. package/api/search/search.test.mjs +124 -1
  143. package/api/search/search.type.d.mts +14 -2
  144. package/api/search/search.type.mjs +5 -2
  145. package/api/swizzle/copy/copy.mjs +28 -11
  146. package/api/swizzle/swizzle.doc.mjs +2 -1
  147. package/api/swizzle/swizzle.type.d.mts +2 -2
  148. package/api/swizzle/swizzle.type.mjs +2 -2
  149. package/api/template/copy/copy.mjs +17 -23
  150. package/api/template/copy/copy.test.mjs +17 -0
  151. package/api/template/list/list.mjs +1 -0
  152. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  153. package/api/template/template-integration.test.mjs +1072 -3
  154. package/api/template/template-suffix.test.mjs +41 -21
  155. package/api/template/template.doc.mjs +30 -8
  156. package/api/template/template.mjs +45 -8
  157. package/api/template/template.type.d.mts +11 -13
  158. package/api/template/template.type.mjs +15 -14
  159. package/api/theme/_adapter.d.mts +2 -3
  160. package/api/theme/_adapter.mjs +4 -5
  161. package/api/theme/add/add.binary.test.mjs +84 -0
  162. package/api/theme/add/add.mjs +31 -22
  163. package/api/theme/add/add.rollback.test.mjs +158 -0
  164. package/api/theme/add/add.staging.test.mjs +83 -0
  165. package/api/theme/add/add.test.mjs +14 -1
  166. package/api/theme/build/build.family.test.mjs +7 -12
  167. package/api/theme/build/build.mjs +140 -59
  168. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  169. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  170. package/api/theme/build/build.rollback.test.mjs +148 -0
  171. package/api/theme/build/build.test.mjs +127 -0
  172. package/api/theme/build/font-warning.mjs +3 -3
  173. package/api/theme/build/font-warning.test.mjs +5 -2
  174. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  175. package/api/theme/integration-themes.test.mjs +39 -28
  176. package/api/theme/list/list.test.mjs +19 -20
  177. package/api/theme/listThemes.doc.mjs +6 -5
  178. package/api/theme/palette/generate/generate.mjs +8 -3
  179. package/api/theme/palette/generate/generate.test.mjs +96 -0
  180. package/api/theme/palette/generate/generator.d.mts +10 -13
  181. package/api/theme/palette/generate/generator.mjs +15 -4
  182. package/api/theme/palette/generate/generator.test.mjs +10 -0
  183. package/api/theme/template/template.mjs +11 -2
  184. package/api/theme/template/template.test.mjs +20 -0
  185. package/api/theme/theme.type.d.mts +170 -11
  186. package/api/theme/theme.type.mjs +94 -27
  187. package/api/theme/themeAdd.doc.mjs +4 -3
  188. package/api/theme/themeBuild.doc.mjs +8 -4
  189. package/api/theme/themeList.doc.mjs +6 -3
  190. package/api/theme/themeListAvailable.doc.mjs +5 -3
  191. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  192. package/api/theme/themeTargets.doc.mjs +1 -0
  193. package/api/theme/themeTemplate.doc.mjs +6 -2
  194. package/api/upgrade/_adapter.d.mts +32 -5
  195. package/api/upgrade/_adapter.mjs +124 -73
  196. package/api/upgrade/list/list.mjs +2 -1
  197. package/api/upgrade/list/list.test.mjs +73 -0
  198. package/api/upgrade/provider-agreement.test.mjs +152 -0
  199. package/api/upgrade/run/run.mjs +356 -59
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +8 -2
  202. package/api/upgrade/upgrade.type.d.mts +42 -4
  203. package/api/upgrade/upgrade.type.mjs +26 -10
  204. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  205. package/assets/codemods/integration-discovery.mjs +48 -4
  206. package/assets/codemods/integration-discovery.test.mjs +73 -0
  207. package/assets/codemods/integration-runner.mjs +56 -4
  208. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  209. package/assets/codemods/run-codemod.mjs +177 -34
  210. package/assets/codemods/runner.mjs +350 -102
  211. package/assets/codemods/term-log.mjs +32 -8
  212. package/assets/codemods/term-log.test.mjs +19 -1
  213. package/assets/codemods/transform-prop.mjs +109 -0
  214. package/assets/codemods/transform-prop.test.mjs +95 -0
  215. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  216. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  217. package/assets/codemods/transforms/next/index.mjs +19 -1
  218. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  219. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  220. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  221. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  222. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  223. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  224. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  225. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  226. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  227. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  228. package/assets/docs/getting-started.doc.mjs +2 -2
  229. package/assets/docs/internationalization.doc.mjs +7 -5
  230. package/assets/docs/layout.doc.dense.mjs +2 -2
  231. package/assets/docs/layout.doc.mjs +1 -1
  232. package/assets/docs/principles.doc.mjs +6 -6
  233. package/assets/docs/styling-libraries.doc.mjs +4 -4
  234. package/assets/docs/styling.doc.mjs +4 -4
  235. package/assets/docs/theme.doc.mjs +5 -5
  236. package/assets/docs/tokens.doc.mjs +1 -1
  237. package/assets/docs/tree/api.doc.mjs +30 -0
  238. package/assets/docs/tree/cli.doc.mjs +23 -0
  239. package/assets/docs/tree/commands.doc.mjs +25 -0
  240. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +95 -39
  241. package/assets/docs/tree/integrations.test.mjs +62 -0
  242. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  243. package/assets/docs/working-with-ai.doc.mjs +4 -4
  244. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  245. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  246. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  247. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  248. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  249. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  250. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  251. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  252. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  253. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  254. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  255. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  262. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  264. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  265. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  266. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  267. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  268. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  269. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  270. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  271. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  272. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  273. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  274. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  275. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  276. package/authoring/_shared/contract.ts +22 -0
  277. package/authoring/codemod/codemod.doc.mjs +7 -2
  278. package/authoring/codemod/parse.d.mts +8 -8
  279. package/authoring/codemod/parse.mjs +8 -6
  280. package/authoring/codemod/type.ts +12 -0
  281. package/authoring/config/config.doc.mjs +10 -2
  282. package/authoring/config/debug-composition.test.mjs +92 -0
  283. package/authoring/config/parse.d.mts +15 -13
  284. package/authoring/config/parse.mjs +27 -8
  285. package/authoring/config/parse.test.mjs +8 -0
  286. package/authoring/config/type.ts +29 -6
  287. package/authoring/debug/debug.doc.d.mts +11 -0
  288. package/authoring/debug/debug.doc.mjs +182 -0
  289. package/authoring/debug/parse.d.mts +7 -7
  290. package/authoring/debug/parse.mjs +3 -3
  291. package/authoring/discover/discover.doc.d.mts +13 -0
  292. package/authoring/discover/discover.doc.mjs +138 -0
  293. package/authoring/discover/parse.d.mts +24 -0
  294. package/authoring/discover/parse.mjs +128 -0
  295. package/authoring/discover/parse.test.mjs +124 -0
  296. package/authoring/discover/type.ts +87 -0
  297. package/authoring/doctypes/_schema.d.mts +240 -128
  298. package/authoring/doctypes/_schema.mjs +198 -16
  299. package/authoring/doctypes/base/graph-fields.doc.mjs +15 -6
  300. package/authoring/doctypes/base/type.ts +9 -4
  301. package/authoring/doctypes/command/command.doc.mjs +4 -3
  302. package/authoring/doctypes/command/parse.d.mts +2 -2
  303. package/authoring/doctypes/command/parse.mjs +1 -1
  304. package/authoring/doctypes/command/type.ts +4 -4
  305. package/authoring/doctypes/component/component.doc.mjs +5 -2
  306. package/authoring/doctypes/component/parse.d.mts +2 -2
  307. package/authoring/doctypes/component/parse.mjs +1 -1
  308. package/authoring/doctypes/component/type.ts +3 -3
  309. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  310. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  311. package/authoring/doctypes/enum/parse.d.mts +2 -2
  312. package/authoring/doctypes/enum/parse.mjs +1 -1
  313. package/authoring/doctypes/enum/type.ts +2 -2
  314. package/authoring/doctypes/function/function.doc.mjs +7 -2
  315. package/authoring/doctypes/function/parse.d.mts +2 -2
  316. package/authoring/doctypes/function/parse.mjs +1 -1
  317. package/authoring/doctypes/function/type.ts +4 -3
  318. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  319. package/authoring/doctypes/hook/parse.d.mts +2 -2
  320. package/authoring/doctypes/hook/parse.mjs +1 -1
  321. package/authoring/doctypes/hook/type.ts +3 -3
  322. package/authoring/doctypes/legacy.d.mts +6 -6
  323. package/authoring/doctypes/legacy.mjs +3 -3
  324. package/authoring/doctypes/load-contract.test.mjs +233 -0
  325. package/authoring/doctypes/namespace/namespace.doc.mjs +9 -9
  326. package/authoring/doctypes/namespace/parse.d.mts +2 -2
  327. package/authoring/doctypes/namespace/parse.mjs +1 -1
  328. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  329. package/authoring/doctypes/namespace/type.ts +6 -3
  330. package/authoring/doctypes/parse.d.mts +22 -20
  331. package/authoring/doctypes/parse.mjs +19 -14
  332. package/authoring/doctypes/reference/parse.d.mts +2 -2
  333. package/authoring/doctypes/reference/parse.mjs +1 -1
  334. package/authoring/doctypes/reference/reference.doc.mjs +39 -6
  335. package/authoring/doctypes/reference/type.ts +31 -14
  336. package/authoring/doctypes/schema/parse.d.mts +2 -2
  337. package/authoring/doctypes/schema/parse.mjs +1 -1
  338. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  339. package/authoring/doctypes/schema/type.ts +3 -4
  340. package/authoring/doctypes/template/parse.d.mts +94 -1
  341. package/authoring/doctypes/template/parse.mjs +37 -1
  342. package/authoring/doctypes/template/parse.test.mjs +18 -0
  343. package/authoring/doctypes/template/template.doc.mjs +13 -3
  344. package/authoring/doctypes/template/type.ts +12 -1
  345. package/authoring/doctypes/theme/parse.d.mts +35 -0
  346. package/authoring/doctypes/theme/parse.mjs +76 -0
  347. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  348. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  349. package/authoring/doctypes/theme/type.ts +42 -0
  350. package/authoring/doctypes/types.ts +12 -11
  351. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  352. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  353. package/authoring/gap-report/parse.d.mts +9 -9
  354. package/authoring/gap-report/parse.mjs +6 -6
  355. package/authoring/gap-report/type.ts +1 -1
  356. package/authoring/identity/identity.doc.mjs +3 -2
  357. package/authoring/identity/type.ts +10 -10
  358. package/authoring/index.d.mts +2 -0
  359. package/authoring/index.d.ts +32 -19
  360. package/authoring/index.mjs +3 -1
  361. package/authoring/integration/integration.doc.mjs +2 -2
  362. package/authoring/integration/parse.d.mts +2 -2
  363. package/authoring/integration/parse.mjs +1 -1
  364. package/authoring/integration/schema.d.mts +4 -4
  365. package/authoring/integration/schema.mjs +3 -3
  366. package/authoring/integration/type.ts +5 -11
  367. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  368. package/clients/cli/command-load-failure.test.mjs +83 -0
  369. package/clients/cli/commands/blog.doc.mjs +1 -1
  370. package/clients/cli/commands/blog.mjs +23 -8
  371. package/clients/cli/commands/blog.test.mjs +42 -1
  372. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  373. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  374. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  375. package/clients/cli/commands/build-theme.mjs +16 -50
  376. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  377. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  378. package/clients/cli/commands/build.doc.mjs +16 -8
  379. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  380. package/clients/cli/commands/build.mjs +137 -114
  381. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  382. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  383. package/clients/cli/commands/component/index.mjs +3 -8
  384. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  385. package/clients/cli/commands/component-package.test.mjs +46 -0
  386. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  387. package/clients/cli/commands/component.doc.mjs +1 -1
  388. package/clients/cli/commands/component.test.mjs +19 -0
  389. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  390. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  391. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  392. package/clients/cli/commands/discover.doc.mjs +55 -9
  393. package/clients/cli/commands/discover.mjs +393 -118
  394. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  395. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  396. package/clients/cli/commands/docs.doc.mjs +21 -9
  397. package/clients/cli/commands/docs.mjs +184 -70
  398. package/clients/cli/commands/docs.test.mjs +120 -16
  399. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  400. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  401. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  402. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  403. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  404. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  405. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  406. package/clients/cli/commands/doctor.doc.mjs +1 -1
  407. package/clients/cli/commands/doctor.mjs +59 -32
  408. package/clients/cli/commands/doctor.test.mjs +42 -0
  409. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  410. package/clients/cli/commands/gap-report.test.mjs +72 -0
  411. package/clients/cli/commands/hook/index.mjs +7 -17
  412. package/clients/cli/commands/hook.doc.mjs +1 -1
  413. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  414. package/clients/cli/commands/init.doc.mjs +20 -9
  415. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  416. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  417. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  418. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  419. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  420. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  421. package/clients/cli/commands/integration.doc.mjs +1 -1
  422. package/clients/cli/commands/integration.mjs +1 -0
  423. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  424. package/clients/cli/commands/json-contract.test.mjs +33 -0
  425. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  426. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  427. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  428. package/clients/cli/commands/layout.doc.mjs +3 -3
  429. package/clients/cli/commands/layout.mjs +21 -9
  430. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  431. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  432. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  433. package/clients/cli/commands/manifest.doc.mjs +1 -1
  434. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  435. package/clients/cli/commands/search.doc.mjs +7 -4
  436. package/clients/cli/commands/search.mjs +28 -9
  437. package/clients/cli/commands/search.test.mjs +75 -0
  438. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  439. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  440. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  441. package/clients/cli/commands/template.doc.mjs +52 -13
  442. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  443. package/clients/cli/commands/template.mjs +4 -91
  444. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  445. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  446. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  447. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  448. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  449. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  450. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  451. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  452. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  453. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  454. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  455. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  456. package/clients/cli/commands/theme.doc.mjs +1 -1
  457. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  458. package/clients/cli/commands/upgrade.doc.mjs +20 -8
  459. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  460. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  461. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  462. package/clients/cli/commands/upgrade.mjs +29 -7
  463. package/clients/cli/formatters/index.mjs +2 -0
  464. package/clients/cli/formatters/index.test.mjs +6 -0
  465. package/clients/cli/index.mjs +21 -30
  466. package/clients/cli/latest-version-env.test.mjs +50 -0
  467. package/clients/cli/lib/cli-error.test.mjs +7 -0
  468. package/clients/cli/lib/component-format.mjs +9 -9
  469. package/clients/cli/lib/component-format.test.mjs +1 -1
  470. package/clients/cli/lib/define-command.mjs +32 -6
  471. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  472. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  473. package/clients/cli/lib/hook-format.mjs +19 -10
  474. package/clients/cli/lib/json-shim.mjs +38 -2
  475. package/clients/cli/lib/json-shim.test.mjs +83 -0
  476. package/clients/cli/lib/manifest.d.ts +2 -0
  477. package/clients/cli/lib/manifest.mjs +32 -2
  478. package/clients/cli/lib/manifest.test.mjs +17 -0
  479. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  480. package/foundation/agent-docs/agent-docs.mjs +82 -12
  481. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  482. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  483. package/foundation/config/integration-debug.test.mjs +28 -3
  484. package/foundation/config/project-themes.test.mjs +11 -19
  485. package/foundation/config/project.d.mts +20 -11
  486. package/foundation/config/project.mjs +246 -89
  487. package/foundation/config/project.test.mjs +270 -21
  488. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  489. package/foundation/discovery/authoring-self-docs.mjs +38 -15
  490. package/foundation/discovery/authoring-self-docs.test.mjs +87 -12
  491. package/foundation/discovery/authoring-surface.d.mts +74 -0
  492. package/foundation/discovery/authoring-surface.mjs +525 -0
  493. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  494. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  495. package/foundation/discovery/cli-self-docs.mjs +490 -0
  496. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  497. package/foundation/discovery/component-discovery.d.mts +38 -0
  498. package/foundation/discovery/component-discovery.mjs +48 -0
  499. package/foundation/discovery/component-loader.d.mts +35 -38
  500. package/foundation/discovery/component-loader.mjs +53 -222
  501. package/foundation/discovery/docs-discovery.d.mts +114 -9
  502. package/foundation/discovery/docs-discovery.mjs +239 -30
  503. package/foundation/discovery/docs-discovery.test.mjs +150 -35
  504. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  505. package/foundation/discovery/docs-output-budget.mjs +1 -1
  506. package/foundation/discovery/docs-section-key.d.mts +28 -10
  507. package/foundation/discovery/docs-section-key.mjs +134 -33
  508. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  509. package/foundation/discovery/template-adapter.d.mts +113 -11
  510. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  511. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  512. package/foundation/discovery/template-adapter.mjs +772 -82
  513. package/foundation/discovery/template-adapter.test.mjs +57 -0
  514. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  515. package/foundation/discovery/template-conflict-release.mjs +40 -0
  516. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  517. package/foundation/discovery/theme-discovery.d.mts +67 -7
  518. package/foundation/discovery/theme-discovery.mjs +916 -186
  519. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  520. package/foundation/discovery/theming-targets.test.mjs +4 -0
  521. package/foundation/doc-compiler/bundle.d.mts +47 -0
  522. package/foundation/doc-compiler/bundle.mjs +278 -0
  523. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  524. package/foundation/doc-compiler/compile.d.mts +343 -0
  525. package/foundation/doc-compiler/compile.mjs +558 -0
  526. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  527. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  528. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  529. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  530. package/foundation/doc-compiler/import.d.mts +24 -0
  531. package/foundation/doc-compiler/import.mjs +59 -0
  532. package/foundation/doc-compiler/inputs.d.mts +102 -0
  533. package/foundation/doc-compiler/inputs.mjs +291 -0
  534. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  535. package/foundation/doc-compiler/ir.d.mts +22 -0
  536. package/foundation/doc-compiler/ir.mjs +471 -0
  537. package/foundation/doc-compiler/lenses.d.mts +36 -0
  538. package/foundation/doc-compiler/lenses.mjs +173 -0
  539. package/foundation/doc-compiler/links.d.mts +162 -0
  540. package/foundation/doc-compiler/links.mjs +294 -0
  541. package/foundation/doc-compiler/links.test.mjs +192 -0
  542. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  543. package/foundation/doc-compiler/overlays.d.mts +37 -0
  544. package/foundation/doc-compiler/overlays.mjs +206 -0
  545. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  546. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  547. package/foundation/doc-compiler/read.d.mts +127 -0
  548. package/foundation/doc-compiler/read.mjs +325 -0
  549. package/foundation/doc-compiler/read.test.mjs +313 -0
  550. package/foundation/doc-compiler/source.d.mts +33 -0
  551. package/foundation/doc-compiler/source.mjs +128 -0
  552. package/foundation/doc-compiler/tree.d.mts +288 -0
  553. package/foundation/doc-compiler/tree.mjs +876 -0
  554. package/foundation/doc-compiler/tree.test.mjs +598 -0
  555. package/foundation/fs/file-protection.d.mts +33 -0
  556. package/foundation/fs/file-protection.mjs +825 -0
  557. package/foundation/fs/file-protection.test.mjs +250 -0
  558. package/foundation/fs/module-loader.d.mts +1 -0
  559. package/foundation/fs/module-loader.mjs +50 -1
  560. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  561. package/foundation/fs/path-safety.d.mts +3 -2
  562. package/foundation/fs/path-safety.mjs +49 -19
  563. package/foundation/fs/path-safety.test.mjs +50 -0
  564. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  565. package/foundation/integrations/autolink.d.mts +58 -1
  566. package/foundation/integrations/autolink.mjs +143 -52
  567. package/foundation/integrations/autolink.test.mjs +1 -1
  568. package/foundation/integrations/cli-requirement.d.mts +45 -0
  569. package/foundation/integrations/cli-requirement.mjs +154 -0
  570. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  571. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  572. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  573. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  574. package/foundation/integrations/contribution-inventory.mjs +27 -24
  575. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  576. package/foundation/integrations/integration-warnings.d.mts +9 -2
  577. package/foundation/integrations/integration-warnings.mjs +51 -26
  578. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  579. package/foundation/integrations/integrations.d.mts +17 -1
  580. package/foundation/integrations/integrations.mjs +52 -98
  581. package/foundation/integrations/integrations.test.mjs +31 -0
  582. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  583. package/foundation/integrations/provider-resolution.d.mts +152 -0
  584. package/foundation/integrations/provider-resolution.mjs +576 -0
  585. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  586. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  587. package/foundation/integrations/theme-descriptor.mjs +44 -0
  588. package/foundation/integrations/validate-contributions.mjs +121 -29
  589. package/foundation/response/base.d.ts +8 -4
  590. package/foundation/response/error-codes.d.mts +3 -1
  591. package/foundation/response/error-codes.d.ts +2 -0
  592. package/foundation/response/error-codes.doc.mjs +13 -4
  593. package/foundation/response/error-codes.mjs +8 -2
  594. package/foundation/response/error-codes.test.mjs +137 -10
  595. package/foundation/response/json-contract.test.mjs +11 -0
  596. package/foundation/response/json.d.mts +4 -2
  597. package/foundation/response/json.mjs +8 -10
  598. package/foundation/response/response-types.doc.d.mts +5 -1
  599. package/foundation/response/response-types.doc.mjs +37 -22
  600. package/foundation/response/response-types.doc.test.mjs +158 -0
  601. package/foundation/response/response.doc.mjs +1 -1
  602. package/foundation/text/string-utils.d.mts +8 -0
  603. package/foundation/text/string-utils.mjs +40 -10
  604. package/foundation/xle/expand.d.mts +2 -0
  605. package/foundation/xle/expand.mjs +4 -3
  606. package/foundation/xle/expand.test.mjs +54 -0
  607. package/foundation/xle/xle.test.mjs +13 -0
  608. package/package.json +10 -11
  609. package/assets/templates/themes/manifest.json +0 -95
  610. package/clients/cli/lib/update-check.mjs +0 -83
  611. package/clients/cli/lib/update-check.test.mjs +0 -137
  612. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -4,17 +4,17 @@
4
4
  * @file Colocated types for the `upgrade` command — source of truth for the
5
5
  * upgrade command JSON responses. Re-exported by `types/upgrade.d.ts`.
6
6
  *
7
- * Invocation -> type discriminator
7
+ * Invocation -> type discriminator
8
8
  * ------------------------------------------------------------------
9
- * xds --json upgrade --list -> upgrade.list
10
- * xds --json upgrade [--apply] -> upgrade.run
11
- * xds --json upgrade --registry [--apply] -> upgrade.registry
12
- * xds --json upgrade (status short-circuit) -> upgrade.status
13
- * (version detection failure) -> CLIError
9
+ * astryx --json upgrade --list -> upgrade.list
10
+ * astryx --json upgrade [--apply] -> upgrade.run
11
+ * astryx --json upgrade --registry [--apply] -> upgrade.registry
12
+ * astryx --json upgrade (status short-circuit) -> upgrade.status
13
+ * (version detection failure) -> CLIError
14
14
  */
15
15
 
16
16
  /**
17
- * xds --json upgrade --list
17
+ * astryx --json upgrade --list
18
18
  * @typedef {object} UpgradeListResponse
19
19
  * @property {'upgrade.list'} type
20
20
  * @property {UpgradeListEntry[]} data
@@ -25,6 +25,7 @@
25
25
  * @property {string} name
26
26
  * @property {string} title
27
27
  * @property {string} version
28
+ * @property {boolean} optional True when the codemod runs only if named with `--codemod`.
28
29
  */
29
30
 
30
31
  /**
@@ -88,14 +89,24 @@
88
89
  */
89
90
 
90
91
  /**
91
- * xds --json upgrade --registry [--apply]
92
+ * astryx --json upgrade --registry [--apply]
92
93
  * @typedef {object} UpgradeRegistryResponse
93
94
  * @property {'upgrade.registry'} type
94
95
  * @property {RegistryCompositionSummary} data
95
96
  */
96
97
 
97
98
  /**
98
- * xds --json upgrade [--apply]
99
+ * A required codemod change blocked by effective working-tree protection.
100
+ * @typedef {object} ProtectedCodemodFile
101
+ * @property {string} file Project-relative path.
102
+ * @property {string[]} codemods Codemods that still require a change.
103
+ * @property {string[]} reasons Protection categories (generated, vendored, ignored, and hard boundaries).
104
+ * @property {string[]} declarations Effective declarations that protect the file.
105
+ * @property {string[]} commands Exact regeneration commands found in generated headers, when present.
106
+ */
107
+
108
+ /**
109
+ * astryx --json upgrade [--apply]
99
110
  * @typedef {object} UpgradeRunResponse
100
111
  * @property {'upgrade.run'} type
101
112
  * @property {object} data
@@ -106,13 +117,18 @@
106
117
  * @property {boolean} data.agentDocsRefreshed
107
118
  * @property {AgentDocsSummary} data.agentDocs
108
119
  * @property {RegistryCompositionSummary} [data.registryCompositions]
120
+ * @property {boolean} [data.complete] False when protected required changes remain.
121
+ * @property {'ERR_CODEMOD_PROTECTED'} [data.errorCode] Stable incomplete-result code when complete is false.
109
122
  * @property {number} [data.filesChanged] Total files changed across core + integration codemods (apply mode).
123
+ * @property {string[]} [data.modifiedFiles] Project-relative files changed or previewed.
124
+ * @property {ProtectedCodemodFile[]} [data.protectedFiles] Protected files that still require a codemod change after regeneration.
125
+ * @property {Array<{file: string, location?: string, reason: string}>} [data.declinedCandidates] Candidates left unchanged because proof was insufficient.
110
126
  * @property {number} [data.transformsApplied] Total transforms that reported a change.
111
127
  * @property {Array<{file: string, codemod: string, error: string}>} [data.errors] Per-codemod errors, when any codemod failed.
112
128
  */
113
129
 
114
130
  /**
115
- * xds --json upgrade — short-circuit status results.
131
+ * astryx --json upgrade — short-circuit status results.
116
132
  *
117
133
  * - `up_to_date`: `--from` is >= installed target and `--force` was not passed.
118
134
  * - `no_codemods`: no codemods (core or integration) apply to the range.
@@ -21,6 +21,40 @@ afterEach(() => {
21
21
  fs.rmSync(tmpDir, {recursive: true, force: true});
22
22
  });
23
23
 
24
+ describe('runCodemods — ordered dry-run state', () => {
25
+ it('feeds each previewed code transform into the next transform', async () => {
26
+ const srcDir = path.join(tmpDir, 'src');
27
+ fs.mkdirSync(srcDir);
28
+ fs.writeFileSync(path.join(srcDir, 'a.ts'), 'const value = "a";\n');
29
+ const transforms = [
30
+ {
31
+ name: 'a-to-b',
32
+ meta: {title: 'a to b'},
33
+ transform: file => file.source.replace('"a"', '"b"'),
34
+ },
35
+ {
36
+ name: 'b-to-c',
37
+ meta: {title: 'b to c'},
38
+ transform: file => file.source.replace('"b"', '"c"'),
39
+ },
40
+ ];
41
+
42
+ const preview = await runCodemods([{version: '1.0.0', transforms}], {
43
+ apply: false,
44
+ path: srcDir,
45
+ root: tmpDir,
46
+ silent: true,
47
+ });
48
+
49
+ expect(preview.totalFilesChanged).toBe(2);
50
+ expect(preview.changedFiles).toEqual([
51
+ path.join(srcDir, 'a.ts'),
52
+ path.join(srcDir, 'a.ts'),
53
+ ]);
54
+ expect(fs.readFileSync(path.join(srcDir, 'a.ts'), 'utf8')).toContain('"a"');
55
+ });
56
+ });
57
+
24
58
  describe('runCodemods — unified config codemod path', () => {
25
59
  it('routes a core config codemod through the (file, api) runner to edit astryx.config.*', async () => {
26
60
  fs.writeFileSync(
@@ -195,17 +229,219 @@ describe('runCodemods — unified config codemod path', () => {
195
229
  });
196
230
  });
197
231
 
198
- describe('findSourceFiles — scan boundaries (symlink + build dirs)', () => {
232
+ describe('runCodemods — project plans honor existing-file protection', () => {
233
+ it('applies new and owned writes while blocking protected replacements and deletes', async () => {
234
+ fs.writeFileSync(
235
+ path.join(tmpDir, '.gitattributes'),
236
+ 'generated/** linguist-generated=true\n',
237
+ );
238
+ fs.mkdirSync(path.join(tmpDir, 'generated'), {recursive: true});
239
+ fs.writeFileSync(path.join(tmpDir, 'generated', 'replace.ts'), 'old\n');
240
+ fs.writeFileSync(path.join(tmpDir, 'generated', 'remove.ts'), 'old\n');
241
+ fs.writeFileSync(path.join(tmpDir, 'owned.ts'), 'old\n');
242
+
243
+ const manifests = [
244
+ {
245
+ version: '1.0.0',
246
+ transforms: [
247
+ {
248
+ name: 'project-plan',
249
+ meta: {title: 'project plan', codemodType: 'project'},
250
+ transform: async root => ({
251
+ writes: [
252
+ {
253
+ path: path.join(root, 'generated', 'replace.ts'),
254
+ contents: 'new\n',
255
+ },
256
+ {path: path.join(root, 'owned.ts'), contents: 'new\n'},
257
+ {path: path.join(root, 'created.ts'), contents: 'new\n'},
258
+ ],
259
+ deletes: [path.join(root, 'generated', 'remove.ts')],
260
+ problems: [],
261
+ }),
262
+ },
263
+ ],
264
+ },
265
+ ];
266
+
267
+ const result = await runCodemods(manifests, {
268
+ apply: true,
269
+ path: './missing',
270
+ root: tmpDir,
271
+ silent: true,
272
+ });
273
+
274
+ expect(
275
+ fs.readFileSync(path.join(tmpDir, 'generated', 'replace.ts'), 'utf8'),
276
+ ).toBe('old\n');
277
+ expect(fs.existsSync(path.join(tmpDir, 'generated', 'remove.ts'))).toBe(
278
+ true,
279
+ );
280
+ expect(fs.readFileSync(path.join(tmpDir, 'owned.ts'), 'utf8')).toBe(
281
+ 'new\n',
282
+ );
283
+ expect(fs.readFileSync(path.join(tmpDir, 'created.ts'), 'utf8')).toBe(
284
+ 'new\n',
285
+ );
286
+ expect(result.totalFilesChanged).toBe(2);
287
+ expect(result.protectedFiles.map(item => item.file).sort()).toEqual([
288
+ 'generated/remove.ts',
289
+ 'generated/replace.ts',
290
+ ]);
291
+ });
292
+
293
+ it('blocks an existing file protected by a declaration in the same plan', async () => {
294
+ fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
295
+ fs.writeFileSync(path.join(tmpDir, 'src', 'out.ts'), 'old\n');
296
+ const manifests = [
297
+ {
298
+ version: '1.0.0',
299
+ transforms: [
300
+ {
301
+ name: 'declare-and-replace',
302
+ meta: {title: 'declare and replace', codemodType: 'project'},
303
+ transform: async root => ({
304
+ writes: [
305
+ {
306
+ path: path.join(root, '.gitattributes'),
307
+ contents: 'src/out.ts linguist-generated\n',
308
+ },
309
+ {path: path.join(root, 'src', 'out.ts'), contents: 'new\n'},
310
+ ],
311
+ deletes: [],
312
+ problems: [],
313
+ }),
314
+ },
315
+ ],
316
+ },
317
+ ];
318
+
319
+ const result = await runCodemods(manifests, {
320
+ apply: true,
321
+ path: './missing',
322
+ root: tmpDir,
323
+ silent: true,
324
+ });
325
+
326
+ expect(fs.readFileSync(path.join(tmpDir, 'src', 'out.ts'), 'utf8')).toBe(
327
+ 'old\n',
328
+ );
329
+ expect(fs.readFileSync(path.join(tmpDir, '.gitattributes'), 'utf8')).toBe(
330
+ 'src/out.ts linguist-generated\n',
331
+ );
332
+ expect(result.protectedFiles).toEqual([
333
+ expect.objectContaining({
334
+ file: 'src/out.ts',
335
+ declaration: 'linguist-generated in .gitattributes:1',
336
+ }),
337
+ ]);
338
+ });
339
+
340
+ it('does not apply rules from a blocked staged declaration', async () => {
341
+ fs.writeFileSync(
342
+ path.join(tmpDir, '.gitattributes'),
343
+ '.gitattributes linguist-generated\n',
344
+ );
345
+ fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
346
+ fs.writeFileSync(path.join(tmpDir, 'src', 'out.ts'), 'old\n');
347
+ const result = await runCodemods(
348
+ [
349
+ {
350
+ version: '1.0.0',
351
+ transforms: [
352
+ {
353
+ name: 'blocked-declaration',
354
+ meta: {title: 'blocked declaration', codemodType: 'project'},
355
+ transform: async root => ({
356
+ writes: [
357
+ {
358
+ path: path.join(root, '.gitattributes'),
359
+ contents: 'src/out.ts linguist-generated\n',
360
+ },
361
+ {path: path.join(root, 'src', 'out.ts'), contents: 'new\n'},
362
+ ],
363
+ deletes: [],
364
+ problems: [],
365
+ }),
366
+ },
367
+ ],
368
+ },
369
+ ],
370
+ {apply: true, path: './missing', root: tmpDir, silent: true},
371
+ );
372
+
373
+ expect(fs.readFileSync(path.join(tmpDir, 'src', 'out.ts'), 'utf8')).toBe(
374
+ 'new\n',
375
+ );
376
+ expect(result.protectedFiles).toEqual([
377
+ expect.objectContaining({file: '.gitattributes'}),
378
+ ]);
379
+ });
380
+
381
+ it('refreshes declarations written by an earlier project codemod before later writes', async () => {
382
+ fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
383
+ fs.writeFileSync(path.join(tmpDir, 'src', 'out.ts'), 'const foo = 1;\n');
384
+ const manifests = [
385
+ {
386
+ version: '1.0.0',
387
+ transforms: [
388
+ {
389
+ name: 'declare-generated',
390
+ meta: {title: 'declare generated', codemodType: 'project'},
391
+ transform: async root => ({
392
+ writes: [
393
+ {
394
+ path: path.join(root, '.gitattributes'),
395
+ contents: 'src/out.ts linguist-generated=true\n',
396
+ },
397
+ ],
398
+ deletes: [],
399
+ problems: [],
400
+ }),
401
+ },
402
+ {
403
+ name: 'rename-after-declaration',
404
+ meta: {title: 'rename after declaration'},
405
+ transform: file => file.source.replace('foo', 'bar'),
406
+ },
407
+ ],
408
+ },
409
+ ];
410
+
411
+ const result = await runCodemods(manifests, {
412
+ apply: true,
413
+ path: path.join(tmpDir, 'src'),
414
+ root: tmpDir,
415
+ silent: true,
416
+ });
417
+
418
+ expect(
419
+ fs.readFileSync(path.join(tmpDir, 'src', 'out.ts'), 'utf8'),
420
+ ).toContain('foo');
421
+ expect(result.protectedFiles).toEqual([
422
+ expect.objectContaining({
423
+ file: 'src/out.ts',
424
+ declaration: 'linguist-generated in .gitattributes:1',
425
+ }),
426
+ ]);
427
+ });
428
+ });
429
+
430
+ describe('findSourceFiles — scan boundaries (symlink + declared protection)', () => {
199
431
  const manifests = [
200
432
  {
201
433
  version: '0.1.3',
202
434
  transforms: [
203
- {name: 'p', meta: {title: 'p'}, transform: f => f.source.replace(/foo/g, 'bar')},
435
+ {
436
+ name: 'p',
437
+ meta: {title: 'p'},
438
+ transform: f => f.source.replace(/foo/g, 'bar'),
439
+ },
204
440
  ],
205
441
  },
206
442
  ];
207
443
 
208
- it('does not follow a symlinked file out of the scan tree', async () => {
444
+ it('reports a symlinked file without writing through it', async () => {
209
445
  const outside = path.join(tmpDir, 'outside');
210
446
  fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
211
447
  fs.mkdirSync(outside, {recursive: true});
@@ -214,13 +450,45 @@ describe('findSourceFiles — scan boundaries (symlink + build dirs)', () => {
214
450
  fs.writeFileSync(path.join(tmpDir, 'src', 'real.ts'), 'const foo = 2;\n');
215
451
  fs.symlinkSync(secret, path.join(tmpDir, 'src', 'link.ts'));
216
452
 
217
- const r = await runCodemods(manifests, {apply: true, path: './src', silent: true});
453
+ const r = await runCodemods(manifests, {
454
+ apply: true,
455
+ path: './src',
456
+ silent: true,
457
+ });
218
458
  // the symlink target (outside the tree) must be untouched
219
459
  expect(fs.readFileSync(secret, 'utf-8')).toBe('const foo = 1;\n');
220
460
  expect(r.writtenFiles.map(f => path.basename(f))).toEqual(['real.ts']);
461
+ expect(r.protectedFiles).toEqual([
462
+ expect.objectContaining({file: 'src/link.ts', reason: 'symlink'}),
463
+ ]);
221
464
  });
222
465
 
223
- it('does not scan generated-output dirs (dist/build/out)', async () => {
466
+ it('reports matching descendants of a symlinked directory without writing through it', async () => {
467
+ const targetDir = path.join(tmpDir, 'target');
468
+ const srcDir = path.join(tmpDir, 'src');
469
+ fs.mkdirSync(targetDir, {recursive: true});
470
+ fs.mkdirSync(srcDir, {recursive: true});
471
+ const target = path.join(targetDir, 'nested.ts');
472
+ fs.writeFileSync(target, 'const foo = 1;\n');
473
+ fs.symlinkSync(targetDir, path.join(srcDir, 'linked'));
474
+
475
+ const result = await runCodemods(manifests, {
476
+ apply: true,
477
+ path: srcDir,
478
+ root: tmpDir,
479
+ silent: true,
480
+ });
481
+
482
+ expect(fs.readFileSync(target, 'utf8')).toContain('foo');
483
+ expect(result.protectedFiles).toEqual([
484
+ expect.objectContaining({
485
+ file: 'src/linked/nested.ts',
486
+ reason: 'symlink',
487
+ }),
488
+ ]);
489
+ });
490
+
491
+ it('does not infer protection from generated-looking directory names', async () => {
224
492
  fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
225
493
  fs.mkdirSync(path.join(tmpDir, 'dist'), {recursive: true});
226
494
  fs.mkdirSync(path.join(tmpDir, 'build'), {recursive: true});
@@ -228,8 +496,62 @@ describe('findSourceFiles — scan boundaries (symlink + build dirs)', () => {
228
496
  fs.writeFileSync(path.join(tmpDir, 'dist', 'b.js'), 'const foo = 2;\n');
229
497
  fs.writeFileSync(path.join(tmpDir, 'build', 'c.js'), 'const foo = 3;\n');
230
498
 
231
- const r = await runCodemods(manifests, {apply: true, path: '.', silent: true});
232
- expect(r.writtenFiles.map(f => path.basename(f))).toEqual(['a.ts']);
233
- expect(fs.readFileSync(path.join(tmpDir, 'dist', 'b.js'), 'utf-8')).toContain('foo');
499
+ const r = await runCodemods(manifests, {
500
+ apply: true,
501
+ path: '.',
502
+ silent: true,
503
+ });
504
+ expect(r.writtenFiles.map(f => path.basename(f)).sort()).toEqual([
505
+ 'a.ts',
506
+ 'b.js',
507
+ 'c.js',
508
+ ]);
509
+ });
510
+
511
+ it('changes owned files but reports generated files without writing them', async () => {
512
+ fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
513
+ fs.mkdirSync(path.join(tmpDir, 'dist'), {recursive: true});
514
+ fs.writeFileSync(
515
+ path.join(tmpDir, '.gitattributes'),
516
+ 'dist/** linguist-generated=true\n',
517
+ );
518
+ fs.writeFileSync(path.join(tmpDir, 'src', 'owned.ts'), 'const foo = 1;\n');
519
+ fs.writeFileSync(
520
+ path.join(tmpDir, 'dist', 'output.js'),
521
+ 'const foo = 2;\n',
522
+ );
523
+
524
+ const r = await runCodemods(manifests, {
525
+ apply: true,
526
+ path: '.',
527
+ silent: true,
528
+ });
529
+
530
+ expect(
531
+ fs.readFileSync(path.join(tmpDir, 'src', 'owned.ts'), 'utf-8'),
532
+ ).toContain('bar');
533
+ expect(
534
+ fs.readFileSync(path.join(tmpDir, 'dist', 'output.js'), 'utf-8'),
535
+ ).toContain('foo');
536
+ expect(r.protectedFiles).toEqual([
537
+ expect.objectContaining({
538
+ file: 'dist/output.js',
539
+ reason: 'generated',
540
+ declaration: 'linguist-generated in .gitattributes:1',
541
+ }),
542
+ ]);
543
+ });
544
+
545
+ it('fails closed before an owned write when a declaration is malformed', async () => {
546
+ fs.mkdirSync(path.join(tmpDir, 'src'), {recursive: true});
547
+ fs.writeFileSync(path.join(tmpDir, 'src', 'owned.ts'), 'const foo = 1;\n');
548
+ fs.writeFileSync(path.join(tmpDir, '.hgignore'), 'syntax: regexp\n[bad\n');
549
+
550
+ await expect(
551
+ runCodemods(manifests, {apply: true, path: '.', silent: true}),
552
+ ).rejects.toThrow(/file-protection source \.hgignore/);
553
+ expect(
554
+ fs.readFileSync(path.join(tmpDir, 'src', 'owned.ts'), 'utf-8'),
555
+ ).toContain('foo');
234
556
  });
235
557
  });
@@ -32,6 +32,40 @@ import {semverCompare} from '../../foundation/env/semver.mjs';
32
32
  /** File extensions recognized as codemod modules. */
33
33
  const CODEMOD_EXTENSIONS = ['.ts', '.mjs', '.js'];
34
34
 
35
+ /**
36
+ * Directories never walked for codemods: a test directory beside a transform is
37
+ * the natural place to put its test, and every file found here is loaded and
38
+ * validated as a codemod.
39
+ */
40
+ const SKIP_DIRS = new Set([
41
+ 'node_modules',
42
+ '.git',
43
+ '__tests__',
44
+ '__fixtures__',
45
+ ]);
46
+
47
+ /**
48
+ * Whether a file name is a test or fixture rather than a codemod.
49
+ *
50
+ * The trap this closes: EVERY `.ts`/`.mjs`/`.js` under a version folder used to
51
+ * be loaded as a codemod, so a test file colocated with its transform failed
52
+ * validation and — because a definition error is a hard error — took every
53
+ * codemod in that package's version with it. `astryx upgrade` then applied no
54
+ * transforms and reported success, which is the worst shape a failure can take.
55
+ *
56
+ * Core's own codemods never hit this: they are enumerated in a registry, and
57
+ * their colocated tests are simply not in it. Only integrations are discovered
58
+ * by walking a directory, so only integrations carry the landmine — which is why
59
+ * this is a loader fix and not a documentation one. It protects the integrations
60
+ * that already exist, which no authoring tool can reach.
61
+ *
62
+ * @param {string} name a file's base name
63
+ * @returns {boolean}
64
+ */
65
+ function isTestFile(name) {
66
+ return /\.(test|spec)\.[^.]+$/.test(name) || /\.fixture\.[^.]+$/.test(name);
67
+ }
68
+
35
69
  /**
36
70
  * Recursively collect codemod module files under a version folder. Returns
37
71
  * entries of {id, file} where id is the extension-less relative path
@@ -49,14 +83,18 @@ function collectCodemodFiles(versionDir) {
49
83
  for (const entry of entries) {
50
84
  const full = path.join(dir, entry.name);
51
85
  if (entry.isDirectory()) {
52
- if (entry.name === 'node_modules' || entry.name === '.git') continue;
86
+ if (SKIP_DIRS.has(entry.name)) continue;
53
87
  walk(full);
54
88
  continue;
55
89
  }
56
90
  const ext = path.extname(entry.name);
57
91
  if (!CODEMOD_EXTENSIONS.includes(ext)) continue;
92
+ if (isTestFile(entry.name)) continue;
58
93
  const rel = path.relative(versionDir, full);
59
- const id = rel.slice(0, rel.length - ext.length).split(path.sep).join('/');
94
+ const id = rel
95
+ .slice(0, rel.length - ext.length)
96
+ .split(path.sep)
97
+ .join('/');
60
98
  out.push({id, file: full});
61
99
  }
62
100
  }
@@ -68,7 +106,7 @@ function collectCodemodFiles(versionDir) {
68
106
  /**
69
107
  * Discover file-based codemods contributed by configured integrations.
70
108
  *
71
- * @param {Array<{name?: string, codemods?: string, __spec?: string}>} loadedIntegrations
109
+ * @param {Array<{name?: string, codemods?: string, __spec?: string, __packageDir?: string}>} loadedIntegrations
72
110
  * @returns {Promise<Map<string, Array<{id: string, type: 'code'|'config', codemod: object, package: string}>>>}
73
111
  * Map keyed by version string; each value is the list of discovered codemods
74
112
  * for that version (across all integrations).
@@ -107,7 +145,13 @@ export async function discoverIntegrationCodemods(loadedIntegrations = []) {
107
145
  const seenInVersion = new Set();
108
146
 
109
147
  for (const {id, file} of files) {
110
- const label = `Integration "${pkgLabel}" codemod ${version}/${id} (${file})`;
148
+ const shown = integration.__packageDir
149
+ ? path
150
+ .relative(integration.__packageDir, file)
151
+ .split(path.sep)
152
+ .join('/')
153
+ : file;
154
+ const label = `Integration "${pkgLabel}" codemod ${version}/${id} (${shown})`;
111
155
 
112
156
  if (seenInVersion.has(id)) {
113
157
  throw new Error(
@@ -163,6 +163,21 @@ describe('integration codemod discovery', () => {
163
163
  ).rejects.toThrow(/is invalid/i);
164
164
  });
165
165
 
166
+ it('names a broken codemod by its path inside the package', async () => {
167
+ scaffold({
168
+ '1.1.0/no-default.mjs': `export const nope = 1;\n`,
169
+ });
170
+ const project = await Project.load(tmpDir);
171
+ const failure = await discoverIntegrationCodemods(
172
+ project.loadedIntegrations,
173
+ ).then(
174
+ () => null,
175
+ error => error,
176
+ );
177
+ expect(failure?.message).toContain('(codemods/1.1.0/no-default.mjs)');
178
+ expect(failure?.message).not.toContain(tmpDir);
179
+ });
180
+
166
181
  it('fails discovery when default export is not a codemod envelope', async () => {
167
182
  scaffold({
168
183
  '0.2.0/bad.mjs': `export default { title: 'x', transform: () => null };\n`,
@@ -221,3 +236,61 @@ describe('integration codemod discovery', () => {
221
236
  ).rejects.toThrow(/across versions/i);
222
237
  });
223
238
  });
239
+
240
+ describe('test files beside a codemod', () => {
241
+ // The incident this closes: every .ts/.mjs/.js under a version folder was
242
+ // loaded AND VALIDATED as a codemod, so a test file colocated with its
243
+ // transform failed validation — and because a definition error is a hard
244
+ // error, it took every codemod in that version with it. `astryx upgrade`
245
+ // then applied nothing and reported success. Core is immune because its own
246
+ // codemods are enumerated in a registry rather than discovered by walking a
247
+ // directory, so its colocated tests are simply never visited. Only
248
+ // integrations carry the landmine.
249
+ const TRANSFORM = `
250
+ export default {
251
+ type: 'code',
252
+ title: 'Drop foo',
253
+ transform: (file) => file.source.replace(/foo/g, 'bar'),
254
+ };
255
+ `;
256
+ // Not a codemod: no default export of the right shape. Loading it throws.
257
+ const A_TEST = `
258
+ import {describe, it, expect} from 'vitest';
259
+ describe('drop-foo', () => {
260
+ it('drops foo', () => expect(1).toBe(1));
261
+ });
262
+ `;
263
+
264
+ it.each([
265
+ ['a .test. sibling', '0.2.0/drop-foo.test.mjs'],
266
+ ['a .spec. sibling', '0.2.0/drop-foo.spec.mjs'],
267
+ ['a fixture sibling', '0.2.0/drop-foo.fixture.mjs'],
268
+ ['a __tests__ directory', '0.2.0/__tests__/drop-foo.mjs'],
269
+ ['a __fixtures__ directory', '0.2.0/__fixtures__/input.mjs'],
270
+ ])('ignores %s and still discovers the codemod', async (_label, testPath) => {
271
+ scaffold({'0.2.0/drop-foo.mjs': TRANSFORM, [testPath]: A_TEST});
272
+
273
+ const project = await Project.load(tmpDir);
274
+ const byVersion = await discoverIntegrationCodemods(
275
+ project.loadedIntegrations,
276
+ );
277
+
278
+ expect([...byVersion.keys()]).toEqual(['0.2.0']);
279
+ expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual(['drop-foo']);
280
+ });
281
+
282
+ it('a nested helper directory is still walked', async () => {
283
+ // Only test and fixture names are skipped. A package that organises its
284
+ // transforms into subdirectories keeps working.
285
+ scaffold({'0.2.0/imports/drop-foo.mjs': TRANSFORM});
286
+
287
+ const project = await Project.load(tmpDir);
288
+ const byVersion = await discoverIntegrationCodemods(
289
+ project.loadedIntegrations,
290
+ );
291
+
292
+ expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual([
293
+ 'imports/drop-foo',
294
+ ]);
295
+ });
296
+ });