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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/README.md +117 -79
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/_adapter.d.mts +50 -0
  4. package/api/build/_adapter.mjs +60 -0
  5. package/api/build/build.doc.mjs +16 -9
  6. package/api/build/build.test.mjs +197 -8
  7. package/api/build/build.type.d.mts +91 -2
  8. package/api/build/build.type.mjs +52 -8
  9. package/api/build/help/help.d.mts +12 -5
  10. package/api/build/help/help.mjs +69 -6
  11. package/api/build/kit/kit.d.mts +4 -1
  12. package/api/build/kit/kit.mjs +165 -49
  13. package/api/build/kit/rank.d.mts +44 -0
  14. package/api/build/kit/rank.mjs +432 -0
  15. package/api/build/kit/rank.test.mjs +196 -0
  16. package/api/component/_adapter.d.mts +6 -12
  17. package/api/component/_adapter.mjs +20 -10
  18. package/api/component/component.doc.mjs +13 -3
  19. package/api/component/component.mjs +91 -14
  20. package/api/component/component.test.mjs +38 -0
  21. package/api/component/component.type.d.mts +22 -11
  22. package/api/component/component.type.mjs +32 -24
  23. package/api/component/detail/blocks/blocks.d.mts +2 -1
  24. package/api/component/detail/blocks/blocks.mjs +4 -3
  25. package/api/component/list/list.d.mts +0 -5
  26. package/api/component/list/list.mjs +40 -11
  27. package/api/discover/_adapter.d.mts +114 -6
  28. package/api/discover/_adapter.mjs +372 -17
  29. package/api/discover/_adapter.test.mjs +215 -0
  30. package/api/discover/_catalog-view.d.mts +115 -0
  31. package/api/discover/_catalog-view.mjs +203 -0
  32. package/api/discover/_catalog-view.test.mjs +128 -0
  33. package/api/discover/detail/detail.d.mts +18 -6
  34. package/api/discover/detail/detail.mjs +67 -13
  35. package/api/discover/detail/detail.test.mjs +85 -0
  36. package/api/discover/detail/item/item.d.mts +26 -0
  37. package/api/discover/detail/item/item.mjs +78 -0
  38. package/api/discover/detail/item/item.test.mjs +73 -0
  39. package/api/discover/discover.d.mts +3 -9
  40. package/api/discover/discover.doc.mjs +62 -18
  41. package/api/discover/discover.mjs +220 -36
  42. package/api/discover/discover.test.mjs +11 -2
  43. package/api/discover/discover.type.d.mts +150 -11
  44. package/api/discover/discover.type.mjs +107 -17
  45. package/api/discover/list/list.d.mts +20 -6
  46. package/api/discover/list/list.mjs +45 -12
  47. package/api/discover/list/list.test.mjs +46 -0
  48. package/api/discover/search/search.d.mts +18 -16
  49. package/api/discover/search/search.mjs +102 -56
  50. package/api/discover/search/search.test.mjs +144 -10
  51. package/api/docs/_adapter.d.mts +268 -47
  52. package/api/docs/_adapter.mjs +970 -149
  53. package/api/docs/compiled-topics.test.mjs +78 -0
  54. package/api/docs/detail/detail.d.mts +0 -15
  55. package/api/docs/detail/detail.mjs +22 -78
  56. package/api/docs/detail/section/section.mjs +39 -24
  57. package/api/docs/detail/section/section.test.mjs +19 -9
  58. package/api/docs/docs.d.mts +5 -3
  59. package/api/docs/docs.doc.mjs +39 -17
  60. package/api/docs/docs.mjs +44 -8
  61. package/api/docs/docs.test.mjs +158 -4
  62. package/api/docs/docs.type.d.mts +185 -6
  63. package/api/docs/docs.type.mjs +127 -13
  64. package/api/docs/index/index.mjs +15 -6
  65. package/api/docs/index/index.test.mjs +1 -1
  66. package/api/docs/integration-tree.test.mjs +555 -0
  67. package/api/docs/integrationDocs.test.mjs +14 -14
  68. package/api/docs/list/list.mjs +28 -12
  69. package/api/docs/node/node.d.mts +43 -0
  70. package/api/docs/node/node.mjs +192 -0
  71. package/api/docs/reference-blocks.test.mjs +406 -0
  72. package/api/doctor/doctor.d.mts +54 -4
  73. package/api/doctor/doctor.doc.mjs +1 -0
  74. package/api/doctor/doctor.mjs +332 -21
  75. package/api/doctor/doctor.test.mjs +420 -7
  76. package/api/gap-report/gap-report.doc.mjs +8 -4
  77. package/api/hook/_adapter.mjs +19 -5
  78. package/api/hook/hook.doc.mjs +1 -0
  79. package/api/hook/hook.type.d.mts +3 -3
  80. package/api/hook/hook.type.mjs +11 -11
  81. package/api/hook/list/list.d.mts +1 -1
  82. package/api/hook/list/list.mjs +69 -17
  83. package/api/index.d.mts +1 -1
  84. package/api/index.mjs +1 -0
  85. package/api/init/init.doc.mjs +6 -1
  86. package/api/init/init.test.mjs +41 -1
  87. package/api/init/remove/remove.mjs +1 -1
  88. package/api/init/run/run.mjs +20 -10
  89. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  90. package/api/integration/add-contribution.d.mts +2 -1
  91. package/api/integration/add-contribution.mjs +130 -15
  92. package/api/integration/add-contribution.test.mjs +258 -7
  93. package/api/integration/add-helpers.d.mts +5 -2
  94. package/api/integration/add-helpers.mjs +36 -9
  95. package/api/integration/add-theme.mjs +34 -64
  96. package/api/integration/add-theme.test.mjs +105 -21
  97. package/api/integration/authoring-checks.mjs +138 -28
  98. package/api/integration/authoring-checks.test.mjs +179 -7
  99. package/api/integration/authoring-checks.type.mjs +6 -1
  100. package/api/integration/integration-authoring.type.d.mts +2 -0
  101. package/api/integration/integration-authoring.type.mjs +2 -0
  102. package/api/integration/integration-block-exports.test.mjs +10 -6
  103. package/api/integration/integrationAdd.doc.mjs +14 -4
  104. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  105. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  106. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  107. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  108. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  109. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  110. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  111. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  112. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  113. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  114. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  115. package/api/integration/pack-check.mjs +83 -7
  116. package/api/integration/pack-check.test.mjs +387 -47
  117. package/api/integration/pack-check.type.d.mts +26 -2
  118. package/api/integration/pack-check.type.mjs +14 -1
  119. package/api/integration/summarizeIssues.doc.mjs +1 -0
  120. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  121. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  122. package/api/integration/validate-integration.mjs +52 -102
  123. package/api/integration/validate-integration.test.mjs +179 -26
  124. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  125. package/api/integration/validateIntegration.doc.mjs +3 -2
  126. package/api/json/assertResponse.doc.mjs +1 -0
  127. package/api/json/envelope-types.test.mjs +76 -0
  128. package/api/json/index.ts +2 -0
  129. package/api/json/isError.doc.mjs +1 -0
  130. package/api/json/parseResponse.doc.mjs +3 -2
  131. package/api/layout/_adapter.mjs +20 -5
  132. package/api/layout/expand/expand.mjs +7 -5
  133. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  134. package/api/layout/grammar/grammar.mjs +2 -1
  135. package/api/layout/layoutCheck.doc.mjs +1 -0
  136. package/api/layout/layoutExpand.doc.mjs +2 -1
  137. package/api/layout/layoutGrammar.doc.mjs +1 -0
  138. package/api/search/search-return-type.test.mjs +54 -0
  139. package/api/search/search.d.mts +61 -10
  140. package/api/search/search.doc.mjs +8 -2
  141. package/api/search/search.mjs +471 -83
  142. package/api/search/search.test.mjs +124 -1
  143. package/api/search/search.type.d.mts +14 -2
  144. package/api/search/search.type.mjs +5 -2
  145. package/api/swizzle/copy/copy.mjs +28 -11
  146. package/api/swizzle/swizzle.doc.mjs +2 -1
  147. package/api/swizzle/swizzle.type.d.mts +2 -2
  148. package/api/swizzle/swizzle.type.mjs +2 -2
  149. package/api/template/copy/copy.mjs +17 -23
  150. package/api/template/copy/copy.test.mjs +17 -0
  151. package/api/template/list/list.mjs +1 -0
  152. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  153. package/api/template/template-integration.test.mjs +1072 -3
  154. package/api/template/template-suffix.test.mjs +41 -21
  155. package/api/template/template.doc.mjs +30 -8
  156. package/api/template/template.mjs +45 -8
  157. package/api/template/template.type.d.mts +11 -13
  158. package/api/template/template.type.mjs +15 -14
  159. package/api/theme/_adapter.d.mts +2 -3
  160. package/api/theme/_adapter.mjs +4 -5
  161. package/api/theme/add/add.binary.test.mjs +84 -0
  162. package/api/theme/add/add.mjs +31 -22
  163. package/api/theme/add/add.rollback.test.mjs +158 -0
  164. package/api/theme/add/add.staging.test.mjs +83 -0
  165. package/api/theme/add/add.test.mjs +14 -1
  166. package/api/theme/build/build.family.test.mjs +7 -12
  167. package/api/theme/build/build.mjs +140 -59
  168. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  169. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  170. package/api/theme/build/build.rollback.test.mjs +148 -0
  171. package/api/theme/build/build.test.mjs +127 -0
  172. package/api/theme/build/font-warning.mjs +3 -3
  173. package/api/theme/build/font-warning.test.mjs +5 -2
  174. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  175. package/api/theme/integration-themes.test.mjs +39 -28
  176. package/api/theme/list/list.test.mjs +19 -20
  177. package/api/theme/listThemes.doc.mjs +6 -5
  178. package/api/theme/palette/generate/generate.mjs +8 -3
  179. package/api/theme/palette/generate/generate.test.mjs +96 -0
  180. package/api/theme/palette/generate/generator.d.mts +10 -13
  181. package/api/theme/palette/generate/generator.mjs +15 -4
  182. package/api/theme/palette/generate/generator.test.mjs +10 -0
  183. package/api/theme/template/template.mjs +11 -2
  184. package/api/theme/template/template.test.mjs +20 -0
  185. package/api/theme/theme.type.d.mts +170 -11
  186. package/api/theme/theme.type.mjs +94 -27
  187. package/api/theme/themeAdd.doc.mjs +4 -3
  188. package/api/theme/themeBuild.doc.mjs +8 -4
  189. package/api/theme/themeList.doc.mjs +6 -3
  190. package/api/theme/themeListAvailable.doc.mjs +5 -3
  191. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  192. package/api/theme/themeTargets.doc.mjs +1 -0
  193. package/api/theme/themeTemplate.doc.mjs +6 -2
  194. package/api/upgrade/_adapter.d.mts +32 -5
  195. package/api/upgrade/_adapter.mjs +124 -73
  196. package/api/upgrade/list/list.mjs +2 -1
  197. package/api/upgrade/list/list.test.mjs +73 -0
  198. package/api/upgrade/provider-agreement.test.mjs +152 -0
  199. package/api/upgrade/run/run.mjs +356 -59
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +8 -2
  202. package/api/upgrade/upgrade.type.d.mts +42 -4
  203. package/api/upgrade/upgrade.type.mjs +26 -10
  204. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  205. package/assets/codemods/integration-discovery.mjs +48 -4
  206. package/assets/codemods/integration-discovery.test.mjs +73 -0
  207. package/assets/codemods/integration-runner.mjs +56 -4
  208. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  209. package/assets/codemods/run-codemod.mjs +177 -34
  210. package/assets/codemods/runner.mjs +350 -102
  211. package/assets/codemods/term-log.mjs +32 -8
  212. package/assets/codemods/term-log.test.mjs +19 -1
  213. package/assets/codemods/transform-prop.mjs +109 -0
  214. package/assets/codemods/transform-prop.test.mjs +95 -0
  215. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  216. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  217. package/assets/codemods/transforms/next/index.mjs +19 -1
  218. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  219. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  220. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  221. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  222. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  223. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  224. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  225. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  226. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  227. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  228. package/assets/docs/getting-started.doc.mjs +2 -2
  229. package/assets/docs/internationalization.doc.mjs +7 -5
  230. package/assets/docs/layout.doc.dense.mjs +2 -2
  231. package/assets/docs/layout.doc.mjs +1 -1
  232. package/assets/docs/principles.doc.mjs +6 -6
  233. package/assets/docs/styling-libraries.doc.mjs +4 -4
  234. package/assets/docs/styling.doc.mjs +4 -4
  235. package/assets/docs/theme.doc.mjs +5 -5
  236. package/assets/docs/tokens.doc.mjs +1 -1
  237. package/assets/docs/tree/api.doc.mjs +30 -0
  238. package/assets/docs/tree/cli.doc.mjs +23 -0
  239. package/assets/docs/tree/commands.doc.mjs +25 -0
  240. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +95 -39
  241. package/assets/docs/tree/integrations.test.mjs +62 -0
  242. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  243. package/assets/docs/working-with-ai.doc.mjs +4 -4
  244. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  245. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  246. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  247. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  248. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  249. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  250. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  251. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  252. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  253. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  254. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  255. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  262. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  264. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  265. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  266. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  267. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  268. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  269. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  270. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  271. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  272. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  273. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  274. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  275. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  276. package/authoring/_shared/contract.ts +22 -0
  277. package/authoring/codemod/codemod.doc.mjs +7 -2
  278. package/authoring/codemod/parse.d.mts +8 -8
  279. package/authoring/codemod/parse.mjs +8 -6
  280. package/authoring/codemod/type.ts +12 -0
  281. package/authoring/config/config.doc.mjs +10 -2
  282. package/authoring/config/debug-composition.test.mjs +92 -0
  283. package/authoring/config/parse.d.mts +15 -13
  284. package/authoring/config/parse.mjs +27 -8
  285. package/authoring/config/parse.test.mjs +8 -0
  286. package/authoring/config/type.ts +29 -6
  287. package/authoring/debug/debug.doc.d.mts +11 -0
  288. package/authoring/debug/debug.doc.mjs +182 -0
  289. package/authoring/debug/parse.d.mts +7 -7
  290. package/authoring/debug/parse.mjs +3 -3
  291. package/authoring/discover/discover.doc.d.mts +13 -0
  292. package/authoring/discover/discover.doc.mjs +138 -0
  293. package/authoring/discover/parse.d.mts +24 -0
  294. package/authoring/discover/parse.mjs +128 -0
  295. package/authoring/discover/parse.test.mjs +124 -0
  296. package/authoring/discover/type.ts +87 -0
  297. package/authoring/doctypes/_schema.d.mts +240 -128
  298. package/authoring/doctypes/_schema.mjs +198 -16
  299. package/authoring/doctypes/base/graph-fields.doc.mjs +15 -6
  300. package/authoring/doctypes/base/type.ts +9 -4
  301. package/authoring/doctypes/command/command.doc.mjs +4 -3
  302. package/authoring/doctypes/command/parse.d.mts +2 -2
  303. package/authoring/doctypes/command/parse.mjs +1 -1
  304. package/authoring/doctypes/command/type.ts +4 -4
  305. package/authoring/doctypes/component/component.doc.mjs +5 -2
  306. package/authoring/doctypes/component/parse.d.mts +2 -2
  307. package/authoring/doctypes/component/parse.mjs +1 -1
  308. package/authoring/doctypes/component/type.ts +3 -3
  309. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  310. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  311. package/authoring/doctypes/enum/parse.d.mts +2 -2
  312. package/authoring/doctypes/enum/parse.mjs +1 -1
  313. package/authoring/doctypes/enum/type.ts +2 -2
  314. package/authoring/doctypes/function/function.doc.mjs +7 -2
  315. package/authoring/doctypes/function/parse.d.mts +2 -2
  316. package/authoring/doctypes/function/parse.mjs +1 -1
  317. package/authoring/doctypes/function/type.ts +4 -3
  318. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  319. package/authoring/doctypes/hook/parse.d.mts +2 -2
  320. package/authoring/doctypes/hook/parse.mjs +1 -1
  321. package/authoring/doctypes/hook/type.ts +3 -3
  322. package/authoring/doctypes/legacy.d.mts +6 -6
  323. package/authoring/doctypes/legacy.mjs +3 -3
  324. package/authoring/doctypes/load-contract.test.mjs +233 -0
  325. package/authoring/doctypes/namespace/namespace.doc.mjs +9 -9
  326. package/authoring/doctypes/namespace/parse.d.mts +2 -2
  327. package/authoring/doctypes/namespace/parse.mjs +1 -1
  328. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  329. package/authoring/doctypes/namespace/type.ts +6 -3
  330. package/authoring/doctypes/parse.d.mts +22 -20
  331. package/authoring/doctypes/parse.mjs +19 -14
  332. package/authoring/doctypes/reference/parse.d.mts +2 -2
  333. package/authoring/doctypes/reference/parse.mjs +1 -1
  334. package/authoring/doctypes/reference/reference.doc.mjs +39 -6
  335. package/authoring/doctypes/reference/type.ts +31 -14
  336. package/authoring/doctypes/schema/parse.d.mts +2 -2
  337. package/authoring/doctypes/schema/parse.mjs +1 -1
  338. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  339. package/authoring/doctypes/schema/type.ts +3 -4
  340. package/authoring/doctypes/template/parse.d.mts +94 -1
  341. package/authoring/doctypes/template/parse.mjs +37 -1
  342. package/authoring/doctypes/template/parse.test.mjs +18 -0
  343. package/authoring/doctypes/template/template.doc.mjs +13 -3
  344. package/authoring/doctypes/template/type.ts +12 -1
  345. package/authoring/doctypes/theme/parse.d.mts +35 -0
  346. package/authoring/doctypes/theme/parse.mjs +76 -0
  347. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  348. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  349. package/authoring/doctypes/theme/type.ts +42 -0
  350. package/authoring/doctypes/types.ts +12 -11
  351. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  352. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  353. package/authoring/gap-report/parse.d.mts +9 -9
  354. package/authoring/gap-report/parse.mjs +6 -6
  355. package/authoring/gap-report/type.ts +1 -1
  356. package/authoring/identity/identity.doc.mjs +3 -2
  357. package/authoring/identity/type.ts +10 -10
  358. package/authoring/index.d.mts +2 -0
  359. package/authoring/index.d.ts +32 -19
  360. package/authoring/index.mjs +3 -1
  361. package/authoring/integration/integration.doc.mjs +2 -2
  362. package/authoring/integration/parse.d.mts +2 -2
  363. package/authoring/integration/parse.mjs +1 -1
  364. package/authoring/integration/schema.d.mts +4 -4
  365. package/authoring/integration/schema.mjs +3 -3
  366. package/authoring/integration/type.ts +5 -11
  367. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  368. package/clients/cli/command-load-failure.test.mjs +83 -0
  369. package/clients/cli/commands/blog.doc.mjs +1 -1
  370. package/clients/cli/commands/blog.mjs +23 -8
  371. package/clients/cli/commands/blog.test.mjs +42 -1
  372. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  373. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  374. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  375. package/clients/cli/commands/build-theme.mjs +16 -50
  376. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  377. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  378. package/clients/cli/commands/build.doc.mjs +16 -8
  379. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  380. package/clients/cli/commands/build.mjs +137 -114
  381. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  382. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  383. package/clients/cli/commands/component/index.mjs +3 -8
  384. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  385. package/clients/cli/commands/component-package.test.mjs +46 -0
  386. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  387. package/clients/cli/commands/component.doc.mjs +1 -1
  388. package/clients/cli/commands/component.test.mjs +19 -0
  389. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  390. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  391. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  392. package/clients/cli/commands/discover.doc.mjs +55 -9
  393. package/clients/cli/commands/discover.mjs +393 -118
  394. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  395. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  396. package/clients/cli/commands/docs.doc.mjs +21 -9
  397. package/clients/cli/commands/docs.mjs +184 -70
  398. package/clients/cli/commands/docs.test.mjs +120 -16
  399. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  400. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  401. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  402. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  403. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  404. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  405. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  406. package/clients/cli/commands/doctor.doc.mjs +1 -1
  407. package/clients/cli/commands/doctor.mjs +59 -32
  408. package/clients/cli/commands/doctor.test.mjs +42 -0
  409. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  410. package/clients/cli/commands/gap-report.test.mjs +72 -0
  411. package/clients/cli/commands/hook/index.mjs +7 -17
  412. package/clients/cli/commands/hook.doc.mjs +1 -1
  413. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  414. package/clients/cli/commands/init.doc.mjs +20 -9
  415. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  416. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  417. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  418. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  419. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  420. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  421. package/clients/cli/commands/integration.doc.mjs +1 -1
  422. package/clients/cli/commands/integration.mjs +1 -0
  423. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  424. package/clients/cli/commands/json-contract.test.mjs +33 -0
  425. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  426. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  427. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  428. package/clients/cli/commands/layout.doc.mjs +3 -3
  429. package/clients/cli/commands/layout.mjs +21 -9
  430. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  431. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  432. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  433. package/clients/cli/commands/manifest.doc.mjs +1 -1
  434. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  435. package/clients/cli/commands/search.doc.mjs +7 -4
  436. package/clients/cli/commands/search.mjs +28 -9
  437. package/clients/cli/commands/search.test.mjs +75 -0
  438. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  439. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  440. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  441. package/clients/cli/commands/template.doc.mjs +52 -13
  442. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  443. package/clients/cli/commands/template.mjs +4 -91
  444. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  445. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  446. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  447. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  448. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  449. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  450. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  451. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  452. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  453. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  454. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  455. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  456. package/clients/cli/commands/theme.doc.mjs +1 -1
  457. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  458. package/clients/cli/commands/upgrade.doc.mjs +20 -8
  459. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  460. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  461. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  462. package/clients/cli/commands/upgrade.mjs +29 -7
  463. package/clients/cli/formatters/index.mjs +2 -0
  464. package/clients/cli/formatters/index.test.mjs +6 -0
  465. package/clients/cli/index.mjs +21 -30
  466. package/clients/cli/latest-version-env.test.mjs +50 -0
  467. package/clients/cli/lib/cli-error.test.mjs +7 -0
  468. package/clients/cli/lib/component-format.mjs +9 -9
  469. package/clients/cli/lib/component-format.test.mjs +1 -1
  470. package/clients/cli/lib/define-command.mjs +32 -6
  471. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  472. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  473. package/clients/cli/lib/hook-format.mjs +19 -10
  474. package/clients/cli/lib/json-shim.mjs +38 -2
  475. package/clients/cli/lib/json-shim.test.mjs +83 -0
  476. package/clients/cli/lib/manifest.d.ts +2 -0
  477. package/clients/cli/lib/manifest.mjs +32 -2
  478. package/clients/cli/lib/manifest.test.mjs +17 -0
  479. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  480. package/foundation/agent-docs/agent-docs.mjs +82 -12
  481. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  482. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  483. package/foundation/config/integration-debug.test.mjs +28 -3
  484. package/foundation/config/project-themes.test.mjs +11 -19
  485. package/foundation/config/project.d.mts +20 -11
  486. package/foundation/config/project.mjs +246 -89
  487. package/foundation/config/project.test.mjs +270 -21
  488. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  489. package/foundation/discovery/authoring-self-docs.mjs +38 -15
  490. package/foundation/discovery/authoring-self-docs.test.mjs +87 -12
  491. package/foundation/discovery/authoring-surface.d.mts +74 -0
  492. package/foundation/discovery/authoring-surface.mjs +525 -0
  493. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  494. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  495. package/foundation/discovery/cli-self-docs.mjs +490 -0
  496. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  497. package/foundation/discovery/component-discovery.d.mts +38 -0
  498. package/foundation/discovery/component-discovery.mjs +48 -0
  499. package/foundation/discovery/component-loader.d.mts +35 -38
  500. package/foundation/discovery/component-loader.mjs +53 -222
  501. package/foundation/discovery/docs-discovery.d.mts +114 -9
  502. package/foundation/discovery/docs-discovery.mjs +239 -30
  503. package/foundation/discovery/docs-discovery.test.mjs +150 -35
  504. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  505. package/foundation/discovery/docs-output-budget.mjs +1 -1
  506. package/foundation/discovery/docs-section-key.d.mts +28 -10
  507. package/foundation/discovery/docs-section-key.mjs +134 -33
  508. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  509. package/foundation/discovery/template-adapter.d.mts +113 -11
  510. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  511. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  512. package/foundation/discovery/template-adapter.mjs +772 -82
  513. package/foundation/discovery/template-adapter.test.mjs +57 -0
  514. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  515. package/foundation/discovery/template-conflict-release.mjs +40 -0
  516. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  517. package/foundation/discovery/theme-discovery.d.mts +67 -7
  518. package/foundation/discovery/theme-discovery.mjs +916 -186
  519. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  520. package/foundation/discovery/theming-targets.test.mjs +4 -0
  521. package/foundation/doc-compiler/bundle.d.mts +47 -0
  522. package/foundation/doc-compiler/bundle.mjs +278 -0
  523. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  524. package/foundation/doc-compiler/compile.d.mts +343 -0
  525. package/foundation/doc-compiler/compile.mjs +558 -0
  526. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  527. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  528. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  529. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  530. package/foundation/doc-compiler/import.d.mts +24 -0
  531. package/foundation/doc-compiler/import.mjs +59 -0
  532. package/foundation/doc-compiler/inputs.d.mts +102 -0
  533. package/foundation/doc-compiler/inputs.mjs +291 -0
  534. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  535. package/foundation/doc-compiler/ir.d.mts +22 -0
  536. package/foundation/doc-compiler/ir.mjs +471 -0
  537. package/foundation/doc-compiler/lenses.d.mts +36 -0
  538. package/foundation/doc-compiler/lenses.mjs +173 -0
  539. package/foundation/doc-compiler/links.d.mts +162 -0
  540. package/foundation/doc-compiler/links.mjs +294 -0
  541. package/foundation/doc-compiler/links.test.mjs +192 -0
  542. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  543. package/foundation/doc-compiler/overlays.d.mts +37 -0
  544. package/foundation/doc-compiler/overlays.mjs +206 -0
  545. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  546. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  547. package/foundation/doc-compiler/read.d.mts +127 -0
  548. package/foundation/doc-compiler/read.mjs +325 -0
  549. package/foundation/doc-compiler/read.test.mjs +313 -0
  550. package/foundation/doc-compiler/source.d.mts +33 -0
  551. package/foundation/doc-compiler/source.mjs +128 -0
  552. package/foundation/doc-compiler/tree.d.mts +288 -0
  553. package/foundation/doc-compiler/tree.mjs +876 -0
  554. package/foundation/doc-compiler/tree.test.mjs +598 -0
  555. package/foundation/fs/file-protection.d.mts +33 -0
  556. package/foundation/fs/file-protection.mjs +825 -0
  557. package/foundation/fs/file-protection.test.mjs +250 -0
  558. package/foundation/fs/module-loader.d.mts +1 -0
  559. package/foundation/fs/module-loader.mjs +50 -1
  560. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  561. package/foundation/fs/path-safety.d.mts +3 -2
  562. package/foundation/fs/path-safety.mjs +49 -19
  563. package/foundation/fs/path-safety.test.mjs +50 -0
  564. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  565. package/foundation/integrations/autolink.d.mts +58 -1
  566. package/foundation/integrations/autolink.mjs +143 -52
  567. package/foundation/integrations/autolink.test.mjs +1 -1
  568. package/foundation/integrations/cli-requirement.d.mts +45 -0
  569. package/foundation/integrations/cli-requirement.mjs +154 -0
  570. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  571. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  572. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  573. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  574. package/foundation/integrations/contribution-inventory.mjs +27 -24
  575. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  576. package/foundation/integrations/integration-warnings.d.mts +9 -2
  577. package/foundation/integrations/integration-warnings.mjs +51 -26
  578. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  579. package/foundation/integrations/integrations.d.mts +17 -1
  580. package/foundation/integrations/integrations.mjs +52 -98
  581. package/foundation/integrations/integrations.test.mjs +31 -0
  582. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  583. package/foundation/integrations/provider-resolution.d.mts +152 -0
  584. package/foundation/integrations/provider-resolution.mjs +576 -0
  585. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  586. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  587. package/foundation/integrations/theme-descriptor.mjs +44 -0
  588. package/foundation/integrations/validate-contributions.mjs +121 -29
  589. package/foundation/response/base.d.ts +8 -4
  590. package/foundation/response/error-codes.d.mts +3 -1
  591. package/foundation/response/error-codes.d.ts +2 -0
  592. package/foundation/response/error-codes.doc.mjs +13 -4
  593. package/foundation/response/error-codes.mjs +8 -2
  594. package/foundation/response/error-codes.test.mjs +137 -10
  595. package/foundation/response/json-contract.test.mjs +11 -0
  596. package/foundation/response/json.d.mts +4 -2
  597. package/foundation/response/json.mjs +8 -10
  598. package/foundation/response/response-types.doc.d.mts +5 -1
  599. package/foundation/response/response-types.doc.mjs +37 -22
  600. package/foundation/response/response-types.doc.test.mjs +158 -0
  601. package/foundation/response/response.doc.mjs +1 -1
  602. package/foundation/text/string-utils.d.mts +8 -0
  603. package/foundation/text/string-utils.mjs +40 -10
  604. package/foundation/xle/expand.d.mts +2 -0
  605. package/foundation/xle/expand.mjs +4 -3
  606. package/foundation/xle/expand.test.mjs +54 -0
  607. package/foundation/xle/xle.test.mjs +13 -0
  608. package/package.json +10 -11
  609. package/assets/templates/themes/manifest.json +0 -95
  610. package/clients/cli/lib/update-check.mjs +0 -83
  611. package/clients/cli/lib/update-check.test.mjs +0 -137
  612. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -86,7 +86,8 @@ function serializePalette(palette, indentation = 0) {
86
86
 
87
87
  /** @param {TonalPaletteCandidate} candidate */
88
88
  export function serializePaletteCandidate(candidate) {
89
- return `{\n "schemaVersion": 1,\n "status": "candidate",\n "recipe": ${JSON.stringify(candidate.recipe)},\n "black": ${JSON.stringify(candidate.black)},\n "white": ${JSON.stringify(candidate.white)},\n "stops": ${JSON.stringify(candidate.stops)},\n "palette": ${serializePalette(candidate.palette, 2)}\n}\n`;
89
+ const stops = candidate.stops.map(stop => ` ${JSON.stringify(stop)}`);
90
+ return `{\n "schemaVersion": 1,\n "status": "candidate",\n "recipe": ${JSON.stringify(candidate.recipe)},\n "black": ${JSON.stringify(candidate.black)},\n "white": ${JSON.stringify(candidate.white)},\n "stops": [\n${stops.join(',\n')}\n ],\n "palette": ${serializePalette(candidate.palette, 2)}\n}\n`;
90
91
  }
91
92
 
92
93
  /** @param {TonalPaletteCandidate} candidate @param {string} outputPath */
@@ -100,7 +101,7 @@ function serializeCandidate(candidate, outputPath) {
100
101
  );
101
102
  }
102
103
 
103
- /** @param {PaletteGenerationResult} result @param {string} candidateText @param {string | null} [previewText] */
104
+ /** @param {PaletteGenerationResult} result @param {string} candidateText @param {string | null} [previewText] @returns {import('../../theme.type.mjs').TonalPaletteGenerationReceipt} */
104
105
  function receiptFor(result, candidateText, previewText = null) {
105
106
  return {
106
107
  schemaVersion: 1,
@@ -168,7 +169,11 @@ function existingFileIdentity(filePath) {
168
169
  ) {
169
170
  return null;
170
171
  }
171
- throw error;
172
+ throw new AstryxError(
173
+ `Could not write palette candidate: ${error instanceof Error ? error.message : String(error)}`,
174
+ undefined,
175
+ ERROR_CODES.ERR_WRITE_FAILED,
176
+ );
172
177
  }
173
178
  }
174
179
 
@@ -1,9 +1,11 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
+ import {createHash} from 'node:crypto';
3
4
  import * as fs from 'node:fs';
4
5
  import * as os from 'node:os';
5
6
  import * as path from 'node:path';
6
7
  import {afterEach, describe, expect, it} from 'vitest';
8
+ import {isErrorCode} from '../../../../foundation/response/error-codes.mjs';
7
9
  import {themePaletteGenerate} from './generate.mjs';
8
10
 
9
11
  const temporaryDirectories = [];
@@ -101,6 +103,81 @@ describe('themePaletteGenerate', () => {
101
103
  expect(result.data.receipt).toBe('ocean.palette.receipt.json');
102
104
  });
103
105
 
106
+ it('writes candidate JSON byte-identical to the recipe fixtures', () => {
107
+ const families = [
108
+ {id: 'neutral', name: 'Neutral', seed: '#777777', kind: 'neutral'},
109
+ {id: 'blue', name: 'Blue', seed: '#0074e2'},
110
+ {id: 'orange', name: 'Orange', seed: '#d57113'},
111
+ ];
112
+ const fixtures = [
113
+ [
114
+ {families},
115
+ 3755,
116
+ '11c40191d508274d89d631bb4e1cb662f70ff0dce6c0dec101c317f9f69d3e25',
117
+ ],
118
+ [
119
+ {
120
+ modeStrategy: 'light-only',
121
+ stops: [20, 50, 80],
122
+ families: [
123
+ {
124
+ id: 'blue',
125
+ name: 'Blue',
126
+ seed: '#0074e2',
127
+ anchors: [
128
+ {mode: 'light', stop: 50, color: '#1682d5', policy: 'exact'},
129
+ ],
130
+ },
131
+ ],
132
+ },
133
+ 327,
134
+ 'c42929be3c4b5cb857cada078f62bb5a2242c1a22cfa4ae7546a18592540f7f3',
135
+ ],
136
+ [
137
+ {
138
+ modeStrategy: 'dark-only',
139
+ stops: [40],
140
+ families: [{id: 'red', name: 'Red', seed: '#d62830'}],
141
+ },
142
+ 258,
143
+ '88d3d69865c74c7fb14347b9967575285a7d44ab893087a08bc842bb66b29bbb',
144
+ ],
145
+ [
146
+ {
147
+ stops: [60, 80, 95],
148
+ families: [
149
+ {id: 'green', name: 'Green', seed: '#358a3a'},
150
+ {id: 'teal', name: 'Teal', seed: '#0c7365'},
151
+ {id: 'cyan', name: 'Cyan', seed: '#0c6f82'},
152
+ ],
153
+ },
154
+ 910,
155
+ '873821574fdbe3357304dbc06986bd2e5ec88af80d0f36305626fd826c3cf07b',
156
+ ],
157
+ ];
158
+
159
+ for (const [request, bytes, sha256] of fixtures) {
160
+ const cwd = fixture();
161
+ fs.writeFileSync(
162
+ path.join(cwd, 'palette.config.json'),
163
+ JSON.stringify(request),
164
+ );
165
+
166
+ const printed = themePaletteGenerate('palette.config.json', {}, {cwd});
167
+ expect(printed.data.generationReceipt.candidateSha256).toBe(sha256);
168
+
169
+ const result = themePaletteGenerate(
170
+ 'palette.config.json',
171
+ {out: 'candidate.json'},
172
+ {cwd},
173
+ );
174
+ const written = fs.readFileSync(path.join(cwd, 'candidate.json'));
175
+ expect(written.length).toBe(bytes);
176
+ expect(createHash('sha256').update(written).digest('hex')).toBe(sha256);
177
+ expect(result.data.generationReceipt.candidateSha256).toBe(sha256);
178
+ }
179
+ });
180
+
104
181
  it('preserves mixed decimal and integer stop order in every artifact', () => {
105
182
  const cwd = fixture();
106
183
  fs.writeFileSync(
@@ -267,4 +344,23 @@ describe('themePaletteGenerate', () => {
267
344
  themePaletteGenerate('palette.config.json', {}, {cwd}),
268
345
  ).toThrow('Could not parse palette config');
269
346
  });
347
+
348
+ it('reports an output path it cannot use with a registered error code', () => {
349
+ const cwd = fixture();
350
+ fs.writeFileSync(path.join(cwd, 'blocker'), '');
351
+
352
+ for (const options of [
353
+ {out: 'blocker/ocean.palette.json'},
354
+ {preview: 'blocker/ocean.palette.html'},
355
+ ]) {
356
+ let error;
357
+ try {
358
+ themePaletteGenerate('palette.config.json', options, {cwd});
359
+ } catch (caught) {
360
+ error = caught;
361
+ }
362
+ expect(error).toMatchObject({code: 'ERR_WRITE_FAILED'});
363
+ expect(isErrorCode(error.code)).toBe(true);
364
+ }
365
+ });
270
366
  });
@@ -22,15 +22,17 @@ export function generateTonalPalette(input: import("../../theme.type.mjs").Tonal
22
22
  export function serializeGenerationResult(result: unknown): string;
23
23
  /** @typedef {import('../../theme.type.mjs').TonalPaletteAnchor} TonalPaletteAnchor */
24
24
  /** @typedef {import('../../theme.type.mjs').TonalPaletteGenerationInput} TonalPaletteGenerationInput */
25
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteRampDiagnostics} TonalPaletteRampDiagnostics */
26
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteCoordinationDiagnostics} TonalPaletteCoordinationDiagnostics */
27
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteNormalizedRequest} NormalizedRequest */
25
28
  /** @typedef {[number, number, number]} ColorTriple */
26
29
  /** @typedef {'light' | 'dark'} PaletteMode */
27
30
  /** @typedef {{lightness: number, chroma: number, hue: number}} PolarColor */
28
31
  /** @typedef {TonalPaletteAnchor & {color: string, generatedColor: string, deltaE: number}} AnchorResult */
29
- /** @typedef {{colors: Record<number, string>, diagnostics: Record<string, unknown>}} GeneratedRamp */
32
+ /** @typedef {{colors: Record<number, string>, diagnostics: TonalPaletteRampDiagnostics}} GeneratedRamp */
30
33
  /** @typedef {{id: string, name: string, seed: string, kind: 'chromatic' | 'neutral', anchors: TonalPaletteAnchor[]}} NormalizedFamily */
31
- /** @typedef {{recipe: typeof PALETTE_RECIPE, vibrancy: number, neutralProfile: string, modeStrategy: string, stops: number[], families: NormalizedFamily[]}} NormalizedRequest */
32
34
  /** @typedef {{id: string, name: string, seed: string, light?: GeneratedRamp, dark?: GeneratedRamp}} GeneratedFamily */
33
- /** @typedef {{recipe: typeof PALETTE_RECIPE, status: 'candidate', request: NormalizedRequest, families: GeneratedFamily[], coordination: Record<string, unknown>[], errors: {familyId: string, message: string}[]}} PaletteGenerationResult */
35
+ /** @typedef {{recipe: typeof PALETTE_RECIPE, status: 'candidate', request: NormalizedRequest, families: GeneratedFamily[], coordination: TonalPaletteCoordinationDiagnostics[], errors: {familyId: string, message: string}[]}} PaletteGenerationResult */
34
36
  export const PALETTE_RECIPE: "astryx-oklch-v1";
35
37
  export const PALETTE_BLACK: "#000000";
36
38
  export const PALETTE_WHITE: "#ffffff";
@@ -38,6 +40,9 @@ export const DEFAULT_21_STOPS: readonly number[];
38
40
  export const COMPACT_11_STOPS: readonly number[];
39
41
  export type TonalPaletteAnchor = import("../../theme.type.mjs").TonalPaletteAnchor;
40
42
  export type TonalPaletteGenerationInput = import("../../theme.type.mjs").TonalPaletteGenerationInput;
43
+ export type TonalPaletteRampDiagnostics = import("../../theme.type.mjs").TonalPaletteRampDiagnostics;
44
+ export type TonalPaletteCoordinationDiagnostics = import("../../theme.type.mjs").TonalPaletteCoordinationDiagnostics;
45
+ export type NormalizedRequest = import("../../theme.type.mjs").TonalPaletteNormalizedRequest;
41
46
  export type ColorTriple = [number, number, number];
42
47
  export type PaletteMode = "light" | "dark";
43
48
  export type PolarColor = {
@@ -52,7 +57,7 @@ export type AnchorResult = TonalPaletteAnchor & {
52
57
  };
53
58
  export type GeneratedRamp = {
54
59
  colors: Record<number, string>;
55
- diagnostics: Record<string, unknown>;
60
+ diagnostics: TonalPaletteRampDiagnostics;
56
61
  };
57
62
  export type NormalizedFamily = {
58
63
  id: string;
@@ -61,14 +66,6 @@ export type NormalizedFamily = {
61
66
  kind: "chromatic" | "neutral";
62
67
  anchors: TonalPaletteAnchor[];
63
68
  };
64
- export type NormalizedRequest = {
65
- recipe: typeof PALETTE_RECIPE;
66
- vibrancy: number;
67
- neutralProfile: string;
68
- modeStrategy: string;
69
- stops: number[];
70
- families: NormalizedFamily[];
71
- };
72
69
  export type GeneratedFamily = {
73
70
  id: string;
74
71
  name: string;
@@ -81,7 +78,7 @@ export type PaletteGenerationResult = {
81
78
  status: "candidate";
82
79
  request: NormalizedRequest;
83
80
  families: GeneratedFamily[];
84
- coordination: Record<string, unknown>[];
81
+ coordination: TonalPaletteCoordinationDiagnostics[];
85
82
  errors: {
86
83
  familyId: string;
87
84
  message: string;
@@ -12,15 +12,17 @@ import {
12
12
 
13
13
  /** @typedef {import('../../theme.type.mjs').TonalPaletteAnchor} TonalPaletteAnchor */
14
14
  /** @typedef {import('../../theme.type.mjs').TonalPaletteGenerationInput} TonalPaletteGenerationInput */
15
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteRampDiagnostics} TonalPaletteRampDiagnostics */
16
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteCoordinationDiagnostics} TonalPaletteCoordinationDiagnostics */
17
+ /** @typedef {import('../../theme.type.mjs').TonalPaletteNormalizedRequest} NormalizedRequest */
15
18
  /** @typedef {[number, number, number]} ColorTriple */
16
19
  /** @typedef {'light' | 'dark'} PaletteMode */
17
20
  /** @typedef {{lightness: number, chroma: number, hue: number}} PolarColor */
18
21
  /** @typedef {TonalPaletteAnchor & {color: string, generatedColor: string, deltaE: number}} AnchorResult */
19
- /** @typedef {{colors: Record<number, string>, diagnostics: Record<string, unknown>}} GeneratedRamp */
22
+ /** @typedef {{colors: Record<number, string>, diagnostics: TonalPaletteRampDiagnostics}} GeneratedRamp */
20
23
  /** @typedef {{id: string, name: string, seed: string, kind: 'chromatic' | 'neutral', anchors: TonalPaletteAnchor[]}} NormalizedFamily */
21
- /** @typedef {{recipe: typeof PALETTE_RECIPE, vibrancy: number, neutralProfile: string, modeStrategy: string, stops: number[], families: NormalizedFamily[]}} NormalizedRequest */
22
24
  /** @typedef {{id: string, name: string, seed: string, light?: GeneratedRamp, dark?: GeneratedRamp}} GeneratedFamily */
23
- /** @typedef {{recipe: typeof PALETTE_RECIPE, status: 'candidate', request: NormalizedRequest, families: GeneratedFamily[], coordination: Record<string, unknown>[], errors: {familyId: string, message: string}[]}} PaletteGenerationResult */
25
+ /** @typedef {{recipe: typeof PALETTE_RECIPE, status: 'candidate', request: NormalizedRequest, families: GeneratedFamily[], coordination: TonalPaletteCoordinationDiagnostics[], errors: {familyId: string, message: string}[]}} PaletteGenerationResult */
24
26
 
25
27
  export const PALETTE_RECIPE = 'astryx-oklch-v1';
26
28
  export const PALETTE_BLACK = '#000000';
@@ -35,6 +37,7 @@ export const COMPACT_11_STOPS = Object.freeze([
35
37
 
36
38
  const DARK_CHROMA_FACTOR = 0.85;
37
39
  const RESERVED_FAMILY_IDS = new Set(['black', 'white']);
40
+ const NEUTRAL_PROFILES = ['neutral-v1', 'warm-v1', 'cool-v1', 'custom'];
38
41
 
39
42
  /** @param {number} value @param {number} minimum @param {number} maximum */
40
43
  function clamp(value, minimum, maximum) {
@@ -411,6 +414,7 @@ function buildDiagnostics(colors, stops, sourceHue, gamutMappedStops, anchors) {
411
414
  let minimumAdjacentDeltaE = Number.POSITIVE_INFINITY;
412
415
  let maximumAdjacentDeltaE = 0;
413
416
  let maximumHueDrift = 0;
417
+ /** @type {TonalPaletteRampDiagnostics['hueIdentityRisk']} */
414
418
  let hueIdentityRisk = null;
415
419
  for (let index = 0; index < stops.length; index++) {
416
420
  const stop = stops[index];
@@ -526,6 +530,7 @@ function buildCoordinationDiagnostics(request, families) {
526
530
  chroma: hexToOklch(color).C,
527
531
  };
528
532
  });
533
+ /** @type {[string, string] | null} */
529
534
  let closestFamilies = null;
530
535
  let minimumFamilyDeltaE = Number.POSITIVE_INFINITY;
531
536
  for (let index = 0; index < samples.length; index++) {
@@ -661,11 +666,17 @@ export function normalizeGenerationRequest(input) {
661
666
  anchors,
662
667
  };
663
668
  });
669
+ const neutralProfile = input.neutralProfile ?? 'neutral-v1';
670
+ // The receipt records this request, so an unknown profile fails even when no
671
+ // neutral family reads it.
672
+ if (!NEUTRAL_PROFILES.includes(neutralProfile)) {
673
+ throw new Error(`Unknown neutral profile: ${String(neutralProfile)}`);
674
+ }
664
675
  /** @type {NormalizedRequest} */
665
676
  const request = {
666
677
  recipe: PALETTE_RECIPE,
667
678
  vibrancy: input.vibrancy ?? 50,
668
- neutralProfile: input.neutralProfile ?? 'neutral-v1',
679
+ neutralProfile,
669
680
  modeStrategy,
670
681
  stops,
671
682
  families: normalizedFamilies,
@@ -293,6 +293,16 @@ describe('astryx-oklch-v1 palette generator', () => {
293
293
  ).toThrow('Anchor mode dark is not generated by mode strategy light-only');
294
294
  });
295
295
 
296
+ it('rejects an unknown neutral profile even without a neutral family', () => {
297
+ expect(() =>
298
+ generatePaletteSet({neutralProfile: 'warm-v2', families: [families[1]]}),
299
+ ).toThrow('Unknown neutral profile: warm-v2');
300
+ expect(
301
+ generatePaletteSet({neutralProfile: 'warm-v1', families: [families[1]]})
302
+ .request.neutralProfile,
303
+ ).toBe('warm-v1');
304
+ });
305
+
296
306
  it('normalizes anchor colors in the generation receipt', () => {
297
307
  const result = generatePaletteSet({
298
308
  modeStrategy: 'light-only',
@@ -62,8 +62,17 @@ export function themeTemplate(options = {}) {
62
62
 
63
63
  // Our repo header has no business in someone else's source tree.
64
64
  const contents = stripCopyrightHeader(fs.readFileSync(THEME_TEMPLATE_SRC, 'utf-8'));
65
- fs.mkdirSync(path.dirname(resolved), {recursive: true});
66
- fs.writeFileSync(resolved, contents);
65
+ try {
66
+ fs.mkdirSync(path.dirname(resolved), {recursive: true});
67
+ fs.writeFileSync(resolved, contents);
68
+ } catch (err) {
69
+ const message = err instanceof Error ? err.message : String(err);
70
+ throw new AstryxError(
71
+ `Failed to write the theme template to ${relative}: ${message}`,
72
+ undefined,
73
+ ERROR_CODES.ERR_WRITE_FAILED,
74
+ );
75
+ }
67
76
 
68
77
  return {type: 'theme.template', data: {path: relative, written: true, reason: null}};
69
78
  }
@@ -13,7 +13,9 @@ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
13
13
  import * as fs from 'node:fs';
14
14
  import * as path from 'node:path';
15
15
  import * as os from 'node:os';
16
+ import {themeTemplate as publicThemeTemplate} from '../../index.mjs';
16
17
  import {themeTemplate, THEME_TEMPLATE_DEFAULT_PATH} from './template.mjs';
18
+ import {isErrorCode} from '../../../foundation/response/error-codes.mjs';
17
19
 
18
20
  let tmpDir;
19
21
  beforeEach(() => {
@@ -24,6 +26,10 @@ afterEach(() => {
24
26
  });
25
27
 
26
28
  describe('themeTemplate()', () => {
29
+ it('is available through the public API entry point', () => {
30
+ expect(publicThemeTemplate).toBe(themeTemplate);
31
+ });
32
+
27
33
  it('writes the template and returns a theme.template receipt', () => {
28
34
  const res = themeTemplate({cwd: tmpDir});
29
35
 
@@ -79,4 +85,18 @@ describe('themeTemplate()', () => {
79
85
  );
80
86
  expect(fs.existsSync(path.join(path.dirname(tmpDir), 'escaped.ts'))).toBe(false);
81
87
  });
88
+
89
+ it('reports a failed write with a registered error code', () => {
90
+ fs.writeFileSync(path.join(tmpDir, 'blocker'), '');
91
+
92
+ let error;
93
+ try {
94
+ themeTemplate({cwd: tmpDir, targetPath: 'blocker/theme.ts'});
95
+ } catch (caught) {
96
+ error = caught;
97
+ }
98
+
99
+ expect(error).toMatchObject({code: 'ERR_WRITE_FAILED'});
100
+ expect(isErrorCode(error.code)).toBe(true);
101
+ });
82
102
  });
@@ -2,7 +2,7 @@
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
4
  /**
5
- * xds --json theme build <file>
5
+ * astryx --json theme build <file>
6
6
  */
7
7
  export type ThemeBuildResponse = {
8
8
  /**
@@ -27,7 +27,7 @@ export type ThemeBuildResponse = {
27
27
  };
28
28
  };
29
29
  /**
30
- * xds --json theme build <file> --check
30
+ * astryx --json theme build <file> --check
31
31
  */
32
32
  export type ThemeBuildCheckResponse = {
33
33
  type: "theme.build.check";
@@ -42,7 +42,7 @@ export type ThemeBuildCheckResponse = {
42
42
  };
43
43
  };
44
44
  /**
45
- * xds --json theme build <a> <b> … — several themes in one invocation. Each
45
+ * astryx --json theme build <a> <b> … — several themes in one invocation. Each
46
46
  * result carries the file as it was passed and the receipt a single-file build
47
47
  * would have returned (null when that theme produced no CSS). One file still
48
48
  * returns the bare theme.build / theme.build.check envelope.
@@ -71,14 +71,14 @@ export type ThemeListEntry = {
71
71
  package?: string | undefined;
72
72
  };
73
73
  /**
74
- * xds --json theme list
74
+ * astryx --json theme list
75
75
  */
76
76
  export type ThemeListResponse = {
77
77
  type: "theme.list";
78
78
  data: ThemeListEntry[];
79
79
  };
80
80
  /**
81
- * xds --json theme add <slug>
81
+ * astryx --json theme add <slug>
82
82
  */
83
83
  export type ThemeAddResponse = {
84
84
  type: "theme.add";
@@ -94,7 +94,7 @@ export type ThemeAddResponse = {
94
94
  };
95
95
  };
96
96
  /**
97
- * xds --json theme template
97
+ * astryx --json theme template
98
98
  * `written: false` with `reason: 'exists'` is a success: the command is safe to
99
99
  * re-run, and an edited template is the consumer's file to keep.
100
100
  */
@@ -123,7 +123,7 @@ export type ThemeTargetEntry = {
123
123
  deprecatedFor?: string | undefined;
124
124
  };
125
125
  /**
126
- * xds --json theme targets [filter]
126
+ * astryx --json theme targets [filter]
127
127
  */
128
128
  export type ThemeTargetsResponse = {
129
129
  type: "theme.targets";
@@ -134,8 +134,7 @@ export type ThemeTargetsResponse = {
134
134
  };
135
135
  };
136
136
  /**
137
- * A generated palette candidate. The palette is still subject to author review
138
- * and is not connected to runtime theme values.
137
+ * A color an author pins at one stop of one mode, constraining generation.
139
138
  */
140
139
  export type TonalPaletteAnchor = {
141
140
  /**
@@ -146,6 +145,10 @@ export type TonalPaletteAnchor = {
146
145
  * Existing requested stop where the anchor applies.
147
146
  */
148
147
  stop: number;
148
+ /**
149
+ * sRGB hex the stop is pulled toward: three or six
150
+ * digits, with or without `#`; the generator normalizes it.
151
+ */
149
152
  color: string;
150
153
  /**
151
154
  * `exact` preserves the
@@ -159,11 +162,32 @@ export type TonalPaletteAnchor = {
159
162
  */
160
163
  maxDeltaE?: number | undefined;
161
164
  };
165
+ /**
166
+ * One requested family: a seed color and the constraints applied to its ramp.
167
+ */
162
168
  export type TonalPaletteFamilyInput = {
169
+ /**
170
+ * Lower-kebab-case key for the family in the generated
171
+ * palette. `black` and `white` are reserved for the standalone values.
172
+ */
163
173
  id: string;
174
+ /**
175
+ * sRGB hex the ramp is generated from: three or six
176
+ * digits, with or without `#`; the generator normalizes it.
177
+ */
164
178
  seed: string;
179
+ /**
180
+ * Display name for review artifacts; defaults to `id`.
181
+ */
165
182
  name?: string | undefined;
183
+ /**
184
+ * `neutral` derives the ramp from
185
+ * `neutralProfile` instead of the seed hue; defaults to `chromatic`.
186
+ */
166
187
  kind?: "neutral" | "chromatic" | undefined;
188
+ /**
189
+ * Colors pinned at specific stops.
190
+ */
167
191
  anchors?: TonalPaletteAnchor[] | undefined;
168
192
  };
169
193
  export type TonalPaletteGenerationInput = {
@@ -173,6 +197,11 @@ export type TonalPaletteGenerationInput = {
173
197
  * (default) to 100 (most vivid).
174
198
  */
175
199
  vibrancy?: number | undefined;
200
+ /**
201
+ * Hue treatment for `neutral` families: `neutral-v1` is fully achromatic,
202
+ * `warm-v1` and `cool-v1` add a slight tint, and `custom` derives the hue from
203
+ * the family's own seed. Defaults to `neutral-v1`.
204
+ */
176
205
  neutralProfile?: "custom" | "neutral-v1" | "warm-v1" | "cool-v1" | undefined;
177
206
  modeStrategy?: "light-only" | "dark-only" | "light-and-dark" | undefined;
178
207
  /**
@@ -182,6 +211,10 @@ export type TonalPaletteGenerationInput = {
182
211
  */
183
212
  stops?: number[] | undefined;
184
213
  };
214
+ /**
215
+ * A generated palette candidate. The palette is still subject to author review
216
+ * and is not connected to runtime theme values.
217
+ */
185
218
  export type TonalPaletteCandidate = {
186
219
  schemaVersion: 1;
187
220
  status: "candidate";
@@ -205,7 +238,133 @@ export type TonalPaletteCandidate = {
205
238
  }>;
206
239
  };
207
240
  /**
208
- * xds --json theme palette generate <config>
241
+ * Per-ramp evidence recorded for one family in one mode.
242
+ */
243
+ export type TonalPaletteRampDiagnostics = {
244
+ /**
245
+ * Whether luminance rises across every stop.
246
+ */
247
+ monotonic: boolean;
248
+ /**
249
+ * Smallest perceptual gap between
250
+ * neighboring stops; a small value means two stops read as one color.
251
+ */
252
+ minimumAdjacentDeltaE: number;
253
+ /**
254
+ * Largest gap between neighboring stops.
255
+ */
256
+ maximumAdjacentDeltaE: number;
257
+ /**
258
+ * Largest hue distance, in degrees, between
259
+ * a stop and the family's reference hue.
260
+ */
261
+ maximumHueDrift: number;
262
+ /**
263
+ * Named
264
+ * drift the ramp is at risk of, or `null`.
265
+ */
266
+ hueIdentityRisk: "blue-to-purple" | "yellow-to-brown" | null;
267
+ /**
268
+ * Stops whose ideal color fell outside
269
+ * sRGB and was mapped back into it.
270
+ */
271
+ gamutMappedStops: number[];
272
+ /**
273
+ * Each anchor with the color the stop received after its policy was applied
274
+ * and the perceptual distance that color still has from the requested target.
275
+ */
276
+ anchors: Array<TonalPaletteAnchor & {
277
+ generatedColor: string;
278
+ deltaE: number;
279
+ }>;
280
+ };
281
+ /**
282
+ * Cross-family evidence for one mode, sampled at the stop nearest 50.
283
+ */
284
+ export type TonalPaletteCoordinationDiagnostics = {
285
+ /**
286
+ * Mode these samples come from.
287
+ */
288
+ mode: "light" | "dark";
289
+ /**
290
+ * Sampled stop.
291
+ */
292
+ stop: number;
293
+ /**
294
+ * The two chromatic
295
+ * families hardest to tell apart, or `null` with fewer than two.
296
+ */
297
+ closestFamilies: [string, string] | null;
298
+ /**
299
+ * Perceptual distance between them.
300
+ */
301
+ minimumFamilyDeltaE: number | null;
302
+ /**
303
+ * Most saturated family at this stop.
304
+ */
305
+ strongestFamily: string | null;
306
+ /**
307
+ * Least saturated family at this stop.
308
+ */
309
+ weakestFamily: string | null;
310
+ /**
311
+ * Strongest chroma over weakest; a large
312
+ * ratio means the families are unbalanced.
313
+ */
314
+ chromaRatio: number | null;
315
+ };
316
+ /**
317
+ * The request as the generator resolved it, with every default filled in.
318
+ */
319
+ export type TonalPaletteNormalizedRequest = {
320
+ recipe: "astryx-oklch-v1";
321
+ vibrancy: number;
322
+ neutralProfile: "neutral-v1" | "warm-v1" | "cool-v1" | "custom";
323
+ modeStrategy: "light-only" | "dark-only" | "light-and-dark";
324
+ stops: number[];
325
+ families: Array<{
326
+ id: string;
327
+ name: string;
328
+ seed: string;
329
+ kind: "chromatic" | "neutral";
330
+ anchors: TonalPaletteAnchor[];
331
+ }>;
332
+ };
333
+ /**
334
+ * The detached receipt written beside a candidate. It records what was asked
335
+ * for and what the generator observed, so a candidate can be traced back to
336
+ * its request without rerunning generation.
337
+ */
338
+ export type TonalPaletteGenerationReceipt = {
339
+ schemaVersion: 1;
340
+ /**
341
+ * Recipe that produced the candidate.
342
+ */
343
+ recipe: "astryx-oklch-v1";
344
+ /**
345
+ * SHA-256 over the candidate bytes as written.
346
+ */
347
+ candidateSha256: string;
348
+ /**
349
+ * Present when preview
350
+ * content was generated for the request, even if no file was written because
351
+ * the target already exists.
352
+ */
353
+ preview?: {
354
+ version: string;
355
+ sha256: string;
356
+ } | undefined;
357
+ request: TonalPaletteNormalizedRequest;
358
+ diagnostics: {
359
+ families: Record<string, {
360
+ light?: TonalPaletteRampDiagnostics;
361
+ dark?: TonalPaletteRampDiagnostics;
362
+ }>;
363
+ coordination: TonalPaletteCoordinationDiagnostics[];
364
+ };
365
+ };
366
+ /**
367
+ * astryx --json theme palette generate <config>
209
368
  */
210
369
  export type ThemePaletteGenerateResponse = {
211
370
  type: "theme.palette.generate";
@@ -221,6 +380,6 @@ export type ThemePaletteGenerateResponse = {
221
380
  written: boolean;
222
381
  reason: "exists" | null;
223
382
  candidate: TonalPaletteCandidate;
224
- generationReceipt: Record<string, unknown>;
383
+ generationReceipt: TonalPaletteGenerationReceipt;
225
384
  };
226
385
  };