@astryxdesign/cli 0.6.3-canary.f22695a → 0.6.3

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 (197) hide show
  1. package/README.md +1 -2
  2. package/api/build/build.type.d.mts +2 -2
  3. package/api/build/build.type.mjs +2 -2
  4. package/api/component/component.type.d.mts +6 -6
  5. package/api/component/component.type.mjs +19 -19
  6. package/api/discover/discover.type.d.mts +4 -4
  7. package/api/discover/discover.type.mjs +10 -10
  8. package/api/docs/_adapter.d.mts +24 -37
  9. package/api/docs/_adapter.mjs +83 -169
  10. package/api/docs/detail/detail.mjs +63 -14
  11. package/api/docs/detail/section/section.d.mts +1 -1
  12. package/api/docs/detail/section/section.mjs +20 -44
  13. package/api/docs/detail/section/section.test.mjs +0 -41
  14. package/api/docs/docs.d.mts +2 -7
  15. package/api/docs/docs.doc.mjs +10 -27
  16. package/api/docs/docs.mjs +9 -16
  17. package/api/docs/docs.test.mjs +0 -6
  18. package/api/docs/docs.type.d.mts +3 -40
  19. package/api/docs/docs.type.mjs +8 -36
  20. package/api/docs/integrationDocs.test.mjs +0 -106
  21. package/api/doctor/doctor.d.mts +0 -48
  22. package/api/doctor/doctor.mjs +0 -232
  23. package/api/doctor/doctor.test.mjs +0 -196
  24. package/api/hook/hook.type.d.mts +3 -3
  25. package/api/hook/hook.type.mjs +11 -11
  26. package/api/hook/list/list.d.mts +1 -1
  27. package/api/integration/add-contribution.mjs +3 -5
  28. package/api/integration/add-contribution.test.mjs +4 -4
  29. package/api/integration/integration-authoring.type.d.mts +1 -1
  30. package/api/integration/pack-check.mjs +7 -49
  31. package/api/integration/pack-check.test.mjs +0 -249
  32. package/api/search/search.d.mts +1 -1
  33. package/api/search/search.mjs +5 -5
  34. package/api/search/search.type.d.mts +2 -2
  35. package/api/search/search.type.mjs +1 -1
  36. package/api/swizzle/swizzle.type.d.mts +2 -2
  37. package/api/swizzle/swizzle.type.mjs +2 -2
  38. package/api/template/template.d.mts +1 -1
  39. package/api/template/template.type.d.mts +6 -6
  40. package/api/template/template.type.mjs +12 -12
  41. package/api/theme/build/build.mjs +6 -20
  42. package/api/theme/build/build.test.mjs +0 -127
  43. package/api/theme/palette/generate/generate.mjs +1 -1
  44. package/api/theme/palette/generate/generator.d.mts +13 -10
  45. package/api/theme/palette/generate/generator.mjs +3 -7
  46. package/api/theme/theme.type.d.mts +11 -170
  47. package/api/theme/theme.type.mjs +27 -94
  48. package/api/upgrade/_adapter.mjs +5 -71
  49. package/api/upgrade/upgrade.doc.mjs +3 -4
  50. package/api/upgrade/upgrade.type.d.mts +5 -5
  51. package/api/upgrade/upgrade.type.mjs +11 -11
  52. package/assets/codemods/integration-discovery.mjs +2 -40
  53. package/assets/codemods/integration-discovery.test.mjs +0 -58
  54. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +5 -27
  55. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +5 -20
  56. package/assets/docs/README.md +0 -9
  57. package/assets/docs/cli-integrations.doc.mjs +15 -86
  58. package/assets/docs/styling-libraries.doc.mjs +1 -1
  59. package/assets/docs/working-with-ai.doc.mjs +1 -1
  60. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +3 -19
  61. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +65 -383
  62. package/authoring/_shared/contract.ts +0 -22
  63. package/authoring/codemod/codemod.doc.mjs +1 -6
  64. package/authoring/codemod/parse.d.mts +8 -8
  65. package/authoring/codemod/parse.mjs +6 -8
  66. package/authoring/config/parse.d.mts +13 -13
  67. package/authoring/config/parse.mjs +8 -8
  68. package/authoring/config/type.ts +3 -3
  69. package/authoring/debug/parse.d.mts +5 -5
  70. package/authoring/debug/parse.mjs +3 -3
  71. package/authoring/doctypes/_schema.d.mts +23 -788
  72. package/authoring/doctypes/_schema.mjs +39 -492
  73. package/authoring/doctypes/base/type.ts +0 -40
  74. package/authoring/doctypes/command/command.doc.mjs +2 -3
  75. package/authoring/doctypes/command/parse.d.mts +2 -2
  76. package/authoring/doctypes/command/parse.mjs +1 -1
  77. package/authoring/doctypes/command/type.ts +2 -3
  78. package/authoring/doctypes/component/component.doc.mjs +3 -6
  79. package/authoring/doctypes/component/parse.d.mts +2 -2
  80. package/authoring/doctypes/component/parse.mjs +1 -1
  81. package/authoring/doctypes/component/type.ts +3 -4
  82. package/authoring/doctypes/enum/parse.d.mts +2 -2
  83. package/authoring/doctypes/enum/parse.mjs +1 -1
  84. package/authoring/doctypes/enum/type.ts +1 -3
  85. package/authoring/doctypes/function/function.doc.mjs +0 -4
  86. package/authoring/doctypes/function/parse.d.mts +2 -2
  87. package/authoring/doctypes/function/parse.mjs +1 -1
  88. package/authoring/doctypes/function/type.ts +2 -6
  89. package/authoring/doctypes/hook/hook.doc.mjs +0 -4
  90. package/authoring/doctypes/hook/parse.d.mts +2 -2
  91. package/authoring/doctypes/hook/parse.mjs +1 -1
  92. package/authoring/doctypes/hook/type.ts +2 -3
  93. package/authoring/doctypes/legacy.d.mts +6 -8
  94. package/authoring/doctypes/legacy.mjs +4 -5
  95. package/authoring/doctypes/parse.d.mts +18 -20
  96. package/authoring/doctypes/parse.mjs +10 -16
  97. package/authoring/doctypes/parse.test.mjs +3 -77
  98. package/authoring/doctypes/reference/parse.d.mts +2 -2
  99. package/authoring/doctypes/reference/parse.mjs +5 -8
  100. package/authoring/doctypes/reference/reference.doc.mjs +4 -17
  101. package/authoring/doctypes/reference/type.ts +5 -51
  102. package/authoring/doctypes/schema/parse.d.mts +2 -2
  103. package/authoring/doctypes/schema/parse.mjs +1 -1
  104. package/authoring/doctypes/schema/type.ts +2 -3
  105. package/authoring/doctypes/template/parse.d.mts +1 -92
  106. package/authoring/doctypes/template/parse.mjs +2 -36
  107. package/authoring/doctypes/template/parse.test.mjs +2 -8
  108. package/authoring/doctypes/template/template.doc.mjs +0 -4
  109. package/authoring/doctypes/template/type.ts +2 -5
  110. package/authoring/doctypes/types.ts +9 -10
  111. package/authoring/gap-report/parse.d.mts +10 -10
  112. package/authoring/gap-report/parse.mjs +6 -6
  113. package/authoring/gap-report/type.ts +1 -1
  114. package/authoring/index.d.mts +0 -1
  115. package/authoring/index.d.ts +17 -49
  116. package/authoring/index.mjs +0 -1
  117. package/authoring/integration/integration.doc.mjs +6 -13
  118. package/authoring/integration/parse.d.mts +2 -2
  119. package/authoring/integration/parse.mjs +1 -1
  120. package/authoring/integration/parse.test.mjs +1 -10
  121. package/authoring/integration/schema.d.mts +4 -6
  122. package/authoring/integration/schema.mjs +3 -9
  123. package/authoring/integration/type.ts +6 -23
  124. package/authoring/shadcn/receipt.d.mts +6 -6
  125. package/clients/cli/commands/docs.doc.mjs +3 -13
  126. package/clients/cli/commands/docs.mjs +21 -121
  127. package/clients/cli/commands/docs.test.mjs +0 -88
  128. package/clients/cli/commands/integration-authoring.test.mjs +9 -13
  129. package/clients/cli/commands/theme-palette-generate.doc.mjs +4 -8
  130. package/clients/cli/commands/upgrade.doc.mjs +2 -2
  131. package/clients/cli/formatters/index.mjs +1 -162
  132. package/clients/cli/formatters/index.test.mjs +0 -91
  133. package/clients/cli/lib/manifest.mjs +2 -7
  134. package/foundation/config/project.mjs +6 -21
  135. package/foundation/discovery/component-discovery.d.mts +1 -1
  136. package/foundation/discovery/component-discovery.mjs +1 -2
  137. package/foundation/discovery/docs-discovery.d.mts +4 -11
  138. package/foundation/discovery/docs-discovery.mjs +88 -208
  139. package/foundation/discovery/docs-discovery.test.mjs +13 -279
  140. package/foundation/discovery/template-adapter.mjs +1 -2
  141. package/foundation/integrations/autolink.mjs +5 -12
  142. package/foundation/integrations/integration-warnings.mjs +0 -6
  143. package/foundation/integrations/integrations.d.mts +2 -46
  144. package/foundation/integrations/integrations.mjs +8 -167
  145. package/foundation/integrations/integrations.test.mjs +1 -384
  146. package/foundation/integrations/validate-contributions.d.mts +0 -2
  147. package/foundation/integrations/validate-contributions.mjs +0 -10
  148. package/foundation/response/json-contract.test.mjs +17 -46
  149. package/foundation/response/response-types.doc.mjs +1 -6
  150. package/package.json +11 -9
  151. package/api/docs/compiled-topics.test.mjs +0 -78
  152. package/api/docs/index/index.d.mts +0 -18
  153. package/api/docs/index/index.mjs +0 -32
  154. package/api/docs/index/index.test.mjs +0 -62
  155. package/api/upgrade/project-context.test.mjs +0 -272
  156. package/assets/docs/authoring.doc.mjs +0 -14
  157. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +0 -14
  158. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +0 -34
  159. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +0 -14
  160. package/assets/templates/blocks/components/Timer/TimerInline.tsx +0 -14
  161. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +0 -13
  162. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +0 -47
  163. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +0 -14
  164. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +0 -31
  165. package/authoring/doctypes/base/graph-fields.doc.d.mts +0 -9
  166. package/authoring/doctypes/base/graph-fields.doc.mjs +0 -62
  167. package/authoring/doctypes/load-contract.test.mjs +0 -207
  168. package/authoring/doctypes/namespace/namespace.doc.d.mts +0 -9
  169. package/authoring/doctypes/namespace/namespace.doc.mjs +0 -132
  170. package/authoring/doctypes/namespace/parse.d.mts +0 -12
  171. package/authoring/doctypes/namespace/parse.mjs +0 -25
  172. package/authoring/doctypes/namespace/parse.test.mjs +0 -165
  173. package/authoring/doctypes/namespace/type.ts +0 -71
  174. package/authoring/identity/identity.doc.d.mts +0 -9
  175. package/authoring/identity/identity.doc.mjs +0 -61
  176. package/authoring/identity/type.ts +0 -132
  177. package/foundation/discovery/authoring-self-docs.d.mts +0 -69
  178. package/foundation/discovery/authoring-self-docs.mjs +0 -214
  179. package/foundation/discovery/authoring-self-docs.test.mjs +0 -154
  180. package/foundation/discovery/docs-output-budget.d.mts +0 -28
  181. package/foundation/discovery/docs-output-budget.mjs +0 -50
  182. package/foundation/discovery/docs-section-key.d.mts +0 -98
  183. package/foundation/discovery/docs-section-key.mjs +0 -221
  184. package/foundation/discovery/docs-section-key.test.mjs +0 -224
  185. package/foundation/doc-compiler/compile.d.mts +0 -162
  186. package/foundation/doc-compiler/compile.mjs +0 -262
  187. package/foundation/doc-compiler/doc-compiler.test.mjs +0 -687
  188. package/foundation/doc-compiler/ir.d.mts +0 -9
  189. package/foundation/doc-compiler/ir.mjs +0 -287
  190. package/foundation/doc-compiler/lenses.d.mts +0 -33
  191. package/foundation/doc-compiler/lenses.mjs +0 -127
  192. package/foundation/identity/provider-identity.d.mts +0 -90
  193. package/foundation/identity/provider-identity.mjs +0 -320
  194. package/foundation/identity/provider-identity.test.mjs +0 -254
  195. package/foundation/identity/providers.d.mts +0 -7
  196. package/foundation/identity/providers.mjs +0 -16
  197. package/foundation/integrations/provider-conflicts.test.mjs +0 -125
@@ -6,23 +6,23 @@
6
6
  * directly (functions own their types); the public `@astryxdesign/cli/api`
7
7
  * surface re-exports them via types/theme.d.ts, so consumers see the same names.
8
8
  *
9
- * Invocation -> type discriminator
9
+ * Invocation -> type discriminator
10
10
  * ------------------------------------------------------------------
11
- * astryx --json theme build <file> -> theme.build
12
- * astryx --json theme build <file> --check -> theme.build.check
13
- * astryx --json theme build <a> <b> … -> theme.build.batch
14
- * astryx --json theme list -> theme.list
15
- * astryx --json theme add <slug> -> theme.add
16
- * astryx --json theme template -> theme.template
17
- * astryx --json theme targets [filter] -> theme.targets
18
- * astryx --json theme palette generate <file> -> theme.palette.generate
19
- * (file not found / parse error) -> CLIError
11
+ * xds --json theme build <file> -> theme.build
12
+ * xds --json theme build <file> --check -> theme.build.check
13
+ * xds --json theme build <a> <b> … -> theme.build.batch
14
+ * xds --json theme list -> theme.list
15
+ * xds --json theme add <slug> -> theme.add
16
+ * xds --json theme template -> theme.template
17
+ * xds --json theme targets [filter] -> theme.targets
18
+ * xds --json theme palette generate <file> -> theme.palette.generate
19
+ * (file not found / parse error) -> CLIError
20
20
  *
21
21
  * @position api — colocated typedefs for api/theme/{theme,build,add,list,template,targets,_adapter}
22
22
  */
23
23
 
24
24
  /**
25
- * astryx --json theme build <file>
25
+ * xds --json theme build <file>
26
26
  * @typedef {object} ThemeBuildResponse
27
27
  * @property {'theme.build'} type
28
28
  * `warnings` are defects the theme author should fix. `notices` are advisories
@@ -32,14 +32,14 @@
32
32
  */
33
33
 
34
34
  /**
35
- * astryx --json theme build <file> --check
35
+ * xds --json theme build <file> --check
36
36
  * @typedef {object} ThemeBuildCheckResponse
37
37
  * @property {'theme.build.check'} type
38
38
  * @property {{name: string, upToDate: boolean, stale: Array<{path: string, reason: 'missing' | 'outdated'}>, checked: string[]}} data
39
39
  */
40
40
 
41
41
  /**
42
- * astryx --json theme build <a> <b> … — several themes in one invocation. Each
42
+ * xds --json theme build <a> <b> … — several themes in one invocation. Each
43
43
  * result carries the file as it was passed and the receipt a single-file build
44
44
  * would have returned (null when that theme produced no CSS). One file still
45
45
  * returns the bare theme.build / theme.build.check envelope.
@@ -59,21 +59,21 @@
59
59
  */
60
60
 
61
61
  /**
62
- * astryx --json theme list
62
+ * xds --json theme list
63
63
  * @typedef {object} ThemeListResponse
64
64
  * @property {'theme.list'} type
65
65
  * @property {ThemeListEntry[]} data
66
66
  */
67
67
 
68
68
  /**
69
- * astryx --json theme add <slug>
69
+ * xds --json theme add <slug>
70
70
  * @typedef {object} ThemeAddResponse
71
71
  * @property {'theme.add'} type
72
72
  * @property {{slug: string, displayName: string, maintained: boolean, package: string, outputDir: string, entry: string, exportName: string, files: string[]}} data
73
73
  */
74
74
 
75
75
  /**
76
- * astryx --json theme template
76
+ * xds --json theme template
77
77
  * `written: false` with `reason: 'exists'` is a success: the command is safe to
78
78
  * re-run, and an edited template is the consumer's file to keep.
79
79
  * @typedef {object} ThemeTemplateResponse
@@ -95,19 +95,19 @@
95
95
  */
96
96
 
97
97
  /**
98
- * astryx --json theme targets [filter]
98
+ * xds --json theme targets [filter]
99
99
  * @typedef {object} ThemeTargetsResponse
100
100
  * @property {'theme.targets'} type
101
101
  * @property {{filter: string | null, componentCount: number, targets: ThemeTargetEntry[]}} data
102
102
  */
103
103
 
104
104
  /**
105
- * A color an author pins at one stop of one mode, constraining generation.
105
+ * A generated palette candidate. The palette is still subject to author review
106
+ * and is not connected to runtime theme values.
106
107
  * @typedef {object} TonalPaletteAnchor
107
108
  * @property {'light' | 'dark'} mode Mode containing the anchored stop.
108
109
  * @property {number} stop Existing requested stop where the anchor applies.
109
- * @property {string} color sRGB hex the stop is pulled toward: three or six
110
- * digits, with or without `#`; the generator normalizes it.
110
+ * @property {string} color
111
111
  * @property {'exact' | 'bounded' | 'flexible'} policy `exact` preserves the
112
112
  * chosen color at that stop; `bounded` permits adjustment within `maxDeltaE`;
113
113
  * `flexible` treats the color as guidance and blends toward it.
@@ -116,16 +116,12 @@
116
116
  */
117
117
 
118
118
  /**
119
- * One requested family: a seed color and the constraints applied to its ramp.
120
119
  * @typedef {object} TonalPaletteFamilyInput
121
- * @property {string} id Lower-kebab-case key for the family in the generated
122
- * palette. `black` and `white` are reserved for the standalone values.
123
- * @property {string} seed sRGB hex the ramp is generated from: three or six
124
- * digits, with or without `#`; the generator normalizes it.
125
- * @property {string} [name] Display name for review artifacts; defaults to `id`.
126
- * @property {'chromatic' | 'neutral'} [kind] `neutral` derives the ramp from
127
- * `neutralProfile` instead of the seed hue; defaults to `chromatic`.
128
- * @property {TonalPaletteAnchor[]} [anchors] Colors pinned at specific stops.
120
+ * @property {string} id
121
+ * @property {string} seed
122
+ * @property {string} [name]
123
+ * @property {'chromatic' | 'neutral'} [kind]
124
+ * @property {TonalPaletteAnchor[]} [anchors]
129
125
  */
130
126
 
131
127
  /**
@@ -134,9 +130,6 @@
134
130
  * @property {number} [vibrancy] Chroma control from 0 (most muted) through 50
135
131
  * (default) to 100 (most vivid).
136
132
  * @property {'neutral-v1' | 'warm-v1' | 'cool-v1' | 'custom'} [neutralProfile]
137
- * Hue treatment for `neutral` families: `neutral-v1` is fully achromatic,
138
- * `warm-v1` and `cool-v1` add a slight tint, and `custom` derives the hue from
139
- * the family's own seed. Defaults to `neutral-v1`.
140
133
  * @property {'light-only' | 'dark-only' | 'light-and-dark'} [modeStrategy]
141
134
  * @property {number[]} [stops] Ordered stops shared by every requested family;
142
135
  * defaults to 0 through 100 in increments of 5. Decimal stops are supported,
@@ -144,8 +137,6 @@
144
137
  */
145
138
 
146
139
  /**
147
- * A generated palette candidate. The palette is still subject to author review
148
- * and is not connected to runtime theme values.
149
140
  * @typedef {object} TonalPaletteCandidate
150
141
  * @property {1} schemaVersion
151
142
  * @property {'candidate'} status
@@ -157,68 +148,10 @@
157
148
  */
158
149
 
159
150
  /**
160
- * Per-ramp evidence recorded for one family in one mode.
161
- * @typedef {object} TonalPaletteRampDiagnostics
162
- * @property {boolean} monotonic Whether luminance rises across every stop.
163
- * @property {number} minimumAdjacentDeltaE Smallest perceptual gap between
164
- * neighboring stops; a small value means two stops read as one color.
165
- * @property {number} maximumAdjacentDeltaE Largest gap between neighboring stops.
166
- * @property {number} maximumHueDrift Largest hue distance, in degrees, between
167
- * a stop and the family's reference hue.
168
- * @property {'blue-to-purple' | 'yellow-to-brown' | null} hueIdentityRisk Named
169
- * drift the ramp is at risk of, or `null`.
170
- * @property {number[]} gamutMappedStops Stops whose ideal color fell outside
171
- * sRGB and was mapped back into it.
172
- * @property {Array<TonalPaletteAnchor & {generatedColor: string, deltaE: number}>} anchors
173
- * Each anchor with the color the stop received after its policy was applied
174
- * and the perceptual distance that color still has from the requested target.
175
- */
176
-
177
- /**
178
- * Cross-family evidence for one mode, sampled at the stop nearest 50.
179
- * @typedef {object} TonalPaletteCoordinationDiagnostics
180
- * @property {'light' | 'dark'} mode Mode these samples come from.
181
- * @property {number} stop Sampled stop.
182
- * @property {[string, string] | null} closestFamilies The two chromatic
183
- * families hardest to tell apart, or `null` with fewer than two.
184
- * @property {number | null} minimumFamilyDeltaE Perceptual distance between them.
185
- * @property {string | null} strongestFamily Most saturated family at this stop.
186
- * @property {string | null} weakestFamily Least saturated family at this stop.
187
- * @property {number | null} chromaRatio Strongest chroma over weakest; a large
188
- * ratio means the families are unbalanced.
189
- */
190
-
191
- /**
192
- * The request as the generator resolved it, with every default filled in.
193
- * @typedef {object} TonalPaletteNormalizedRequest
194
- * @property {'astryx-oklch-v1'} recipe
195
- * @property {number} vibrancy
196
- * @property {'neutral-v1' | 'warm-v1' | 'cool-v1' | 'custom'} neutralProfile
197
- * @property {'light-only' | 'dark-only' | 'light-and-dark'} modeStrategy
198
- * @property {number[]} stops
199
- * @property {Array<{id: string, name: string, seed: string, kind: 'chromatic' | 'neutral', anchors: TonalPaletteAnchor[]}>} families
200
- */
201
-
202
- /**
203
- * The detached receipt written beside a candidate. It records what was asked
204
- * for and what the generator observed, so a candidate can be traced back to
205
- * its request without rerunning generation.
206
- * @typedef {object} TonalPaletteGenerationReceipt
207
- * @property {1} schemaVersion
208
- * @property {'astryx-oklch-v1'} recipe Recipe that produced the candidate.
209
- * @property {string} candidateSha256 SHA-256 over the candidate bytes as written.
210
- * @property {{version: string, sha256: string}} [preview] Present when preview
211
- * content was generated for the request, even if no file was written because
212
- * the target already exists.
213
- * @property {TonalPaletteNormalizedRequest} request
214
- * @property {{families: Record<string, {light?: TonalPaletteRampDiagnostics, dark?: TonalPaletteRampDiagnostics}>, coordination: TonalPaletteCoordinationDiagnostics[]}} diagnostics
215
- */
216
-
217
- /**
218
- * astryx --json theme palette generate <config>
151
+ * xds --json theme palette generate <config>
219
152
  * @typedef {object} ThemePaletteGenerateResponse
220
153
  * @property {'theme.palette.generate'} type
221
- * @property {{recipe: 'astryx-oklch-v1', status: 'candidate', familyCount: number, stopCount: number, modes: string[], output: string | null, receipt: string | null, preview: string | null, written: boolean, reason: 'exists' | null, candidate: TonalPaletteCandidate, generationReceipt: TonalPaletteGenerationReceipt}} data
154
+ * @property {{recipe: 'astryx-oklch-v1', status: 'candidate', familyCount: number, stopCount: number, modes: string[], output: string | null, receipt: string | null, preview: string | null, written: boolean, reason: 'exists' | null, candidate: TonalPaletteCandidate, generationReceipt: Record<string, unknown>}} data
222
155
  */
223
156
 
224
157
  // Make this a module so the @typedefs above are importable as types via
@@ -33,10 +33,7 @@ import {
33
33
  } from '../../foundation/agent-docs/agent-docs.mjs';
34
34
  import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
35
35
  import {Project} from '../../foundation/config/project.mjs';
36
- import {
37
- loadIntegrations,
38
- markProviderConflicts,
39
- } from '../../foundation/integrations/integrations.mjs';
36
+ import {loadIntegrations} from '../../foundation/integrations/integrations.mjs';
40
37
  import {warnOnIntegrationIssues} from '../../foundation/integrations/integration-warnings.mjs';
41
38
  import {logger} from '../logger.mjs';
42
39
 
@@ -311,15 +308,6 @@ export async function runCoreCodemods(versionManifests, {apply, path: srcPath, c
311
308
  });
312
309
  }
313
310
 
314
- /**
315
- * One installed package at one version; two specs that reach it share this.
316
- * @param {{name: string, version?: string}} integration
317
- * @returns {string}
318
- */
319
- function packageIdentity(integration) {
320
- return `${integration.name}\u0000${integration.version ?? ''}`;
321
- }
322
-
323
311
  /**
324
312
  * Load the consumer project's config + integrations. Throws on invalid config;
325
313
  * the run leaf decides between the config_fixable preview and a hard abort.
@@ -333,65 +321,11 @@ export async function loadProjectContext(cwd, extraIntegrationSpecs = []) {
333
321
  // cache entry; ordinary Project discovery remains cached by default.
334
322
  const project = await Project.load(cwd, {fresh: true});
335
323
  const postCodemodHooks = project.config.hooks?.postCodemod ?? [];
336
- const configuredSpecs = new Set(project.integrations ?? []);
337
- // Configured packages come from Project, which has already resolved provider
338
- // identity over configured, autolinked, and local packages. Loading them
339
- // again here would let upgrade run codemods from a package Project set aside.
340
- const configured = project.loadedIntegrations.filter(
341
- integration =>
342
- !integration.__autolinked && configuredSpecs.has(integration.__spec),
343
- );
344
- // A package that lists itself runs its installed copy's released codemods,
345
- // never the work in progress being authored, so that copy stands in for it.
346
- const local = project.loadedIntegrations.find(
347
- integration => integration.__local,
348
- );
349
- const selfListed = local != null && configured.includes(local);
350
- if (local != null && selfListed && project.configPath) {
351
- const installed = await loadIntegrations([local.__spec], {
352
- cwd: path.dirname(project.configPath),
353
- resolveProviders: false,
354
- });
355
- configured.splice(configured.indexOf(local), 1, ...installed);
356
- }
357
- const extraSpecs = uniqueFiles(extraIntegrationSpecs ?? []).filter(
358
- spec => !configuredSpecs.has(spec),
359
- );
360
- const extras =
361
- extraSpecs.length === 0
362
- ? []
363
- : await loadIntegrations(extraSpecs, {resolveProviders: false});
364
- // Naming the package being authored with --integration asks for its
365
- // installed copy too, so the local package must not claim against it.
366
- const localStandsIn =
367
- local != null &&
368
- (selfListed || extras.some(extra => extra.name === local.name));
369
- // Autolinked packages and the package being authored join the pass only as
370
- // claimants: every other command uses them for their provider IDs, but
371
- // upgrade has never run their codemods and still does not. An extra that
372
- // names one of them opts it in, so the extra stands in for that claimant.
373
- const extraIdentities = new Set(extras.map(packageIdentity));
374
- const claimantsOnly = project.loadedIntegrations.filter(
375
- integration =>
376
- (integration.__autolinked || (integration.__local && !localStandsIn)) &&
377
- !extraIdentities.has(packageIdentity(integration)),
378
- );
379
- const resolved = markProviderConflicts([
380
- ...configured,
381
- ...claimantsOnly,
382
- ...extras,
324
+ const integrationSpecs = uniqueFiles([
325
+ ...(project.integrations ?? []),
326
+ ...(extraIntegrationSpecs ?? []),
383
327
  ]);
384
- // Claimants leave by package directory, not object identity: the pass can
385
- // return one as a new conflict entry, and upgrade must not warn that a
386
- // package every other command uses contributes nothing.
387
- const claimantDirs = new Set(
388
- claimantsOnly.map(integration => integration.__packageDir),
389
- );
390
- const integrations = resolved.filter(
391
- integration =>
392
- integration.__packageDir == null ||
393
- !claimantDirs.has(integration.__packageDir),
394
- );
328
+ const integrations = await loadIntegrations(integrationSpecs);
395
329
  return {postCodemodHooks, integrations};
396
330
  }
397
331
 
@@ -16,9 +16,8 @@ export const doc = {
16
16
  description:
17
17
  'Migrates project source from a previous Astryx version to the currently ' +
18
18
  'installed one by running the registered codemods, and compares the fully ' +
19
- 'rendered managed agent-docs block on every migration path, including ' +
20
- 'same-Core integration guidance changes; list and registry-only modes do not ' +
21
- 'run migration reconciliation. Dry-run previews without writing; `apply` ' +
19
+ 'rendered managed agent-docs block on every path, including same-Core ' +
20
+ 'integration guidance changes. Dry-run previews without writing; `apply` ' +
22
21
  'writes the prepared block only after selected codemods and hooks succeed. ' +
23
22
  'Core codemods run before ' +
24
23
  'the config is loaded so a config codemod can repair an otherwise-invalid ' +
@@ -69,7 +68,7 @@ export const doc = {
69
68
  name: 'options.integration',
70
69
  type: 'string[]',
71
70
  description:
72
- 'Explicit integration specifiers to process. Resolved beneath node_modules; absolute paths and `.` or `..` segments are rejected.',
71
+ 'Explicit integration package names / file paths to process.',
73
72
  },
74
73
  {
75
74
  name: 'options.path',
@@ -2,7 +2,7 @@
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
4
  /**
5
- * astryx --json upgrade --list
5
+ * xds --json upgrade --list
6
6
  */
7
7
  export type UpgradeListResponse = {
8
8
  type: "upgrade.list";
@@ -121,14 +121,14 @@ export type RegistryCompositionSummary = {
121
121
  items: RegistryCompositionItemSummary[];
122
122
  };
123
123
  /**
124
- * astryx --json upgrade --registry [--apply]
124
+ * xds --json upgrade --registry [--apply]
125
125
  */
126
126
  export type UpgradeRegistryResponse = {
127
127
  type: "upgrade.registry";
128
128
  data: RegistryCompositionSummary;
129
129
  };
130
130
  /**
131
- * astryx --json upgrade [--apply]
131
+ * xds --json upgrade [--apply]
132
132
  */
133
133
  export type UpgradeRunResponse = {
134
134
  type: "upgrade.run";
@@ -150,7 +150,7 @@ export type UpgradeRunResponse = {
150
150
  };
151
151
  };
152
152
  /**
153
- * astryx --json upgrade — short-circuit status results.
153
+ * xds --json upgrade — short-circuit status results.
154
154
  *
155
155
  * - `up_to_date`: `--from` is >= installed target and `--force` was not passed.
156
156
  * - `no_codemods`: no codemods (core or integration) apply to the range.
@@ -211,7 +211,7 @@ export type UpgradeOptions = {
211
211
  */
212
212
  skipCodemod?: string[] | undefined;
213
213
  /**
214
- * Explicit integration specifiers resolved beneath node_modules; absolute paths and `.` or `..` segments are rejected.
214
+ * Explicit integration package names / file paths.
215
215
  */
216
216
  integration?: string[] | undefined;
217
217
  /**
@@ -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
- * 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
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
14
14
  */
15
15
 
16
16
  /**
17
- * astryx --json upgrade --list
17
+ * xds --json upgrade --list
18
18
  * @typedef {object} UpgradeListResponse
19
19
  * @property {'upgrade.list'} type
20
20
  * @property {UpgradeListEntry[]} data
@@ -88,14 +88,14 @@
88
88
  */
89
89
 
90
90
  /**
91
- * astryx --json upgrade --registry [--apply]
91
+ * xds --json upgrade --registry [--apply]
92
92
  * @typedef {object} UpgradeRegistryResponse
93
93
  * @property {'upgrade.registry'} type
94
94
  * @property {RegistryCompositionSummary} data
95
95
  */
96
96
 
97
97
  /**
98
- * astryx --json upgrade [--apply]
98
+ * xds --json upgrade [--apply]
99
99
  * @typedef {object} UpgradeRunResponse
100
100
  * @property {'upgrade.run'} type
101
101
  * @property {object} data
@@ -112,7 +112,7 @@
112
112
  */
113
113
 
114
114
  /**
115
- * astryx --json upgrade — short-circuit status results.
115
+ * xds --json upgrade — short-circuit status results.
116
116
  *
117
117
  * - `up_to_date`: `--from` is >= installed target and `--force` was not passed.
118
118
  * - `no_codemods`: no codemods (core or integration) apply to the range.
@@ -135,7 +135,7 @@
135
135
  * @property {boolean} [force] Run codemods even if `from` >= installed.
136
136
  * @property {string} [codemod] Run a single named transform.
137
137
  * @property {string[]} [skipCodemod] Exclude named codemods (re-run past a failure).
138
- * @property {string[]} [integration] Explicit integration specifiers resolved beneath node_modules; absolute paths and `.` or `..` segments are rejected.
138
+ * @property {string[]} [integration] Explicit integration package names / file paths.
139
139
  * @property {string} [path] Source directory to scan (default `./src`).
140
140
  * @property {boolean} [installDeps] Auto-install jscodeshift without prompting.
141
141
  * @property {boolean} [registry] Reconcile only ShadCN-copied compositions; `from` is not required.
@@ -32,40 +32,6 @@ 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
-
69
35
  /**
70
36
  * Recursively collect codemod module files under a version folder. Returns
71
37
  * entries of {id, file} where id is the extension-less relative path
@@ -83,18 +49,14 @@ function collectCodemodFiles(versionDir) {
83
49
  for (const entry of entries) {
84
50
  const full = path.join(dir, entry.name);
85
51
  if (entry.isDirectory()) {
86
- if (SKIP_DIRS.has(entry.name)) continue;
52
+ if (entry.name === 'node_modules' || entry.name === '.git') continue;
87
53
  walk(full);
88
54
  continue;
89
55
  }
90
56
  const ext = path.extname(entry.name);
91
57
  if (!CODEMOD_EXTENSIONS.includes(ext)) continue;
92
- if (isTestFile(entry.name)) continue;
93
58
  const rel = path.relative(versionDir, full);
94
- const id = rel
95
- .slice(0, rel.length - ext.length)
96
- .split(path.sep)
97
- .join('/');
59
+ const id = rel.slice(0, rel.length - ext.length).split(path.sep).join('/');
98
60
  out.push({id, file: full});
99
61
  }
100
62
  }
@@ -221,61 +221,3 @@ describe('integration codemod discovery', () => {
221
221
  ).rejects.toThrow(/across versions/i);
222
222
  });
223
223
  });
224
-
225
- describe('test files beside a codemod', () => {
226
- // The incident this closes: every .ts/.mjs/.js under a version folder was
227
- // loaded AND VALIDATED as a codemod, so a test file colocated with its
228
- // transform failed validation — and because a definition error is a hard
229
- // error, it took every codemod in that version with it. `astryx upgrade`
230
- // then applied nothing and reported success. Core is immune because its own
231
- // codemods are enumerated in a registry rather than discovered by walking a
232
- // directory, so its colocated tests are simply never visited. Only
233
- // integrations carry the landmine.
234
- const TRANSFORM = `
235
- export default {
236
- type: 'code',
237
- title: 'Drop foo',
238
- transform: (file) => file.source.replace(/foo/g, 'bar'),
239
- };
240
- `;
241
- // Not a codemod: no default export of the right shape. Loading it throws.
242
- const A_TEST = `
243
- import {describe, it, expect} from 'vitest';
244
- describe('drop-foo', () => {
245
- it('drops foo', () => expect(1).toBe(1));
246
- });
247
- `;
248
-
249
- it.each([
250
- ['a .test. sibling', '0.2.0/drop-foo.test.mjs'],
251
- ['a .spec. sibling', '0.2.0/drop-foo.spec.mjs'],
252
- ['a fixture sibling', '0.2.0/drop-foo.fixture.mjs'],
253
- ['a __tests__ directory', '0.2.0/__tests__/drop-foo.mjs'],
254
- ['a __fixtures__ directory', '0.2.0/__fixtures__/input.mjs'],
255
- ])('ignores %s and still discovers the codemod', async (_label, testPath) => {
256
- scaffold({'0.2.0/drop-foo.mjs': TRANSFORM, [testPath]: A_TEST});
257
-
258
- const project = await Project.load(tmpDir);
259
- const byVersion = await discoverIntegrationCodemods(
260
- project.loadedIntegrations,
261
- );
262
-
263
- expect([...byVersion.keys()]).toEqual(['0.2.0']);
264
- expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual(['drop-foo']);
265
- });
266
-
267
- it('a nested helper directory is still walked', async () => {
268
- // Only test and fixture names are skipped. A package that organises its
269
- // transforms into subdirectories keeps working.
270
- scaffold({'0.2.0/imports/drop-foo.mjs': TRANSFORM});
271
-
272
- const project = await Project.load(tmpDir);
273
- const byVersion = await discoverIntegrationCodemods(
274
- project.loadedIntegrations,
275
- );
276
-
277
- expect(byVersion.get('0.2.0').map(entry => entry.id)).toEqual([
278
- 'imports/drop-foo',
279
- ]);
280
- });
281
- });
@@ -3,8 +3,7 @@
3
3
  import {describe, it, expect} from 'vitest';
4
4
 
5
5
  async function applyTransform(source, path = 'test.ts') {
6
- const {default: transform} =
7
- await import('../unwrap-authoring-factories.mjs');
6
+ const {default: transform} = await import('../unwrap-authoring-factories.mjs');
8
7
  const jscodeshift = (await import('jscodeshift')).default;
9
8
  const j = jscodeshift.withParser('tsx');
10
9
  const api = {jscodeshift: j, stats: () => {}, report: () => {}};
@@ -19,7 +18,7 @@ export default createConfig({integrations: ['@acme/widgets']});
19
18
  `;
20
19
  const output = await applyTransform(input);
21
20
  expect(output).not.toContain('createConfig');
22
- expect(output).toContain('export default {');
21
+ expect(output).toContain("export default {");
23
22
  expect(output).toContain("integrations: ['@acme/widgets']");
24
23
  expect(output).not.toContain('type:');
25
24
  });
@@ -133,34 +132,13 @@ export default createComponentDoc();
133
132
  expect(output).toContain("type: 'component'");
134
133
  });
135
134
 
136
- it('leaves same-named factories from unrelated packages unchanged', async () => {
137
- const input = `import {createConfig} from '@acme/eslint';
138
- export default createConfig({strict: true});
139
- `;
140
- expect(await applyTransform(input)).toBe(input);
141
- });
142
-
143
- it('keeps an unrelated same-named import when another factory is migrated', async () => {
144
- const input = `import {createConfig as createLintConfig} from '@acme/eslint';
145
- import {createDoc} from '@astryxdesign/cli/doc';
146
- export const lintConfig = createLintConfig({strict: true});
147
- export const doc = createDoc({name: 'Theming', description: 'How theming works.'});
148
- `;
149
- const output = await applyTransform(input);
150
- expect(output).toContain(
151
- "import {createConfig as createLintConfig} from '@acme/eslint'",
152
- );
153
- expect(output).toContain('createLintConfig({strict: true})');
154
- expect(output).not.toContain('createDoc');
155
- expect(output).toContain("type: 'generic'");
156
- });
157
-
158
135
  it('is a no-op when no authoring factory is imported', async () => {
159
136
  const input = `import {Button} from '@astryxdesign/core';
160
137
  export default Button;
161
138
  `;
162
- const {default: transform} =
163
- await import('../unwrap-authoring-factories.mjs');
139
+ const {default: transform} = await import(
140
+ '../unwrap-authoring-factories.mjs'
141
+ );
164
142
  const jscodeshift = (await import('jscodeshift')).default;
165
143
  const j = jscodeshift.withParser('tsx');
166
144
  const api = {jscodeshift: j, stats: () => {}, report: () => {}};