@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db7b338

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 (276) hide show
  1. package/README.md +22 -1
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +1 -0
  4. package/api/component/component.doc.mjs +1 -0
  5. package/api/discover/discover.doc.mjs +1 -0
  6. package/api/docs/_adapter.d.mts +3 -8
  7. package/api/docs/_adapter.mjs +13 -105
  8. package/api/docs/detail/section/section.mjs +9 -15
  9. package/api/docs/detail/section/section.test.mjs +15 -6
  10. package/api/docs/docs.doc.mjs +1 -0
  11. package/api/docs/list/list.mjs +3 -7
  12. package/api/doctor/doctor.d.mts +25 -3
  13. package/api/doctor/doctor.doc.mjs +1 -0
  14. package/api/doctor/doctor.mjs +186 -14
  15. package/api/doctor/doctor.test.mjs +332 -7
  16. package/api/gap-report/gap-report.doc.mjs +1 -0
  17. package/api/hook/_adapter.mjs +19 -5
  18. package/api/hook/hook.doc.mjs +1 -0
  19. package/api/hook/list/list.d.mts +1 -1
  20. package/api/hook/list/list.mjs +69 -17
  21. package/api/init/init.doc.mjs +1 -0
  22. package/api/integration/add-contribution.mjs +7 -7
  23. package/api/integration/add-contribution.test.mjs +37 -3
  24. package/api/integration/add-theme.mjs +34 -64
  25. package/api/integration/add-theme.test.mjs +105 -21
  26. package/api/integration/authoring-checks.test.mjs +8 -4
  27. package/api/integration/integration-block-exports.test.mjs +10 -6
  28. package/api/integration/integrationAdd.doc.mjs +1 -0
  29. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  30. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  31. package/api/integration/integrationAddComponent.doc.mjs +1 -0
  32. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  33. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  34. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  35. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  36. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  37. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  38. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  39. package/api/integration/pack-check.test.mjs +17 -47
  40. package/api/integration/summarizeIssues.doc.mjs +1 -0
  41. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  42. package/api/integration/validate-integration.mjs +50 -102
  43. package/api/integration/validate-integration.test.mjs +85 -23
  44. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  45. package/api/integration/validateIntegration.doc.mjs +1 -0
  46. package/api/json/assertResponse.doc.mjs +1 -0
  47. package/api/json/isError.doc.mjs +1 -0
  48. package/api/json/parseResponse.doc.mjs +1 -0
  49. package/api/layout/layoutCheck.doc.mjs +1 -0
  50. package/api/layout/layoutExpand.doc.mjs +1 -0
  51. package/api/layout/layoutGrammar.doc.mjs +1 -0
  52. package/api/search/search.doc.mjs +1 -0
  53. package/api/search/search.mjs +16 -6
  54. package/api/swizzle/swizzle.doc.mjs +1 -0
  55. package/api/template/template-suffix.test.mjs +41 -21
  56. package/api/template/template.doc.mjs +1 -0
  57. package/api/theme/_adapter.d.mts +2 -3
  58. package/api/theme/_adapter.mjs +4 -5
  59. package/api/theme/add/add.binary.test.mjs +10 -17
  60. package/api/theme/add/add.test.mjs +14 -1
  61. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  62. package/api/theme/integration-themes.test.mjs +39 -28
  63. package/api/theme/list/list.test.mjs +19 -20
  64. package/api/theme/listThemes.doc.mjs +6 -5
  65. package/api/theme/themeAdd.doc.mjs +4 -3
  66. package/api/theme/themeBuild.doc.mjs +1 -0
  67. package/api/theme/themeList.doc.mjs +6 -3
  68. package/api/theme/themeListAvailable.doc.mjs +5 -3
  69. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  70. package/api/theme/themeTargets.doc.mjs +1 -0
  71. package/api/theme/themeTemplate.doc.mjs +1 -0
  72. package/api/upgrade/_adapter.d.mts +32 -5
  73. package/api/upgrade/_adapter.mjs +97 -69
  74. package/api/upgrade/provider-agreement.test.mjs +152 -0
  75. package/api/upgrade/run/run.mjs +356 -59
  76. package/api/upgrade/upgrade.doc.mjs +6 -1
  77. package/api/upgrade/upgrade.type.d.mts +34 -0
  78. package/api/upgrade/upgrade.type.mjs +15 -0
  79. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  80. package/assets/codemods/integration-discovery.mjs +8 -2
  81. package/assets/codemods/integration-discovery.test.mjs +15 -0
  82. package/assets/codemods/integration-runner.mjs +56 -4
  83. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  84. package/assets/codemods/run-codemod.mjs +177 -34
  85. package/assets/codemods/runner.mjs +350 -102
  86. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  87. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  88. package/assets/codemods/transforms/next/index.mjs +19 -1
  89. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  90. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  91. package/assets/docs/cli-integrations.doc.mjs +30 -30
  92. package/assets/docs/cli.doc.mjs +15 -0
  93. package/assets/docs/theme.doc.mjs +1 -1
  94. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  95. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  96. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  97. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  98. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  99. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  100. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  101. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  102. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  103. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  104. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  105. package/authoring/codemod/codemod.doc.mjs +1 -1
  106. package/authoring/codemod/type.ts +12 -0
  107. package/authoring/config/config.doc.mjs +1 -1
  108. package/authoring/debug/debug.doc.d.mts +11 -0
  109. package/authoring/debug/debug.doc.mjs +182 -0
  110. package/authoring/doctypes/_schema.d.mts +71 -141
  111. package/authoring/doctypes/_schema.mjs +29 -2
  112. package/authoring/doctypes/base/graph-fields.doc.mjs +1 -1
  113. package/authoring/doctypes/command/command.doc.mjs +1 -1
  114. package/authoring/doctypes/command/type.ts +1 -1
  115. package/authoring/doctypes/component/type.ts +2 -2
  116. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  117. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  118. package/authoring/doctypes/enum/type.ts +1 -1
  119. package/authoring/doctypes/function/function.doc.mjs +1 -1
  120. package/authoring/doctypes/function/type.ts +1 -1
  121. package/authoring/doctypes/hook/type.ts +2 -2
  122. package/authoring/doctypes/load-contract.test.mjs +3 -2
  123. package/authoring/doctypes/namespace/namespace.doc.mjs +2 -2
  124. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  125. package/authoring/doctypes/namespace/type.ts +5 -2
  126. package/authoring/doctypes/parse.d.mts +4 -2
  127. package/authoring/doctypes/parse.mjs +10 -5
  128. package/authoring/doctypes/reference/reference.doc.mjs +6 -4
  129. package/authoring/doctypes/reference/type.ts +9 -10
  130. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  131. package/authoring/doctypes/schema/type.ts +1 -2
  132. package/authoring/doctypes/template/template.doc.mjs +3 -3
  133. package/authoring/doctypes/theme/parse.d.mts +35 -0
  134. package/authoring/doctypes/theme/parse.mjs +76 -0
  135. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  136. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  137. package/authoring/doctypes/theme/type.ts +42 -0
  138. package/authoring/doctypes/types.ts +2 -1
  139. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  140. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  141. package/authoring/index.d.mts +1 -0
  142. package/authoring/index.d.ts +7 -4
  143. package/authoring/index.mjs +2 -1
  144. package/authoring/integration/integration.doc.mjs +2 -2
  145. package/authoring/integration/type.ts +3 -9
  146. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  147. package/clients/cli/commands/blog.doc.mjs +1 -1
  148. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  149. package/clients/cli/commands/build-theme.mjs +10 -44
  150. package/clients/cli/commands/build.doc.mjs +1 -1
  151. package/clients/cli/commands/component.doc.mjs +1 -1
  152. package/clients/cli/commands/discover.doc.mjs +1 -1
  153. package/clients/cli/commands/docs.doc.mjs +1 -1
  154. package/clients/cli/commands/docs.mjs +15 -58
  155. package/clients/cli/commands/docs.test.mjs +11 -14
  156. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  157. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  158. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  159. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  160. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  161. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  162. package/clients/cli/commands/doctor.doc.mjs +1 -1
  163. package/clients/cli/commands/gap-report.doc.mjs +1 -1
  164. package/clients/cli/commands/hook.doc.mjs +1 -1
  165. package/clients/cli/commands/init.doc.mjs +1 -1
  166. package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
  167. package/clients/cli/commands/integration-add.doc.mjs +1 -1
  168. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  169. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  170. package/clients/cli/commands/integration.doc.mjs +1 -1
  171. package/clients/cli/commands/layout-check.doc.mjs +1 -1
  172. package/clients/cli/commands/layout-expand.doc.mjs +1 -1
  173. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  174. package/clients/cli/commands/layout.doc.mjs +1 -1
  175. package/clients/cli/commands/manifest.doc.mjs +1 -1
  176. package/clients/cli/commands/search.doc.mjs +1 -1
  177. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  178. package/clients/cli/commands/template.doc.mjs +1 -1
  179. package/clients/cli/commands/text-json-parity.test.mjs +718 -0
  180. package/clients/cli/commands/theme-add.doc.mjs +2 -2
  181. package/clients/cli/commands/theme-build.doc.mjs +1 -1
  182. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  183. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  184. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  185. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  186. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  187. package/clients/cli/commands/theme-template.doc.mjs +1 -1
  188. package/clients/cli/commands/theme.doc.mjs +1 -1
  189. package/clients/cli/commands/upgrade.doc.mjs +3 -2
  190. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  191. package/clients/cli/commands/upgrade.mjs +29 -7
  192. package/clients/cli/formatters/index.mjs +2 -0
  193. package/clients/cli/formatters/index.test.mjs +6 -0
  194. package/clients/cli/lib/hook-format.mjs +14 -5
  195. package/foundation/config/project-themes.test.mjs +11 -19
  196. package/foundation/config/project.d.mts +8 -0
  197. package/foundation/config/project.mjs +50 -21
  198. package/foundation/config/project.test.mjs +3 -16
  199. package/foundation/discovery/authoring-self-docs.d.mts +6 -0
  200. package/foundation/discovery/authoring-self-docs.mjs +17 -7
  201. package/foundation/discovery/authoring-self-docs.test.mjs +3 -2
  202. package/foundation/discovery/authoring-surface.d.mts +74 -0
  203. package/foundation/discovery/authoring-surface.mjs +525 -0
  204. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  205. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  206. package/foundation/discovery/cli-self-docs.mjs +514 -0
  207. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  208. package/foundation/discovery/component-loader.d.mts +35 -38
  209. package/foundation/discovery/component-loader.mjs +53 -222
  210. package/foundation/discovery/docs-discovery.d.mts +3 -2
  211. package/foundation/discovery/docs-discovery.mjs +14 -17
  212. package/foundation/discovery/docs-discovery.test.mjs +15 -15
  213. package/foundation/discovery/docs-section-key.d.mts +19 -8
  214. package/foundation/discovery/docs-section-key.mjs +119 -32
  215. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  216. package/foundation/discovery/template-adapter.d.mts +7 -0
  217. package/foundation/discovery/template-adapter.mjs +27 -40
  218. package/foundation/discovery/template-adapter.test.mjs +15 -0
  219. package/foundation/discovery/theme-discovery.d.mts +67 -7
  220. package/foundation/discovery/theme-discovery.mjs +916 -186
  221. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  222. package/foundation/doc-compiler/bundle.d.mts +47 -0
  223. package/foundation/doc-compiler/bundle.mjs +218 -0
  224. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  225. package/foundation/doc-compiler/compile.d.mts +200 -0
  226. package/foundation/doc-compiler/compile.mjs +259 -9
  227. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  228. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  229. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  230. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  231. package/foundation/doc-compiler/import.d.mts +24 -0
  232. package/foundation/doc-compiler/import.mjs +59 -0
  233. package/foundation/doc-compiler/inputs.d.mts +102 -0
  234. package/foundation/doc-compiler/inputs.mjs +286 -0
  235. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  236. package/foundation/doc-compiler/ir.d.mts +13 -0
  237. package/foundation/doc-compiler/ir.mjs +189 -12
  238. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  239. package/foundation/doc-compiler/overlays.d.mts +37 -0
  240. package/foundation/doc-compiler/overlays.mjs +206 -0
  241. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  242. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  243. package/foundation/doc-compiler/read.d.mts +126 -0
  244. package/foundation/doc-compiler/read.mjs +320 -0
  245. package/foundation/doc-compiler/read.test.mjs +313 -0
  246. package/foundation/doc-compiler/source.d.mts +33 -0
  247. package/foundation/doc-compiler/source.mjs +128 -0
  248. package/foundation/fs/file-protection.d.mts +33 -0
  249. package/foundation/fs/file-protection.mjs +825 -0
  250. package/foundation/fs/file-protection.test.mjs +250 -0
  251. package/foundation/integrations/autolink.d.mts +58 -1
  252. package/foundation/integrations/autolink.mjs +143 -57
  253. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  254. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  255. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  256. package/foundation/integrations/contribution-inventory.mjs +17 -20
  257. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  258. package/foundation/integrations/integrations.d.mts +3 -0
  259. package/foundation/integrations/integrations.mjs +11 -97
  260. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  261. package/foundation/integrations/provider-resolution.d.mts +152 -0
  262. package/foundation/integrations/provider-resolution.mjs +576 -0
  263. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  264. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  265. package/foundation/integrations/theme-descriptor.mjs +44 -0
  266. package/foundation/integrations/validate-contributions.mjs +104 -10
  267. package/foundation/response/error-codes.d.mts +3 -1
  268. package/foundation/response/error-codes.d.ts +2 -0
  269. package/foundation/response/error-codes.doc.mjs +12 -2
  270. package/foundation/response/error-codes.mjs +7 -1
  271. package/foundation/response/error-codes.test.mjs +55 -11
  272. package/foundation/response/response-types.doc.mjs +1 -1
  273. package/foundation/response/response.doc.mjs +1 -1
  274. package/foundation/text/string-utils.mjs +22 -10
  275. package/package.json +10 -9
  276. package/assets/templates/themes/manifest.json +0 -95
@@ -0,0 +1,183 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file SchemaDoc for GapReportHandler, the handler `astryx gap-report` calls.
5
+ * @input The GapReportHandler type beside it (`type.ts`), which `parse.mjs`
6
+ * validates.
7
+ * @output The `gap-report-handler` section of `astryx docs authoring`.
8
+ * @position packages/cli/authoring/gap-report — schema documentation
9
+ */
10
+
11
+ /** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
12
+ export const doc = {
13
+ type: 'schema',
14
+ name: 'gap-report-handler',
15
+ displayName: 'GapReportHandler',
16
+ namespace: 'authoring',
17
+ description:
18
+ 'A handler for `astryx gap-report`: a plain object with an `audience` and a `handle` function. Set it as `gapReport` in astryx.config, or export it as `gapReport` from an integration manifest. Every handler runs: the project handler first, then each integration handler in config order.',
19
+ appliesTo:
20
+ '`gapReport` in astryx.config.*, or the `gapReport` named export of astryx.integration.*',
21
+ fields: [
22
+ {
23
+ name: 'audience',
24
+ type: "'internal' | 'public'",
25
+ description:
26
+ 'Whether the destination is internal to your organization or public. A public handler runs only when the caller agrees; an internal handler always runs.',
27
+ required: true,
28
+ },
29
+ {
30
+ name: 'handle',
31
+ type: '(report: GapReport, context: GapReportHandlerContext) => GapReportHandlerReceipt | Promise<GapReportHandlerReceipt>',
32
+ description:
33
+ 'Gets the report and returns a receipt. It can be async, and the CLI waits at most 30 seconds for it. A throw, a timeout, or an invalid receipt is a failed delivery, and the other handlers still run.',
34
+ required: true,
35
+ fields: [
36
+ {
37
+ name: 'report',
38
+ type: 'GapReport',
39
+ description: 'The report. Each handler gets its own copy.',
40
+ required: true,
41
+ fields: [
42
+ {
43
+ name: 'report.schemaVersion',
44
+ type: '1',
45
+ description: 'Version of the report shape.',
46
+ required: true,
47
+ },
48
+ {
49
+ name: 'report.component',
50
+ type: 'string',
51
+ description: 'The component the gap is about.',
52
+ required: true,
53
+ },
54
+ {
55
+ name: 'report.category',
56
+ type: 'GapReportCategory',
57
+ description:
58
+ "The kind of gap: 'missing_component', 'missing_variant', 'layout_gap', 'styling_gap', 'a11y_gap', 'api_friction', 'docs_gap', or 'other'.",
59
+ required: true,
60
+ },
61
+ {
62
+ name: 'report.categoryLabel',
63
+ type: 'string',
64
+ description: 'A readable name for the category.',
65
+ required: true,
66
+ },
67
+ {
68
+ name: 'report.intention',
69
+ type: 'string',
70
+ description: 'What the caller was trying to do.',
71
+ required: true,
72
+ },
73
+ {
74
+ name: 'report.detail',
75
+ type: 'string',
76
+ description: 'More detail, when the caller gave some.',
77
+ },
78
+ {
79
+ name: 'report.source',
80
+ type: 'DebugInvocationSource',
81
+ description:
82
+ "Who sent the report: 'human', 'ai', 'automation', or 'unknown'.",
83
+ required: true,
84
+ },
85
+ {
86
+ name: 'report.timestamp',
87
+ type: 'string',
88
+ description: 'When the report was sent, as ISO 8601.',
89
+ required: true,
90
+ },
91
+ {
92
+ name: 'report.target',
93
+ type: 'GapReportTarget',
94
+ description: 'The package the report is about.',
95
+ required: true,
96
+ fields: [
97
+ {
98
+ name: 'report.target.package',
99
+ type: 'string',
100
+ description: 'The package name.',
101
+ required: true,
102
+ },
103
+ {
104
+ name: 'report.target.version',
105
+ type: 'string',
106
+ description:
107
+ 'The installed version. Null when it is not known.',
108
+ required: true,
109
+ },
110
+ {
111
+ name: 'report.target.issuesUrl',
112
+ type: 'string',
113
+ description:
114
+ 'Where the package takes issues. Null when it does not say.',
115
+ required: true,
116
+ },
117
+ ],
118
+ },
119
+ ],
120
+ },
121
+ {
122
+ name: 'context',
123
+ type: 'GapReportHandlerContext',
124
+ description: 'The context of this call.',
125
+ required: true,
126
+ fields: [
127
+ {
128
+ name: 'context.signal',
129
+ type: 'AbortSignal',
130
+ description: 'Aborted when the handler runs past 30 seconds.',
131
+ required: true,
132
+ },
133
+ ],
134
+ },
135
+ ],
136
+ },
137
+ ],
138
+ examples: [
139
+ {
140
+ label: 'A project handler in astryx.config',
141
+ code:
142
+ 'export default {\n' +
143
+ ' gapReport: {\n' +
144
+ " audience: 'internal',\n" +
145
+ ' async handle(report, {signal}) {\n' +
146
+ ' const url = await fileIssue(report, {signal});\n' +
147
+ " return {status: 'filed', url};\n" +
148
+ ' },\n' +
149
+ ' },\n' +
150
+ '};',
151
+ },
152
+ ],
153
+ notes: [
154
+ {
155
+ type: 'table',
156
+ headers: ['Receipt field', 'Type', 'Required', 'Description'],
157
+ rows: [
158
+ [
159
+ 'status',
160
+ "'filed' | 'routed_only' | 'skipped'",
161
+ 'yes',
162
+ "'filed': the handler created or queued the report. 'routed_only': it points to a place to file the report, and must return `url`. 'skipped': it chose not to act, for example on a duplicate.",
163
+ ],
164
+ [
165
+ 'url',
166
+ 'string',
167
+ 'no',
168
+ 'An http or https URL. Required when status is routed_only.',
169
+ ],
170
+ [
171
+ 'message',
172
+ 'string',
173
+ 'no',
174
+ 'A readable message of at most 2000 characters.',
175
+ ],
176
+ ],
177
+ },
178
+ {
179
+ type: 'prose',
180
+ text: 'The receipt is strict: an unknown field, a URL that is not http or https, or a filed or routed_only receipt with neither `url` nor `message` is invalid.',
181
+ },
182
+ ],
183
+ };
@@ -15,5 +15,6 @@ export { parseSchema } from "./doctypes/schema/parse.mjs";
15
15
  export { parseCommand } from "./doctypes/command/parse.mjs";
16
16
  export { parseEnum } from "./doctypes/enum/parse.mjs";
17
17
  export { parseNamespace } from "./doctypes/namespace/parse.mjs";
18
+ export { parseTheme } from "./doctypes/theme/parse.mjs";
18
19
  export { parseLegacyDoc } from "./doctypes/legacy.mjs";
19
20
  export { parseGapReportHandler, parseGapReportReceipt } from "./gap-report/parse.mjs";
@@ -23,15 +23,16 @@
23
23
  // ═══════════════════════════════════════════════════════════════════════
24
24
  // AUTHOR THESE — each is the default export of one authored file.
25
25
  // ═══════════════════════════════════════════════════════════════════════
26
- export type {ComponentDoc} from './doctypes/types.js'; // Button.doc.{ts,mjs}
27
- export type {HookDoc} from './doctypes/types.js'; // useToast.doc.{ts,mjs}
26
+ export type {ComponentDoc} from './doctypes/types.js'; // Button.doc.mjs
27
+ export type {HookDoc} from './doctypes/types.js'; // useToast.doc.mjs
28
28
  export type {FunctionDoc} from './doctypes/types.js'; // search.doc.mjs (hook | api)
29
- export type {ReferenceDoc} from './doctypes/types.js'; // theming.doc.{ts,mjs}
30
- export type {TemplateDoc} from './doctypes/types.js'; // Foo.template.{ts,mjs}
29
+ export type {ReferenceDoc} from './doctypes/types.js'; // theming.doc.mjs
30
+ export type {TemplateDoc} from './doctypes/types.js'; // Foo.doc.mjs
31
31
  export type {SchemaDoc} from './doctypes/types.js'; // config.doc.mjs (object shape)
32
32
  export type {CommandDoc} from './doctypes/types.js'; // search.doc.mjs (CLI command)
33
33
  export type {EnumDoc} from './doctypes/types.js'; // error-codes.doc.mjs (vocabulary)
34
34
  export type {NamespaceDoc} from './doctypes/types.js'; // cli.doc.mjs (hierarchy)
35
+ export type {ThemeDoc} from './doctypes/types.js'; // oceanTheme.doc.mjs
35
36
  export type {AstryxConfig} from './config/type.js'; // astryx.config.{ts,mjs}
36
37
  export type {DebugEvent} from './debug/type.js'; // one recorded CLI run
37
38
  export type {AstryxIntegration} from './integration/type.js'; // astryx.integration.{ts,mjs}
@@ -58,6 +59,7 @@ export {parseSchema} from './doctypes/schema/parse.mjs';
58
59
  export {parseCommand} from './doctypes/command/parse.mjs';
59
60
  export {parseEnum} from './doctypes/enum/parse.mjs';
60
61
  export {parseNamespace} from './doctypes/namespace/parse.mjs';
62
+ export {parseTheme} from './doctypes/theme/parse.mjs';
61
63
  export {parseLegacyDoc} from './doctypes/legacy.mjs';
62
64
  export {parseConfig} from './config/parse.mjs';
63
65
  export {parseIntegration} from './integration/parse.mjs';
@@ -129,6 +131,7 @@ export type {
129
131
  // reference
130
132
  ReferenceSection,
131
133
  ReferenceContentBlock,
134
+ GraphContentBlock,
132
135
  ReferenceTokenPreviewType,
133
136
  ReferenceTranslationDoc,
134
137
  WorkflowStep,
@@ -11,7 +11,7 @@
11
11
  * `type` directly.
12
12
  *
13
13
  * Types (config, integration, codemod, and the doc vocabulary —
14
- * component/hook/reference/template) are re-exported via `./index.ts`.
14
+ * component/hook/reference/template/theme) are re-exported via `./index.ts`.
15
15
  */
16
16
 
17
17
  export {parseConfig} from './config/parse.mjs';
@@ -32,4 +32,5 @@ export {parseSchema} from './doctypes/schema/parse.mjs';
32
32
  export {parseCommand} from './doctypes/command/parse.mjs';
33
33
  export {parseEnum} from './doctypes/enum/parse.mjs';
34
34
  export {parseNamespace} from './doctypes/namespace/parse.mjs';
35
+ export {parseTheme} from './doctypes/theme/parse.mjs';
35
36
  export {parseLegacyDoc} from './doctypes/legacy.mjs';
@@ -11,7 +11,7 @@ export const doc = {
11
11
  type: 'schema',
12
12
  name: 'integration',
13
13
  displayName: 'Astryx Integration',
14
- namespace: 'cli',
14
+ namespace: 'authoring',
15
15
  description:
16
16
  'The astryx.integration.* manifest that sits beside an integration ' +
17
17
  "package's package.json. It can preserve a stable provider identity across a package rename, " +
@@ -57,7 +57,7 @@ export const doc = {
57
57
  name: 'themes',
58
58
  type: 'string',
59
59
  description:
60
- 'Relative path to a source-theme catalog root containing manifest.json plus one directory per theme slug. Installed themes appear in `astryx theme list` and can be copied with `astryx theme add`.',
60
+ 'Relative path to a source-theme root with one directory per theme slug. Each directory contains a source module and mandatory same-stem, strongly typed .doc.mjs descriptor. Installed themes appear in `astryx theme list` and can be copied with `astryx theme add`.',
61
61
  example: "'./themes'",
62
62
  },
63
63
  {
@@ -34,15 +34,9 @@ export interface AstryxIntegration {
34
34
  * serves from `astryx docs`, alongside the built-in ones. A topic may also
35
35
  * `replace` or `extend` a built-in topic; see the ReferenceDoc type. */
36
36
  docs?: string;
37
- /** Relative path to the source-theme catalog root (resolved to absolute).
38
- * The root contains `manifest.json` plus one directory per theme slug.
39
- * `manifest.json` is `{ "version": 1, "themes": [...] }` where each
40
- * entry requires `slug`, `displayName`, `description` (string),
41
- * `maintained` (boolean), `entry` (source file relative to `themes/<slug>/`),
42
- * `exportName` (a valid JS identifier naming the runtime export), and
43
- * `files` (non-empty array of filenames relative to `themes/<slug>/`).
44
- * Every file listed must exist on disk; the entry file must also appear
45
- * in `files`. */
37
+ /** Relative path to the source-theme root (resolved to absolute). Each
38
+ * lower-kebab theme directory contains a source module and mandatory
39
+ * same-stem, strongly typed `.doc.mjs` descriptor. */
46
40
  themes?: string;
47
41
  /** Static package guidance appended to the CLI-owned managed agent block. */
48
42
  agentDocs?: {
@@ -3,37 +3,35 @@
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import {describe, it, expect} from 'vitest';
6
-
7
- describe('@astryxdesign/cli Theme Manifest & Template Validation', () => {
8
- const manifestPath = path.resolve(
9
- 'packages/cli/assets/templates/themes/manifest.json',
10
- );
11
-
12
- it('validates theme manifest existence and structure', () => {
13
- expect(fs.existsSync(manifestPath)).toBe(true);
14
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
15
-
16
- expect(manifest.version).toBe(1);
17
- expect(Array.isArray(manifest.themes)).toBe(true);
18
- expect(manifest.themes.length).toBeGreaterThan(0);
19
- });
20
-
21
- it('verifies all referenced theme files exist', () => {
22
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
23
- const themesDir = path.dirname(manifestPath);
24
-
25
- for (const theme of manifest.themes) {
26
- expect(theme.slug).toBeDefined();
27
- expect(theme.displayName).toBeDefined();
28
- expect(theme.entry).toBeDefined();
29
-
30
- const entryPath = path.join(themesDir, theme.slug, theme.entry);
31
- expect(fs.existsSync(entryPath)).toBe(true);
32
-
6
+ import {discoverBundledThemes} from '../../../foundation/discovery/theme-discovery.mjs';
7
+
8
+ describe('@astryxdesign/cli bundled theme descriptor validation', () => {
9
+ it('discovers typed descriptors and their same-stem source files', () => {
10
+ const themes = discoverBundledThemes();
11
+ expect(themes.length).toBeGreaterThan(0);
12
+
13
+ for (const theme of themes) {
14
+ expect(theme.slug).toBeTruthy();
15
+ expect(theme.displayName).toBeTruthy();
16
+ expect(theme.docPath).toBe(
17
+ path.join(
18
+ theme.sourceDir,
19
+ `${path.basename(theme.entry, path.extname(theme.entry))}.doc.mjs`,
20
+ ),
21
+ );
22
+ expect(fs.existsSync(theme.docPath)).toBe(true);
23
+ expect(fs.existsSync(path.join(theme.sourceDir, theme.entry))).toBe(true);
33
24
  for (const file of theme.files) {
34
- const filePath = path.join(themesDir, theme.slug, file);
35
- expect(fs.existsSync(filePath)).toBe(true);
25
+ expect(fs.existsSync(path.join(theme.sourceDir, file))).toBe(true);
36
26
  }
37
27
  }
38
28
  });
29
+
30
+ it('does not ship the obsolete central theme catalog', () => {
31
+ expect(
32
+ fs.existsSync(
33
+ path.resolve('packages/cli/assets/templates/themes/manifest.json'),
34
+ ),
35
+ ).toBe(false);
36
+ });
39
37
  });
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'blog',
14
14
  displayName: 'astryx blog',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary: 'Read the Astryx blog from the published feed',
17
17
  description:
18
18
  'Reads the design-system blog over its published RSS feed (never the source ' +
@@ -3,7 +3,8 @@
3
3
  /**
4
4
  * @file Ensures `astryx theme build` preserves AST-012 adaptation semantics.
5
5
  * Runtime and static output share core's compiler; this suite guards the CLI
6
- * loading, diagnostics, serialization, and extension boundaries around it.
6
+ * loading, diagnostics, serialization, and extension boundaries around it,
7
+ * including root component overrides underneath adapted typography scales.
7
8
  */
8
9
 
9
10
  import {afterEach, beforeAll, beforeEach, describe, expect, it} from 'vitest';
@@ -94,6 +95,104 @@ describe('theme build adaptations', () => {
94
95
  );
95
96
  });
96
97
 
98
+ it.each([
99
+ ['defined', writeTheme],
100
+ ['plain', writePlainTheme],
101
+ ])(
102
+ 'preserves component pins in %s themes and built extensions',
103
+ async (_kind, write) => {
104
+ const {defineTheme, generateAdaptationCSS, generateThemeCSS} =
105
+ await import('@astryxdesign/core/theme');
106
+ const project = path.join(tmpDir, 'project');
107
+ const themesDir = path.join(project, 'themes');
108
+ const displayFamily =
109
+ 'Sarina, "Brush Script MT", "Snell Roundhand", cursive';
110
+ const input = {
111
+ name: 'adaptive-display',
112
+ typography: {
113
+ scale: {base: 16, ratio: 1.25},
114
+ body: {family: 'Outfit', fallbacks: 'sans-serif'},
115
+ },
116
+ components: {
117
+ text: Object.fromEntries(
118
+ ['display-1', 'display-2', 'display-3'].map(type => [
119
+ `type:${type}`,
120
+ {fontFamily: displayFamily},
121
+ ]),
122
+ ),
123
+ button: {base: {borderRadius: '12px'}},
124
+ },
125
+ adaptations: {
126
+ rules: [
127
+ {
128
+ when: {width: {below: 'md'}, pointer: 'coarse'},
129
+ value: {typography: {scale: {base: 14, ratio: 1.2}}},
130
+ },
131
+ {
132
+ when: {contrast: 'more'},
133
+ value: {
134
+ typography: {scale: {base: 15}},
135
+ components: {
136
+ text: {'type:display-1': {fontFamily: 'monospace'}},
137
+ },
138
+ },
139
+ },
140
+ ],
141
+ },
142
+ };
143
+ const themeFile = write(themesDir, input.name, JSON.stringify(input));
144
+ const result = await build(project, themeFile);
145
+ expect(result.code, result.stderr).toBe(0);
146
+ const css = fs.readFileSync(
147
+ path.join(themesDir, 'adaptive-display.css'),
148
+ 'utf8',
149
+ );
150
+ const compact = value => value.replace(/\s+/g, ' ').trim();
151
+ const source = defineTheme(input);
152
+ const runtime = generateThemeCSS(source);
153
+ // The CLI wraps root, adaptation, and surface CSS in separate @layer
154
+ // blocks; their contents and order must still match runtime output.
155
+ const adaptationCSS = generateAdaptationCSS(source).component;
156
+ const [rootCSS, surfaceCSS] = runtime.component.split(adaptationCSS);
157
+ const blocks = [rootCSS, adaptationCSS, surfaceCSS].map(compact);
158
+ let previousIndex = -1;
159
+ for (const block of blocks) {
160
+ expect(compact(css)).toContain(block);
161
+ const index = compact(css).indexOf(block);
162
+ expect(index).toBeGreaterThan(previousIndex);
163
+ previousIndex = index;
164
+ }
165
+ expect(compact(css)).toContain(compact(runtime.prose));
166
+ const scaleBlock = css.slice(
167
+ css.indexOf('@media (width < 768px) and (pointer: coarse)'),
168
+ css.indexOf('@media (prefers-contrast: more)'),
169
+ );
170
+ expect(scaleBlock).toContain('--font-size-base: 0.875rem');
171
+ expect(scaleBlock).not.toContain('.astryx-text');
172
+ expect(scaleBlock).not.toContain('.astryx-heading');
173
+ expect(scaleBlock).not.toContain('.astryx-button');
174
+ expect(css).toContain(`font-family: ${displayFamily};`);
175
+ expect(css).toContain('font-family: monospace;');
176
+
177
+ const {adaptiveDisplayTheme: builtTheme} = await import(
178
+ pathToFileURL(path.join(themesDir, 'adaptive-display.js')).href
179
+ );
180
+ expect(builtTheme.__adaptationRules).toBeUndefined();
181
+ expect(generateThemeCSS(builtTheme)).toEqual(runtime);
182
+ const childInput = {
183
+ name: 'display-child',
184
+ components: {text: {'type:display-2': {fontFamily: 'serif'}}},
185
+ };
186
+ const fromSource = defineTheme({...childInput, extends: source});
187
+ const fromBuilt = defineTheme({...childInput, extends: builtTheme});
188
+ expect(generateThemeCSS(fromBuilt)).toEqual(generateThemeCSS(fromSource));
189
+ expect(fromBuilt.__adaptationRules[0].components).toBeUndefined();
190
+ expect(fromBuilt.components.text['type:display-2'].fontFamily).toBe(
191
+ 'serif',
192
+ );
193
+ },
194
+ );
195
+
97
196
  it('resolves a plain object whose only input-only field is adaptations', async () => {
98
197
  const project = path.join(tmpDir, 'project');
99
198
  const themesDir = path.join(project, 'themes');
@@ -33,7 +33,7 @@ import {fileURLToPath} from 'node:url';
33
33
  import {spawn} from 'node:child_process';
34
34
  import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
35
35
  import {jsonOut} from '../../../foundation/response/json.mjs';
36
- import {emit, section, text, list, code} from '../formatters/index.mjs';
36
+ import {emit, section, text, list, records, code} from '../formatters/index.mjs';
37
37
  import {logger} from '../../../api/logger.mjs';
38
38
  import {cliError} from '../lib/cli-error.mjs';
39
39
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
@@ -229,47 +229,6 @@ function printThemeList(themes) {
229
229
  );
230
230
  }
231
231
 
232
- /**
233
- * Render the targets as one greppable line each, under an aligned header. A
234
- * `records()` block would be five lines per target — over a thousand for the
235
- * full surface, which is the view this command exists to make readable.
236
- * @param {import('../../../api/theme/theme.type.mjs').ThemeTargetEntry[]} targets
237
- * @returns {string}
238
- */
239
- function formatTargetsTable(targets) {
240
- const rows = targets.map(t => ({
241
- key: t.deprecatedFor
242
- ? `${t.key} [deprecated; use ${t.deprecatedFor}]`
243
- : t.key,
244
- component: t.component,
245
- props: t.props.join(', ') || '-',
246
- states: t.states.join(', ') || '-',
247
- }));
248
- const head = {
249
- key: 'key',
250
- component: 'component',
251
- props: 'props',
252
- states: 'states',
253
- };
254
- const width = (/** @type {'key'|'component'|'props'} */ field) =>
255
- [head, ...rows].reduce((max, r) => Math.max(max, r[field].length), 0);
256
- const w = {
257
- key: width('key'),
258
- component: width('component'),
259
- props: width('props'),
260
- };
261
- const line = (/** @type {typeof head} */ r) =>
262
- [
263
- r.key.padEnd(w.key),
264
- r.component.padEnd(w.component),
265
- r.props.padEnd(w.props),
266
- r.states,
267
- ]
268
- .join(' ')
269
- .trimEnd();
270
- return [line(head), ...rows.map(line)].join('\n');
271
- }
272
-
273
232
  /**
274
233
  * @param {import('commander').Command} program
275
234
  */
@@ -811,9 +770,16 @@ export function registerTheme(program) {
811
770
  emit(
812
771
  section(
813
772
  'Theming targets',
814
- `${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}`,
773
+ `${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}\n(key - component - props - states - className - deprecatedFor)`,
815
774
  ),
816
- text(formatTargetsTable(targets)),
775
+ records(targets, {
776
+ fields: ['key', 'component', 'props', 'states', 'className', 'deprecatedFor'],
777
+ layout: 'inline',
778
+ format: {
779
+ deprecatedFor: (/** @type {string|null} */ v) =>
780
+ v ? `deprecated; use ${v}` : '',
781
+ },
782
+ }),
817
783
  text(
818
784
  [
819
785
  `Each key goes under \`components\` in defineTheme; it paints \`.astryx-<key>\`.`,
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'build',
14
14
  displayName: 'astryx build',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary:
17
17
  'Build a page: composition kit for an idea, or the workflow playbook (no args)',
18
18
  description:
@@ -13,7 +13,7 @@ export const doc = {
13
13
  type: 'command',
14
14
  name: 'component',
15
15
  displayName: 'astryx component',
16
- namespace: 'cli',
16
+ namespace: 'cli/commands',
17
17
  summary: 'List components or print component docs',
18
18
  description:
19
19
  'Resolves a component by name across core and integration packages and prints ' +
@@ -13,7 +13,7 @@ export const doc = {
13
13
  type: 'command',
14
14
  name: 'discover',
15
15
  displayName: 'astryx discover',
16
- namespace: 'cli',
16
+ namespace: 'cli/commands',
17
17
  summary: 'Discover external packages and components',
18
18
  description:
19
19
  'Explores components contributed by configured external packages and integrations. ' +
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'docs',
14
14
  displayName: 'astryx docs',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary: 'Print reference docs',
17
17
  description:
18
18
  'Reads the reference docs: with no topic it lists every topic; a topic prints that ' +