@astryxdesign/cli 0.1.7 → 0.1.8-canary.07362a9

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 (389) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +115 -19
  3. package/{src/api → api/blog}/blog.mjs +42 -6
  4. package/{src/api → api/blog}/blog.test.mjs +2 -2
  5. package/api/build/build.mjs +92 -0
  6. package/api/build/build.test.mjs +92 -0
  7. package/{src/api → api/component}/component.mjs +49 -26
  8. package/{src/api → api/discover}/discover.mjs +55 -18
  9. package/{src/api → api/docs}/docs.mjs +47 -21
  10. package/{src/api → api/doctor}/doctor.mjs +13 -10
  11. package/{src/api → api}/error.mjs +2 -2
  12. package/{src/api → api/hook}/hook.mjs +11 -11
  13. package/{src/api → api}/index.mjs +16 -9
  14. package/{src/api → api/integration}/validate-integration.mjs +48 -15
  15. package/{src/api → api/integration}/validate-integration.test.mjs +1 -1
  16. package/{src/api → api/layout}/layout.mjs +66 -17
  17. package/{src/api → api/layout}/layout.test.mjs +1 -1
  18. package/{src/api → api/search}/search.mjs +71 -12
  19. package/api/swizzle/swizzle.mjs +283 -0
  20. package/{src/commands → api/swizzle}/swizzle.test.mjs +26 -1
  21. package/{src/api → api/template}/template-integration.test.mjs +2 -2
  22. package/{src/api → api/template}/template-suffix.test.mjs +3 -3
  23. package/{src/api → api/template}/template.mjs +96 -19
  24. package/{src/api → api/theme}/theme-add.mjs +35 -7
  25. package/{src → authoring}/codemod.mjs +6 -6
  26. package/{src → authoring}/config.test.mjs +1 -1
  27. package/{src → authoring}/doc.mjs +1 -1
  28. package/{src → authoring}/doc.test.mjs +1 -1
  29. package/{src → authoring}/template.mjs +1 -1
  30. package/bin/astryx.mjs +12 -10
  31. package/{src → cli}/commands/blog.mjs +48 -7
  32. package/{src → cli}/commands/build-theme.mjs +133 -115
  33. package/cli/commands/build.mjs +172 -0
  34. package/cli/commands/cli-postinstall.test.mjs +42 -0
  35. package/{src → cli}/commands/component/index.mjs +52 -25
  36. package/{src → cli}/commands/component-ownership.test.mjs +3 -3
  37. package/{src → cli}/commands/component-package.test.mjs +1 -1
  38. package/{src → cli}/commands/component-resolution.test.mjs +2 -2
  39. package/{src → cli}/commands/discover.mjs +23 -12
  40. package/{src → cli}/commands/docs.mjs +42 -10
  41. package/{src → cli}/commands/docs.test.mjs +1 -1
  42. package/{src → cli}/commands/doctor.mjs +3 -3
  43. package/{src → cli}/commands/doctor.test.mjs +2 -2
  44. package/{src → cli}/commands/ensure-core-built.mjs +3 -2
  45. package/{src → cli}/commands/external-showcase.test.mjs +1 -1
  46. package/{src → cli}/commands/hook/index.mjs +40 -17
  47. package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
  48. package/cli/commands/init.mjs +195 -0
  49. package/{src → cli}/commands/init.next-steps.test.mjs +1 -1
  50. package/cli/commands/interactive-guard.test.mjs +66 -0
  51. package/{src → cli}/commands/json-contract.test.mjs +2 -2
  52. package/{src → cli}/commands/layout.mjs +59 -19
  53. package/{src → cli}/commands/search.mjs +22 -15
  54. package/{src → cli}/commands/search.test.mjs +1 -1
  55. package/cli/commands/setup-nudge.test.mjs +108 -0
  56. package/cli/commands/swizzle.mjs +103 -0
  57. package/{src → cli}/commands/template.mjs +84 -53
  58. package/{src → cli}/commands/template.path-safety.test.mjs +2 -2
  59. package/{src → cli}/commands/upgrade.integration-policy.test.mjs +1 -1
  60. package/{src → cli}/commands/upgrade.mjs +291 -77
  61. package/cli/commands/upgrade.test.mjs +314 -0
  62. package/{src → cli}/commands/validate-integration.mjs +17 -37
  63. package/{src → cli}/index.mjs +55 -19
  64. package/{src/codemods → codemods}/__tests__/registry.test.mjs +1 -0
  65. package/{src/codemods → codemods}/ensure-jscodeshift.mjs +12 -28
  66. package/{src/codemods → codemods}/integration-discovery.mjs +6 -3
  67. package/{src/codemods → codemods}/integration-discovery.test.mjs +1 -1
  68. package/{src/codemods → codemods}/integration-runner.mjs +8 -3
  69. package/{src/codemods → codemods}/registry.mjs +4 -1
  70. package/{src/codemods → codemods}/run-codemod.mjs +18 -11
  71. package/{src/codemods → codemods}/runner.mjs +24 -14
  72. package/{src/codemods → codemods}/transforms/v0.0.10/remove-size-props.mjs +9 -4
  73. package/{src/codemods → codemods}/transforms/v0.0.12/add-is-icon-only.mjs +27 -22
  74. package/{src/codemods → codemods}/transforms/v0.0.13/icon-name-deprecations.mjs +12 -5
  75. package/{src/codemods → codemods}/transforms/v0.0.13/rename-attachments-to-drawer.mjs +15 -8
  76. package/{src/codemods → codemods}/transforms/v0.0.13/toolbar-density-to-size.mjs +10 -4
  77. package/{src/codemods → codemods}/transforms/v0.0.14/rename-action-props.mjs +11 -5
  78. package/{src/codemods → codemods}/transforms/v0.0.14/rename-section-wash-to-muted.mjs +11 -6
  79. package/{src/codemods → codemods}/transforms/v0.0.14/rename-status-variants.mjs +15 -10
  80. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-item-children-to-endcontent.mjs +13 -8
  81. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-selector-children-to-render-option.mjs +18 -13
  82. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-theme-selectors-to-data-attrs.mjs +8 -4
  83. package/{src/codemods → codemods}/transforms/v0.0.15/rename-date-picker-to-input.mjs +11 -6
  84. package/{src/codemods → codemods}/transforms/v0.0.15/rename-imperative-ref-to-handleRef.mjs +6 -1
  85. package/{src/codemods → codemods}/transforms/v0.0.15/rename-isStreaming-to-isStopShown.mjs +6 -1
  86. package/{src/codemods → codemods}/transforms/v0.0.15/rename-stack-element-to-as.mjs +8 -3
  87. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-badge-dot-to-statusdot.mjs +17 -10
  88. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-gap-to-numeric.mjs +7 -1
  89. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-isFullBleed-to-padding.mjs +9 -4
  90. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-useXDSIcon-to-getIcon.mjs +12 -7
  91. package/{src/codemods → codemods}/transforms/v0.0.2/rename-banner-endButton-to-endContent.mjs +7 -2
  92. package/{src/codemods → codemods}/transforms/v0.0.2/rename-form-tooltip-startIcon.mjs +8 -2
  93. package/{src/codemods → codemods}/transforms/v0.0.2/rename-isShown-to-isOpen.mjs +7 -2
  94. package/{src/codemods → codemods}/transforms/v0.0.2/rename-selector-items-to-options.mjs +7 -2
  95. package/{src/codemods → codemods}/transforms/v0.0.2/rename-sidenav-header-to-heading.mjs +11 -4
  96. package/{src/codemods → codemods}/transforms/v0.0.2/rename-topnav-title-to-heading.mjs +10 -4
  97. package/{src/codemods → codemods}/transforms/v0.0.2/unify-uncontrolled-to-defaultX.mjs +7 -2
  98. package/{src/codemods → codemods}/transforms/v0.0.2/unify-visibility-to-onOpenChange.mjs +10 -5
  99. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-badge-children-to-label.mjs +7 -2
  100. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-collapse-to-collapsible.mjs +9 -3
  101. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-radius-tokens.mjs +11 -5
  102. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-shadow-tokens.mjs +13 -6
  103. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-skeleton-radius.mjs +7 -1
  104. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-token-names.mjs +11 -5
  105. package/{src/codemods → codemods}/transforms/v0.0.7/rename-banner-variant-to-container.mjs +8 -3
  106. package/{src/codemods → codemods}/transforms/v0.0.8/migrate-token-renames.mjs +15 -8
  107. package/{src/codemods → codemods}/transforms/v0.0.8/rename-endslot-to-endcontent.mjs +7 -2
  108. package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +42 -7
  109. package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +43 -0
  110. package/{src/codemods → codemods}/transforms/v0.1.0/drop-xds-prefix-imports.mjs +117 -13
  111. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +21 -17
  112. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-declare-module.mjs +7 -2
  113. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +86 -15
  114. package/{src/codemods → codemods}/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +15 -9
  115. package/{src/codemods → codemods}/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +17 -12
  116. package/{src/codemods → codemods}/transforms/v0.1.5/rename-switch-label-spacing-default-to-hug.mjs +15 -9
  117. package/{src/codemods → codemods}/transforms/v0.1.7/migrate-table-tableprops-to-direct-props.mjs +17 -10
  118. package/{src/codemods → codemods}/transforms/v0.1.7/rename-table-renderprops-styles-to-xstyle.mjs +18 -13
  119. package/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +161 -0
  120. package/codemods/transforms/v0.1.8/index.mjs +19 -0
  121. package/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +239 -0
  122. package/docs/cli-integrations.doc.mjs +150 -0
  123. package/docs/elevation.doc.mjs +79 -1
  124. package/docs/getting-started.doc.mjs +9 -9
  125. package/docs/internationalization.doc.mjs +92 -46
  126. package/docs/migration.doc.mjs +18 -18
  127. package/docs/principles.doc.dense.mjs +1 -1
  128. package/docs/principles.doc.mjs +6 -6
  129. package/docs/principles.doc.zh.mjs +1 -1
  130. package/docs/styling-libraries.doc.mjs +3 -3
  131. package/docs/styling.doc.mjs +4 -4
  132. package/docs/theme.doc.dense.mjs +2 -2
  133. package/docs/theme.doc.mjs +7 -7
  134. package/docs/theme.doc.zh.mjs +1 -1
  135. package/docs/tokens.doc.mjs +1 -1
  136. package/docs/working-with-ai.doc.mjs +19 -19
  137. package/{src/commands → lib/agent-docs}/agent-docs.mjs +164 -29
  138. package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
  139. package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +123 -10
  140. package/{src/lib → lib}/cli-error.mjs +2 -2
  141. package/{src/lib → lib}/component-discovery.mjs +44 -2
  142. package/{src/lib → lib}/component-format.mjs +67 -25
  143. package/{src/lib → lib}/component-loader.mjs +27 -13
  144. package/{src/lib → lib}/componentDocOverlay.test.mjs +0 -1
  145. package/{src/lib → lib}/error-codes.test.mjs +1 -1
  146. package/{src/lib → lib}/hook-discovery.mjs +14 -1
  147. package/{src/lib → lib}/hook-format.mjs +29 -5
  148. package/{src/lib → lib}/integration-warnings.mjs +2 -2
  149. package/{src/lib → lib}/integrations.mjs +20 -0
  150. package/{src/lib → lib}/integrations.test.mjs +1 -1
  151. package/{src/lib → lib}/json-contract.test.mjs +1 -1
  152. package/{src/lib → lib}/json-shim.mjs +11 -6
  153. package/{src/lib → lib}/json-shim.test.mjs +1 -1
  154. package/{src/lib → lib}/json.mjs +3 -3
  155. package/{src/lib → lib}/levenshtein.mjs +6 -0
  156. package/{src/lib → lib}/manifest.mjs +7 -5
  157. package/{src/lib → lib}/manifest.test.mjs +2 -2
  158. package/{src/lib → lib}/module-loader.mjs +1 -0
  159. package/{src/lib → lib}/package-scanner.mjs +47 -0
  160. package/{src/lib → lib}/project.mjs +48 -18
  161. package/{src/lib → lib}/project.test.mjs +1 -1
  162. package/{src/lib → lib}/resolve-theme.mjs +5 -0
  163. package/{src/lib → lib}/string-utils.mjs +15 -0
  164. package/lib/term-log.mjs +57 -0
  165. package/{src/lib → lib}/xle/browser.mjs +18 -8
  166. package/{src/lib → lib}/xle/expand.mjs +155 -22
  167. package/{src/lib → lib}/xle/parse.mjs +119 -13
  168. package/{src/lib → lib}/xle/print.mjs +54 -14
  169. package/{src/lib → lib}/xle/registry-core.mjs +28 -3
  170. package/{src/lib → lib}/xle/registry.mjs +9 -4
  171. package/{src/lib → lib}/xle/splice.mjs +13 -2
  172. package/{src/lib → lib}/xle/validate.mjs +95 -14
  173. package/lib/xle/xle-ast.d.ts +214 -0
  174. package/package.json +37 -28
  175. package/scripts/postinstall.mjs +74 -0
  176. package/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +4 -4
  177. package/templates/blocks/components/Avatar/AvatarGroup.tsx +2 -2
  178. package/templates/blocks/components/Avatar/AvatarInitialsFallback.tsx +1 -1
  179. package/templates/blocks/components/Avatar/AvatarShowcase.tsx +5 -5
  180. package/templates/blocks/components/Avatar/AvatarUserCard.tsx +1 -1
  181. package/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
  182. package/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
  183. package/templates/blocks/components/AvatarGroup/AvatarGroupShowcase.tsx +2 -2
  184. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowCustomText.tsx +1 -1
  185. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowDefault.tsx +1 -1
  186. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowShowcase.tsx +2 -2
  187. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotShowcase.tsx +3 -3
  188. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +3 -3
  189. package/templates/blocks/components/Banner/BannerFloating.doc.mjs +14 -0
  190. package/templates/blocks/components/Banner/BannerFloating.tsx +16 -0
  191. package/templates/blocks/components/Button/ButtonFloating.doc.mjs +14 -0
  192. package/templates/blocks/components/Button/ButtonFloating.tsx +37 -0
  193. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +14 -0
  194. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +23 -0
  195. package/templates/blocks/components/Card/CardElevations.doc.mjs +14 -0
  196. package/templates/blocks/components/Card/CardElevations.tsx +32 -0
  197. package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +14 -0
  198. package/templates/blocks/components/Card/ClickableCardElevated.tsx +21 -0
  199. package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +14 -0
  200. package/templates/blocks/components/Card/SelectableCardElevated.tsx +37 -0
  201. package/templates/blocks/components/Carousel/CarouselSnap.tsx +1 -1
  202. package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +14 -0
  203. package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +75 -0
  204. package/templates/blocks/components/ChatMessage/ChatMessageAvatarName.tsx +2 -2
  205. package/templates/blocks/components/ChatMessage/ChatMessageMultiBubble.tsx +1 -1
  206. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleGrouping.tsx +1 -1
  207. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleMetadata.tsx +1 -1
  208. package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +5 -9
  209. package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -1
  210. package/templates/blocks/components/CodeBlock/CodeBlockTerminal.tsx +1 -1
  211. package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -1
  212. package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +14 -0
  213. package/templates/blocks/components/IconButton/IconButtonFloating.tsx +37 -0
  214. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.doc.mjs +19 -0
  215. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +46 -0
  216. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.doc.mjs +14 -0
  217. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.tsx +33 -0
  218. package/templates/blocks/components/Item/ItemWithMedia.tsx +2 -2
  219. package/templates/blocks/components/ListItem/ListItemWithMedia.tsx +2 -2
  220. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +14 -0
  221. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +39 -0
  222. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +14 -0
  223. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +44 -0
  224. package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -6
  225. package/templates/blocks/components/Stack/StackFillItem.tsx +2 -6
  226. package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
  227. package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
  228. package/templates/blocks/components/Table/TableRowStatusTable.doc.mjs +14 -0
  229. package/templates/blocks/components/Table/TableRowStatusTable.tsx +59 -0
  230. package/templates/blocks/components/Thumbnail/ThumbnailDisabled.tsx +6 -1
  231. package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +1 -0
  232. package/templates/blocks/components/Thumbnail/ThumbnailRemovable.tsx +1 -0
  233. package/templates/blocks/components/TypeaheadItem/TypeaheadItemShowcase.tsx +1 -1
  234. package/templates/pages/ai-chat/page.tsx +4 -4
  235. package/templates/pages/dashboard-portfolio/page.tsx +3 -11
  236. package/templates/pages/detail-page/page.tsx +5 -12
  237. package/templates/pages/documentation-design/page.tsx +1 -1
  238. package/templates/pages/messaging-shell/page.tsx +6 -8
  239. package/templates/pages/table-grouped/page.tsx +9 -14
  240. package/templates/pages/table-page/page.tsx +7 -9
  241. package/templates/pages/table-page-heatmap-status/page.tsx +5 -13
  242. package/{src/types → types}/api.contract.assert.ts +17 -8
  243. package/{src/types → types}/api.d.ts +110 -9
  244. package/{src/types → types}/base.d.ts +40 -4
  245. package/types/build.d.ts +53 -0
  246. package/types/codemod.d.ts +166 -0
  247. package/{src/types → types}/component.d.ts +1 -1
  248. package/{src/types → types}/discover.d.ts +1 -1
  249. package/{src/types → types}/docs.d.ts +1 -4
  250. package/{src/types → types}/hook.d.ts +1 -1
  251. package/{src/types → types}/index.d.ts +1 -0
  252. package/types/jscodeshift.d.ts +19 -0
  253. package/types/layout.d.ts +74 -0
  254. package/{src/types → types}/swizzle.d.ts +4 -0
  255. package/{src/types → types}/template-api.d.ts +4 -1
  256. package/types/theme.d.ts +53 -0
  257. package/types/upgrade.d.ts +108 -0
  258. package/utils/package-manager.mjs +178 -0
  259. package/utils/package-manager.test.mjs +220 -0
  260. package/{src/utils → utils}/path-safety.mjs +0 -18
  261. package/{src/utils → utils}/paths.mjs +4 -1
  262. package/{src/utils → utils}/update-check.mjs +5 -4
  263. package/{src/utils → utils}/update-check.test.mjs +3 -3
  264. package/docs/integration-authoring.md +0 -105
  265. package/src/commands/build.mjs +0 -196
  266. package/src/commands/init.mjs +0 -288
  267. package/src/commands/interactive-guard.test.mjs +0 -69
  268. package/src/commands/swizzle.mjs +0 -440
  269. package/src/commands/upgrade.test.mjs +0 -160
  270. package/src/types/codemod.d.ts +0 -81
  271. package/src/types/theme.d.ts +0 -23
  272. package/src/types/upgrade.d.ts +0 -64
  273. package/src/utils/interactive.mjs +0 -76
  274. package/src/utils/interactive.test.mjs +0 -70
  275. package/src/utils/package-manager.mjs +0 -74
  276. package/src/utils/package-manager.test.mjs +0 -113
  277. /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
  278. /package/{src/api → api/integration}/integration-block-exports.test.mjs +0 -0
  279. /package/{src/api → api/template}/template.test.mjs +0 -0
  280. /package/{src → authoring}/codemod.test.mjs +0 -0
  281. /package/{src → authoring}/config.mjs +0 -0
  282. /package/{src → authoring}/integration.mjs +0 -0
  283. /package/{src → authoring}/template.test.mjs +0 -0
  284. /package/{src → cli}/cli-exit-codes.test.mjs +0 -0
  285. /package/{src → cli}/commands/build-theme.color-scheme.test.mjs +0 -0
  286. /package/{src → cli}/commands/build-theme.import-path.test.mjs +0 -0
  287. /package/{src → cli}/commands/build-theme.path-safety.test.mjs +0 -0
  288. /package/{src → cli}/commands/build-theme.prose.test.mjs +0 -0
  289. /package/{src → cli}/commands/build-theme.variants.test.mjs +0 -0
  290. /package/{src → cli}/commands/build-theme.watch.test.mjs +0 -0
  291. /package/{src → cli}/commands/component.test.mjs +0 -0
  292. /package/{src → cli}/commands/detail-levels.test.mjs +0 -0
  293. /package/{src → cli}/commands/swizzle.path-safety.test.mjs +0 -0
  294. /package/{src → cli}/commands/swizzle.routing.test.mjs +0 -0
  295. /package/{src → cli}/commands/template.test.mjs +0 -0
  296. /package/{src → cli}/commands/upgrade.config-ordering.test.mjs +0 -0
  297. /package/{src → cli}/commands/validate-integration.test.mjs +0 -0
  298. /package/{src → cli}/update-hint-commands.test.mjs +0 -0
  299. /package/{src/codemods → codemods}/__tests__/rename-imperative-ref-to-handleRef.test.mjs +0 -0
  300. /package/{src/codemods → codemods}/__tests__/rename-isStreaming-to-isStopShown.test.mjs +0 -0
  301. /package/{src/codemods → codemods}/__tests__/rename-section-wash-to-muted.test.mjs +0 -0
  302. /package/{src/codemods → codemods}/__tests__/runner.test.mjs +0 -0
  303. /package/{src/codemods → codemods}/__tests__/toolbar-density-to-size.test.mjs +0 -0
  304. /package/{src/codemods → codemods}/__tests__/validation.test.mjs +0 -0
  305. /package/{src/codemods → codemods}/transforms/v0.0.10/__tests__/remove-size-props.test.mjs +0 -0
  306. /package/{src/codemods → codemods}/transforms/v0.0.10/index.mjs +0 -0
  307. /package/{src/codemods → codemods}/transforms/v0.0.12/__tests__/add-is-icon-only.test.mjs +0 -0
  308. /package/{src/codemods → codemods}/transforms/v0.0.12/index.mjs +0 -0
  309. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/icon-name-deprecations.test.mjs +0 -0
  310. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/rename-attachments-to-drawer.test.mjs +0 -0
  311. /package/{src/codemods → codemods}/transforms/v0.0.13/index.mjs +0 -0
  312. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-action-props.test.mjs +0 -0
  313. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +0 -0
  314. /package/{src/codemods → codemods}/transforms/v0.0.14/index.mjs +0 -0
  315. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-item-children-to-endcontent.test.mjs +0 -0
  316. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-selector-children-to-render-option.test.mjs +0 -0
  317. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-theme-selectors-to-data-attrs.test.mjs +0 -0
  318. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-date-picker-to-input.test.mjs +0 -0
  319. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-stack-element-to-as.test.mjs +0 -0
  320. /package/{src/codemods → codemods}/transforms/v0.0.15/index.mjs +0 -0
  321. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-badge-dot-to-statusdot.test.mjs +0 -0
  322. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-gap-to-numeric.test.mjs +0 -0
  323. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-isFullBleed-to-padding.test.mjs +0 -0
  324. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-useXDSIcon-to-getIcon.test.mjs +0 -0
  325. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-banner-endButton-to-endContent.test.mjs +0 -0
  326. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-form-tooltip-startIcon.test.mjs +0 -0
  327. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-isShown-to-isOpen.test.mjs +0 -0
  328. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-selector-items-to-options.test.mjs +0 -0
  329. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-sidenav-header-to-heading.test.mjs +0 -0
  330. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-topnav-title-to-heading.test.mjs +0 -0
  331. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-uncontrolled-to-defaultX.test.mjs +0 -0
  332. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-visibility-to-onOpenChange.test.mjs +0 -0
  333. /package/{src/codemods → codemods}/transforms/v0.0.2/index.mjs +0 -0
  334. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-collapse-to-collapsible.test.mjs +0 -0
  335. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-radius-tokens.test.mjs +0 -0
  336. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-shadow-tokens.test.mjs +0 -0
  337. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-skeleton-radius.test.mjs +0 -0
  338. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-token-names.test.mjs +0 -0
  339. /package/{src/codemods → codemods}/transforms/v0.0.6/index.mjs +0 -0
  340. /package/{src/codemods → codemods}/transforms/v0.0.7/__tests__/rename-banner-variant-to-container.test.mjs +0 -0
  341. /package/{src/codemods → codemods}/transforms/v0.0.7/index.mjs +0 -0
  342. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/migrate-token-renames.test.mjs +0 -0
  343. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/rename-endslot-to-endcontent.test.mjs +0 -0
  344. /package/{src/codemods → codemods}/transforms/v0.0.8/index.mjs +0 -0
  345. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -0
  346. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -0
  347. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -0
  348. /package/{src/codemods → codemods}/transforms/v0.1.0/index.mjs +0 -0
  349. /package/{src/codemods → codemods}/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +0 -0
  350. /package/{src/codemods → codemods}/transforms/v0.1.2/index.mjs +0 -0
  351. /package/{src/codemods → codemods}/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +0 -0
  352. /package/{src/codemods → codemods}/transforms/v0.1.3/index.mjs +0 -0
  353. /package/{src/codemods → codemods}/transforms/v0.1.5/__tests__/rename-switch-label-spacing-default-to-hug.test.mjs +0 -0
  354. /package/{src/codemods → codemods}/transforms/v0.1.5/index.mjs +0 -0
  355. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/migrate-table-tableprops-to-direct-props.test.mjs +0 -0
  356. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/rename-table-renderprops-styles-to-xstyle.test.mjs +0 -0
  357. /package/{src/codemods → codemods}/transforms/v0.1.7/index.mjs +0 -0
  358. /package/{src/lib → lib}/cli-error.test.mjs +0 -0
  359. /package/{src/lib → lib}/component-discovery.importpath.test.mjs +0 -0
  360. /package/{src/lib → lib}/component-format.test.mjs +0 -0
  361. /package/{src/lib → lib}/component-loader.test.mjs +0 -0
  362. /package/{src/lib → lib}/config-cache.mjs +0 -0
  363. /package/{src/lib → lib}/config-cache.test.mjs +0 -0
  364. /package/{src/lib → lib}/config-schema.mjs +0 -0
  365. /package/{src/lib → lib}/error-codes.mjs +0 -0
  366. /package/{src/lib → lib}/integration-warnings.test.mjs +0 -0
  367. /package/{src/lib → lib}/module-loader.test.mjs +0 -0
  368. /package/{src/lib → lib}/node-version.mjs +0 -0
  369. /package/{src/lib → lib}/node-version.test.mjs +0 -0
  370. /package/{src/lib → lib}/parse.mjs +0 -0
  371. /package/{src/lib → lib}/site.mjs +0 -0
  372. /package/{src/lib → lib}/xle/browser.d.ts +0 -0
  373. /package/{src/lib → lib}/xle/xle.test.mjs +0 -0
  374. /package/{src/schemas → schemas}/doc-schema.mjs +0 -0
  375. /package/{src/schemas → schemas}/template-schema.mjs +0 -0
  376. /package/{src/types → types}/config.d.ts +0 -0
  377. /package/{src/types → types}/doc.d.ts +0 -0
  378. /package/{src/types → types}/doctor.d.ts +0 -0
  379. /package/{src/types → types}/error-codes.d.ts +0 -0
  380. /package/{src/types → types}/integration.d.ts +0 -0
  381. /package/{src/types → types}/manifest.d.ts +0 -0
  382. /package/{src/types → types}/search.d.ts +0 -0
  383. /package/{src/types → types}/template.d.ts +0 -0
  384. /package/{src/types → types}/validate-integration.d.ts +0 -0
  385. /package/{src/utils → utils}/github.mjs +0 -0
  386. /package/{src/utils → utils}/path-safety.test.mjs +0 -0
  387. /package/{src/utils → utils}/paths.test.mjs +0 -0
  388. /package/{src/utils → utils}/semver.mjs +0 -0
  389. /package/{src/utils → utils}/semver.test.mjs +0 -0
@@ -11,8 +11,11 @@
11
11
  *
12
12
  * Pipeline (--apply):
13
13
  * 1. Read installed @astryxdesign/core (or legacy @xds/core) version
14
- * 2. Run codemods for --from → installed version
15
- * 3. Refresh agent docs (AGENTS.md / CLAUDE.md) if present
14
+ * 2. Refresh the managed agent-docs block (AGENTS.md / CLAUDE.md) to the
15
+ * installed version — runs on EVERY path (including the up-to-date /
16
+ * no-codemods short-circuits), because the block documents the installed
17
+ * library, not the codemod outcome. Dry-run reports without writing.
18
+ * 3. Run codemods for --from → installed version
16
19
  *
17
20
  * Options:
18
21
  * --from <version> Previous version before the dependency upgrade
@@ -37,23 +40,23 @@ import * as fs from 'node:fs';
37
40
  import * as path from 'node:path';
38
41
  import {execFile} from 'node:child_process';
39
42
  import {promisify} from 'node:util';
40
- import * as p from '@clack/prompts';
41
- import {ensureJscodeshift} from '../codemods/ensure-jscodeshift.mjs';
42
- import {getTransformsBetween, latestVersion} from '../codemods/registry.mjs';
43
- import {runCodemods} from '../codemods/runner.mjs';
43
+ import * as p from '../../lib/term-log.mjs';
44
+ import {ensureJscodeshift} from '../../codemods/ensure-jscodeshift.mjs';
45
+ import {getTransformsBetween, latestVersion} from '../../codemods/registry.mjs';
46
+ import {runCodemods} from '../../codemods/runner.mjs';
44
47
  import {
45
48
  discoverIntegrationCodemods,
46
49
  selectIntegrationCodemods,
47
- } from '../codemods/integration-discovery.mjs';
48
- import {runIntegrationCodemods} from '../codemods/integration-runner.mjs';
49
- import {installAgentDocs, discoverAgentDocs} from './agent-docs.mjs';
50
- import {getRunPrefix} from '../utils/package-manager.mjs';
51
- import {isValidSemver, semverGte} from '../utils/semver.mjs';
52
- import {jsonOut, jsonError} from '../lib/json.mjs';
53
- import {Project} from '../lib/project.mjs';
54
- import {loadIntegrations} from '../lib/integrations.mjs';
55
- import {warnOnIntegrationIssues} from '../lib/integration-warnings.mjs';
56
- import {ERROR_CODES} from '../lib/error-codes.mjs';
50
+ } from '../../codemods/integration-discovery.mjs';
51
+ import {runIntegrationCodemods} from '../../codemods/integration-runner.mjs';
52
+ import {installAgentDocs, inspectAgentDocs} from '../../lib/agent-docs/agent-docs.mjs';
53
+ import {getCliInvocation, formatCliCommand} from '../../utils/package-manager.mjs';
54
+ import {isValidSemver, semverGte} from '../../utils/semver.mjs';
55
+ import {jsonOut, jsonError} from '../../lib/json.mjs';
56
+ import {Project} from '../../lib/project.mjs';
57
+ import {loadIntegrations} from '../../lib/integrations.mjs';
58
+ import {warnOnIntegrationIssues} from '../../lib/integration-warnings.mjs';
59
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
57
60
 
58
61
  const execFileAsync = promisify(execFile);
59
62
 
@@ -79,8 +82,18 @@ function detectInstalledTargetVersion() {
79
82
  return null;
80
83
  }
81
84
 
85
+ /**
86
+ * @param {(string | null | undefined | false)[] | undefined} files
87
+ * @returns {string[]}
88
+ */
82
89
  function uniqueFiles(files) {
83
- return [...new Set((files ?? []).filter(Boolean))];
90
+ return [
91
+ ...new Set(
92
+ (files ?? []).filter(
93
+ /** @returns {f is string} */ f => Boolean(f),
94
+ ),
95
+ ),
96
+ ];
84
97
  }
85
98
 
86
99
  /**
@@ -92,7 +105,7 @@ function uniqueFiles(files) {
92
105
  * In apply mode the commands run in order via execFile; a nonzero exit (or a
93
106
  * buildCommand throw) fails the upgrade.
94
107
  *
95
- * @param {import('../types/config').PostCodemodHook[]} hooks
108
+ * @param {import('../../types/config').PostCodemodHook[]} hooks
96
109
  * @param {{packageDir: string, files: string[], apply: boolean}} context
97
110
  * @param {boolean} silent
98
111
  */
@@ -123,20 +136,140 @@ async function runPostCodemodHooks(hooks, context, silent) {
123
136
  continue;
124
137
  }
125
138
 
126
- await execFileAsync(cmd.command, cmd.args ?? [], {
127
- cwd: cmd.options?.cwd ?? packageDir,
128
- timeout: cmd.options?.timeout ?? 300_000,
129
- stdio: 'pipe',
130
- encoding: 'utf-8',
131
- ...cmd.options,
132
- env: {...process.env, ...(cmd.options?.env ?? {})},
133
- });
139
+ await execFileAsync(
140
+ cmd.command,
141
+ cmd.args ?? [],
142
+ /** @type {import('node:child_process').ExecFileOptions & {encoding: 'utf-8'}} */ ({
143
+ cwd: cmd.options?.cwd ?? packageDir,
144
+ timeout: cmd.options?.timeout ?? 300_000,
145
+ stdio: 'pipe',
146
+ encoding: 'utf-8',
147
+ ...cmd.options,
148
+ env: {...process.env, ...(cmd.options?.env ?? {})},
149
+ }),
150
+ );
134
151
  log.success(`Post-codemod hook ${label} completed.`);
135
152
  }
136
153
  }
137
154
 
155
+ /**
156
+ * Refresh (or, in dry-run, report) the managed agent-docs block after a version
157
+ * bump. The block (`<!-- ASTRYX:START --> … <!-- ASTRYX:END -->`) documents the
158
+ * INSTALLED library — its version, component index, and agent rules — so it must
159
+ * be re-synced on EVERY upgrade path, including the up-to-date / no-codemods
160
+ * short-circuits where no source file changes. That was the gap in #4168: an
161
+ * agent reading a stale index queries missing components and follows superseded
162
+ * rules. Three cases, one detection pass:
163
+ *
164
+ * - `stale` — a managed block records an older version (or a legacy XDS
165
+ * marker). `--apply` rewrites it; dry-run reports the pending
166
+ * refresh as a loud next step and writes nothing.
167
+ * - `missing` — core is installed but no managed block exists anywhere (the repo
168
+ * never ran `init`, or its agent docs were never marked). We never
169
+ * silently create docs mid-upgrade; we nudge to run `init`.
170
+ * - `current` — every block already matches the installed version: stay silent.
171
+ *
172
+ * @param {{cwd: string, installedVersion: string, apply: boolean, json: boolean}} ctx
173
+ * @returns {import('../../types/upgrade').AgentDocsSummary}
174
+ */
175
+ export function refreshAgentDocs({cwd, installedVersion, apply, json}) {
176
+ const inspection = inspectAgentDocs(cwd, installedVersion);
177
+ /** @type {import('../../types/upgrade').AgentDocsSummary} */
178
+ const summary = {
179
+ status: inspection.status,
180
+ installedVersion,
181
+ fromVersions: inspection.blockVersions,
182
+ files: [],
183
+ refreshed: false,
184
+ action: 'none',
185
+ };
186
+
187
+ // Never initialized — don't silently create docs during an upgrade; nudge.
188
+ if (inspection.status === 'missing') {
189
+ summary.action = 'nudge-init';
190
+ if (!json) {
191
+ p.log.warn(
192
+ `No Astryx agent-docs block found — AI agents have no component index. Run \`${formatCliCommand('astryx init --features agents')}\` to install it.`,
193
+ );
194
+ }
195
+ return summary;
196
+ }
197
+
198
+ if (inspection.status === 'current') return summary;
199
+
200
+ // Stale.
201
+ summary.files = inspection.staleFiles;
202
+ const fromLabel = summary.fromVersions.length
203
+ ? `v${summary.fromVersions.join(', v')}`
204
+ : 'an unknown version';
205
+
206
+ if (!apply) {
207
+ // Dry-run: report the pending change, never write.
208
+ summary.action = 'would-refresh';
209
+ if (!json) {
210
+ p.log.warn(
211
+ `Agent docs are stale: block is at ${fromLabel}, installed is v${installedVersion}. Re-run with --apply to refresh (${summary.files.join(', ')}).`,
212
+ );
213
+ }
214
+ return summary;
215
+ }
216
+
217
+ // Apply: rewrite only files that already carry a marker (onlyReplace).
218
+ try {
219
+ const written = installAgentDocs(cwd, {onlyReplace: true});
220
+ summary.refreshed = written.length > 0;
221
+ summary.files = written;
222
+ if (summary.refreshed) {
223
+ summary.action = 'refreshed';
224
+ if (!json) {
225
+ p.log.success(
226
+ `Agent docs refreshed → v${installedVersion} (from ${fromLabel}): ${written.join(', ')}`,
227
+ );
228
+ }
229
+ } else {
230
+ // We detected a stale marked block but rewrote nothing, and
231
+ // installAgentDocs did not throw — the block markers are malformed (e.g. a
232
+ // START with no matching END, so the writer can't safely splice it). Don't
233
+ // fail silently: the block is exactly the artifact agents rely on.
234
+ summary.action = 'error';
235
+ if (!json) {
236
+ p.log.warn(
237
+ `Agent docs look stale but couldn't be refreshed — the <!-- ASTRYX:START -->/<!-- ASTRYX:END --> markers may be malformed. Run \`${formatCliCommand('astryx init --features agents')}\` to reinstall the block.`,
238
+ );
239
+ }
240
+ }
241
+ } catch {
242
+ summary.action = 'error';
243
+ if (!json) {
244
+ p.log.warn(
245
+ `Could not refresh agent docs. Run \`${formatCliCommand('astryx init --features agents')}\` to update them manually.`,
246
+ );
247
+ }
248
+ }
249
+ return summary;
250
+ }
251
+
252
+ /**
253
+ * A single core transform entry as produced by the registry manifests. The
254
+ * registry's declared return type omits the optional `optional` flag and the
255
+ * `pr`/`codemodType` meta fields that the transform modules actually carry;
256
+ * this local shape captures what the upgrade command reads. Remove once
257
+ * codemods/registry.mjs declares these fields on its return type.
258
+ * @typedef {object} CoreTransformEntry
259
+ * @property {string} name
260
+ * @property {import('../../types/codemod').CodemodTransform} transform
261
+ * @property {{title: string, description?: string, pr?: string, codemodType?: string}} meta
262
+ * @property {boolean} [optional]
263
+ */
264
+
265
+ /**
266
+ * A version-scoped group of core transforms from the registry.
267
+ * @typedef {{version: string, transforms: CoreTransformEntry[]}} CoreVersionManifest
268
+ */
269
+
138
270
  /**
139
271
  * Register the `upgrade` command (codemod-driven version migration).
272
+ * @param {import('commander').Command} program
140
273
  */
141
274
  export function registerUpgrade(program) {
142
275
  program
@@ -160,6 +293,10 @@ export function registerUpgrade(program) {
160
293
  .option(
161
294
  '--integration <package-or-file>',
162
295
  'Explicit integration package name or integration file path (repeatable)',
296
+ /**
297
+ * @param {string} value
298
+ * @param {string[]} previous
299
+ */
163
300
  (value, previous) => [...(previous ?? []), value],
164
301
  [],
165
302
  )
@@ -170,13 +307,27 @@ export function registerUpgrade(program) {
170
307
  false,
171
308
  )
172
309
  .option('--list', 'List available codemods', false)
173
- .action(async options => {
310
+ .action(
311
+ /**
312
+ * @param {{
313
+ * list?: boolean,
314
+ * from?: string,
315
+ * apply: boolean,
316
+ * force?: boolean,
317
+ * codemod?: string,
318
+ * skipCodemod?: string[],
319
+ * integration?: string[],
320
+ * path: string,
321
+ * installDeps?: boolean,
322
+ * }} options
323
+ */
324
+ async options => {
174
325
  const json = program.opts().json || false;
175
326
  if (!json) p.intro('Upgrade');
176
327
 
177
328
  if (!options.list && !options.from) {
178
329
  const msg =
179
- 'Missing required --from. Install the target version first, then run `astryx upgrade --from <old-version>`.';
330
+ `Missing required --from. Install the target version first, then run \`${getCliInvocation()} upgrade --from <old-version>\`.`;
180
331
  if (json)
181
332
  return jsonError(msg, undefined, ERROR_CODES.ERR_INVALID_ARGUMENT);
182
333
  p.log.error(msg);
@@ -201,7 +352,9 @@ export function registerUpgrade(program) {
201
352
  // over every version and re-walked getTransformsBetween('0.0.0', v),
202
353
  // so each codemod was printed once per release that included it
203
354
  // (31 unique × 9 ≈ 201 lines on the current registry).
204
- const manifests = await getTransformsBetween('0.0.0', latestVersion);
355
+ const manifests = /** @type {CoreVersionManifest[]} */ (
356
+ await getTransformsBetween('0.0.0', latestVersion)
357
+ );
205
358
  for (const {version, transforms} of manifests) {
206
359
  for (const {name, meta, optional} of transforms) {
207
360
  codemods.push({
@@ -233,11 +386,12 @@ export function registerUpgrade(program) {
233
386
  return;
234
387
  }
235
388
 
236
- const currentVersion = options.from;
389
+ // Guarded above: reaching here means --from passed isValidSemver, so it's a string.
390
+ const currentVersion = /** @type {string} */ (options.from);
237
391
  const installed = detectInstalledTargetVersion();
238
392
  if (!installed) {
239
393
  const msg =
240
- 'Could not find installed @astryxdesign/core (or legacy @xds/core). Install the target version first, then rerun `astryx upgrade --from <old-version>`.';
394
+ `Could not find installed @astryxdesign/core (or legacy @xds/core). Install the target version first, then rerun \`${getCliInvocation()} upgrade --from <old-version>\`.`;
241
395
  if (json)
242
396
  return jsonError(msg, undefined, ERROR_CODES.ERR_VERSION_DETECT);
243
397
  p.log.error(msg);
@@ -254,6 +408,19 @@ export function registerUpgrade(program) {
254
408
  );
255
409
  }
256
410
 
411
+ // Sync the managed agent-docs block to the installed version FIRST. It
412
+ // documents the installed library (version + component index + rules),
413
+ // independent of any source codemods, so it must be refreshed on every
414
+ // path below — including the up-to-date / no-codemods short-circuits that
415
+ // return before codemods ever run (issue #4168). Dry-run reports without
416
+ // writing. Folded into every terminal payload as `agentDocs`.
417
+ const agentDocs = refreshAgentDocs({
418
+ cwd: process.cwd(),
419
+ installedVersion: targetVersion,
420
+ apply: options.apply,
421
+ json,
422
+ });
423
+
257
424
  // ───────────────────────────────────────────────────────────────────
258
425
  // PIPELINE ORDERING
259
426
  //
@@ -275,6 +442,7 @@ export function registerUpgrade(program) {
275
442
  status: 'up_to_date',
276
443
  from: currentVersion,
277
444
  to: targetVersion,
445
+ agentDocs,
278
446
  });
279
447
  }
280
448
  p.log.success('Already up to date — no codemods to run.');
@@ -286,9 +454,9 @@ export function registerUpgrade(program) {
286
454
  // Resolve CORE transforms from the registry. These do not need the loaded
287
455
  // config. Integration codemods are discovered later, AFTER the config
288
456
  // loads successfully (they require a valid config to resolve).
289
- const versionManifests = [
457
+ const versionManifests = /** @type {CoreVersionManifest[]} */ ([
290
458
  ...(await getTransformsBetween(currentVersion, targetVersion)),
291
- ];
459
+ ]);
292
460
 
293
461
  // Does the selected core set include >=1 CONFIG codemod? A config codemod
294
462
  // is the established convention `meta.codemodType === 'config'` (see
@@ -356,6 +524,15 @@ export function registerUpgrade(program) {
356
524
  skipCodemods,
357
525
  silent: json,
358
526
  });
527
+ // runCodemods returns either a success accounting or a
528
+ // {ok: false, reason} sentinel (e.g. source_path_missing). Narrow to the
529
+ // success shape so downstream property reads type-check; the sentinel
530
+ // branch collapses to null and the `?? 0`/`?? []` fallbacks below treat
531
+ // it as "no files changed", matching the existing runtime behavior.
532
+ const coreResult =
533
+ codemodResult && 'totalFilesChanged' in codemodResult
534
+ ? codemodResult
535
+ : null;
359
536
 
360
537
  // STEP 4 — Load the consumer's config (STRICT validation; unchanged). On
361
538
  // --apply this now sees the repaired config the core codemod just wrote.
@@ -363,8 +540,11 @@ export function registerUpgrade(program) {
363
540
  // here. Wrap in a graceful dry-run catch (see below).
364
541
  // Assigned inside the try below; every catch branch returns, so these
365
542
  // are always set before any later read.
543
+ /** @type {Array<import('../../lib/integrations.mjs').LoadedIntegration>} */
366
544
  let integrations;
545
+ /** @type {import('../../types/config').PostCodemodHook[]} */
367
546
  let postCodemodHooks;
547
+ /** @type {Array<{version: string, codemods: import('../../types/codemod').CodemodEntry[]}>} */
368
548
  let integrationVersionGroups;
369
549
  try {
370
550
  const project = await Project.load(process.cwd());
@@ -375,6 +555,7 @@ export function registerUpgrade(program) {
375
555
  ]);
376
556
  integrations = await loadIntegrations(integrationSpecs);
377
557
  } catch (err) {
558
+ const configErr = /** @type {Error} */ (err);
378
559
  // GRACEFUL DRY-RUN CATCH. A config that fails strict validation is the
379
560
  // EXPECTED, fixable case ONLY when we are in dry-run AND a pending core
380
561
  // config codemod just PREVIEWED a change to the config — i.e. the very
@@ -385,11 +566,14 @@ export function registerUpgrade(program) {
385
566
  // gate and aborts below — preserving the strictness contract.) This is
386
567
  // the reason this PR reorders the pipeline.
387
568
  const codemodWouldFixConfig =
388
- hasCoreConfigCodemod && (codemodResult?.totalFilesChanged ?? 0) > 0;
569
+ hasCoreConfigCodemod && (coreResult?.totalFilesChanged ?? 0) > 0;
389
570
  if (!options.apply && codemodWouldFixConfig) {
390
571
  const codemodFlags = coreConfigCodemodNames
391
572
  .map(name => `--codemod ${name}`)
392
573
  .join(' ');
574
+ // Canonical (bare) form — this is a structured, machine-executable
575
+ // field in the --json envelope. The human print below is made
576
+ // install-aware via formatCliCommand.
393
577
  const suggestedCommand = `astryx upgrade --from ${currentVersion} ${codemodFlags} --apply`;
394
578
  const guidance =
395
579
  'Your astryx.config currently fails strict validation, but a pending ' +
@@ -401,15 +585,16 @@ export function registerUpgrade(program) {
401
585
  status: 'config_fixable',
402
586
  from: currentVersion,
403
587
  to: targetVersion,
404
- configError: err.message,
588
+ configError: configErr.message,
405
589
  configCodemods: coreConfigCodemodNames,
406
590
  suggestedCommand,
407
591
  message: guidance,
408
592
  note: 'Integrations are skipped in this preview; they will be processed on the --apply run.',
593
+ agentDocs,
409
594
  });
410
595
  }
411
596
  p.log.warn(guidance);
412
- p.log.info(` ${suggestedCommand}`);
597
+ p.log.info(` ${formatCliCommand(suggestedCommand)}`);
413
598
  p.log.info(
414
599
  'Integrations are skipped in this preview; they will be processed on the --apply run.',
415
600
  );
@@ -417,14 +602,15 @@ export function registerUpgrade(program) {
417
602
  return;
418
603
  }
419
604
  // Genuine config error (apply mode, OR dry-run with no pending core
420
- // config codemod that would fix it): abort as before.
605
+ // config codemod that would fix it): abort as before. The agent-docs
606
+ // refresh already ran (it's independent of config), so surface it.
421
607
  if (json)
422
608
  return jsonError(
423
- err.message,
424
- undefined,
609
+ configErr.message,
610
+ /** @type {import('../../types/base').Suggestion[]} */ (/** @type {unknown} */ ({agentDocs})),
425
611
  ERROR_CODES.ERR_INVALID_ARGUMENT,
426
612
  );
427
- p.log.error(err.message);
613
+ p.log.error(configErr.message);
428
614
  p.outro('Aborted');
429
615
  process.exitCode = 1;
430
616
  return;
@@ -455,12 +641,21 @@ export function registerUpgrade(program) {
455
641
  // hard-failing the upgrade. An EXECUTION-time failure (a transform
456
642
  // throwing) is handled later by the codemod-error gate, which still
457
643
  // aborts the upgrade.
644
+ /** @type {Map<string, Array<import('../../types/codemod').CodemodEntry>>} */
458
645
  const integrationCodemodsByVersion = new Map();
459
646
  for (const integration of integrations) {
460
647
  if (!integration?.codemods) continue;
461
648
  try {
462
649
  const byVersion = await discoverIntegrationCodemods([integration]);
463
- for (const [version, list] of byVersion) {
650
+ for (const [version, rawList] of byVersion) {
651
+ // discoverIntegrationCodemods declares `codemod: object` (loose); the
652
+ // runtime entries carry the full CodemodEntry.codemod shape. Narrow
653
+ // to the map's element type. Report: integration-discovery.mjs's
654
+ // @returns should declare CodemodEntry instead of the loose object.
655
+ const list =
656
+ /** @type {Array<import('../../types/codemod').CodemodEntry>} */ (
657
+ /** @type {unknown} */ (rawList)
658
+ );
464
659
  const existing = integrationCodemodsByVersion.get(version);
465
660
  if (existing) existing.push(...list);
466
661
  else integrationCodemodsByVersion.set(version, [...list]);
@@ -470,11 +665,14 @@ export function registerUpgrade(program) {
470
665
  // above surfaces the underlying issue. Best-effort, non-blocking.
471
666
  }
472
667
  }
473
- integrationVersionGroups = selectIntegrationCodemods(
474
- integrationCodemodsByVersion,
475
- currentVersion,
476
- targetVersion,
477
- );
668
+ integrationVersionGroups =
669
+ /** @type {Array<{version: string, codemods: import('../../types/codemod').CodemodEntry[]}>} */ (
670
+ selectIntegrationCodemods(
671
+ integrationCodemodsByVersion,
672
+ currentVersion,
673
+ targetVersion,
674
+ )
675
+ );
478
676
  const hasIntegrationCodemods = integrationVersionGroups.some(
479
677
  g => g.codemods.length > 0,
480
678
  );
@@ -499,6 +697,7 @@ export function registerUpgrade(program) {
499
697
  status: 'no_codemods',
500
698
  from: currentVersion,
501
699
  to: targetVersion,
700
+ agentDocs,
502
701
  });
503
702
  }
504
703
  p.log.success('No codemods available for this version range.');
@@ -510,7 +709,7 @@ export function registerUpgrade(program) {
510
709
  if (totalTransforms === 0 && totalOptional === 0) {
511
710
  const msg = `Codemod "${options.codemod}" not found. Use --list to see available codemods.`;
512
711
  if (json)
513
- return jsonError(msg, undefined, ERROR_CODES.ERR_UNKNOWN_CODEMOD);
712
+ return jsonError(msg, /** @type {import('../../types/base').Suggestion[]} */ (/** @type {unknown} */ ({agentDocs})), ERROR_CODES.ERR_UNKNOWN_CODEMOD);
514
713
  p.log.error(msg);
515
714
  p.outro('Aborted');
516
715
  process.exitCode = 1;
@@ -527,12 +726,35 @@ export function registerUpgrade(program) {
527
726
  }
528
727
  }
529
728
 
729
+ /**
730
+ * Terminal upgrade receipt. NOTE: the shape emitted here (with
731
+ * `integrations`, `filesChanged`, `transformsApplied`, `errors`) is what
732
+ * the command has always produced and what upgrade.test/config-ordering
733
+ * assert on; it does NOT match `UpgradeRunResponse.data` in
734
+ * types/upgrade.d.ts (which declares a stale `depsUpdated` field and omits
735
+ * these). The jsonOut call below is cast to bridge that drift. See the
736
+ * report: types/upgrade.d.ts needs reconciling with the real envelope.
737
+ * @type {{
738
+ * from: string,
739
+ * to: string,
740
+ * codemods: number,
741
+ * integrations: string[],
742
+ * agentDocsRefreshed: boolean,
743
+ * agentDocs: import('../../types/upgrade').AgentDocsSummary,
744
+ * filesChanged?: number,
745
+ * transformsApplied?: number,
746
+ * errors?: Array<{file: string, codemod: string, error: string}>,
747
+ * }}
748
+ */
530
749
  const receipt = {
531
750
  from: currentVersion,
532
751
  to: targetVersion,
533
752
  codemods: totalTransforms,
534
753
  integrations: integrations.map(i => i.name ?? i.__spec),
535
- agentDocsRefreshed: false,
754
+ // Refreshed up front (before the gates above), so the receipt just
755
+ // reports what happened. `agentDocsRefreshed` kept for back-compat.
756
+ agentDocsRefreshed: agentDocs.refreshed,
757
+ agentDocs,
536
758
  };
537
759
 
538
760
  // Run file-based integration codemods alongside the core registry
@@ -556,17 +778,17 @@ export function registerUpgrade(program) {
556
778
  // Merge core + integration codemod results into a single accounting so
557
779
  // hooks, receipts, and error gating see both.
558
780
  const mergedFilesChanged =
559
- (codemodResult?.totalFilesChanged ?? 0) +
781
+ (coreResult?.totalFilesChanged ?? 0) +
560
782
  (integrationResult?.totalFilesChanged ?? 0);
561
783
  const mergedTransformsApplied =
562
- (codemodResult?.totalTransformsApplied ?? 0) +
784
+ (coreResult?.totalTransformsApplied ?? 0) +
563
785
  (integrationResult?.totalTransformsApplied ?? 0);
564
786
  const mergedWrittenFiles = [
565
- ...(codemodResult?.writtenFiles ?? []),
787
+ ...(coreResult?.writtenFiles ?? []),
566
788
  ...(integrationResult?.writtenFiles ?? []),
567
789
  ];
568
790
  const mergedErrors = [
569
- ...(codemodResult?.errors ?? []),
791
+ ...(coreResult?.errors ?? []),
570
792
  ...(integrationResult?.errors ?? []),
571
793
  ];
572
794
 
@@ -591,39 +813,23 @@ export function registerUpgrade(program) {
591
813
  json,
592
814
  );
593
815
  } catch (err) {
816
+ const hookErr = /** @type {Error} */ (err);
594
817
  if (json)
595
818
  return jsonError(
596
- `Post-codemod hook failed: ${err.message}`,
597
- {receipt},
819
+ `Post-codemod hook failed: ${hookErr.message}`,
820
+ /** @type {import('../../types/base').Suggestion[]} */ (/** @type {unknown} */ ({receipt})),
598
821
  ERROR_CODES.ERR_CODEMOD_FAILED,
599
822
  );
600
- p.log.error(`Post-codemod hook failed: ${err.message}`);
823
+ p.log.error(`Post-codemod hook failed: ${hookErr.message}`);
601
824
  p.outro('Upgrade failed');
602
825
  process.exitCode = 1;
603
826
  return;
604
827
  }
605
828
  }
606
829
 
607
- // Refresh agent docs if any exist (AGENTS.md, CLAUDE.md, .claude/CLAUDE.md, etc.)
608
- // Always update after --apply; also update during dry-run if files exist,
609
- // since the index reflects the installed CLI version, not the codemods.
610
- const existingDocs = discoverAgentDocs(process.cwd());
611
- if (existingDocs.length > 0) {
612
- try {
613
- // onlyReplace: only update files that already have Astryx markers.
614
- // Don't inject into files that never had Astryx content.
615
- const written = installAgentDocs(process.cwd(), {onlyReplace: true});
616
- receipt.agentDocsRefreshed = written.length > 0;
617
- if (!json && written.length > 0)
618
- p.log.success(`Agent docs updated: ${written.join(', ')}`);
619
- } catch {
620
- if (!json) {
621
- p.log.warn(
622
- `Could not update agent docs. Run \`${getRunPrefix()} astryx init --features agents\` to update manually.`,
623
- );
624
- }
625
- }
626
- }
830
+ // NOTE: the managed agent-docs block was already refreshed up front (see
831
+ // refreshAgentDocs after installed-version detection), so it stays in sync
832
+ // even on the short-circuit paths that return before this point.
627
833
 
628
834
  receipt.filesChanged = mergedFilesChanged;
629
835
  receipt.transformsApplied = mergedTransformsApplied;
@@ -632,7 +838,7 @@ export function registerUpgrade(program) {
632
838
  if (receipt.errors?.length > 0) {
633
839
  const msg = `Upgrade completed with ${receipt.errors.length} codemod error${receipt.errors.length === 1 ? '' : 's'}.`;
634
840
  if (json) {
635
- return jsonError(msg, {receipt}, ERROR_CODES.ERR_CODEMOD_FAILED);
841
+ return jsonError(msg, /** @type {import('../../types/base').Suggestion[]} */ (/** @type {unknown} */ ({receipt})), ERROR_CODES.ERR_CODEMOD_FAILED);
636
842
  }
637
843
  p.outro('Upgrade failed');
638
844
  process.exitCode = 1;
@@ -640,7 +846,15 @@ export function registerUpgrade(program) {
640
846
  }
641
847
 
642
848
  if (json) {
643
- return jsonOut('upgrade.run', receipt);
849
+ // The emitted receipt intentionally differs from UpgradeRunResponse.data
850
+ // (see the typedef note above and the report): cast to the declared
851
+ // envelope shape until types/upgrade.d.ts is reconciled.
852
+ return jsonOut(
853
+ 'upgrade.run',
854
+ /** @type {import('../../types/upgrade').UpgradeRunResponse['data']} */ (
855
+ /** @type {unknown} */ (receipt)
856
+ ),
857
+ );
644
858
  }
645
859
  p.outro(options.apply ? 'Upgrade complete' : 'Dry run complete');
646
860
  });