@astryxdesign/cli 0.3.0-canary.c857354 → 0.3.0-canary.ccb5ca9

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 (192) hide show
  1. package/README.md +8 -8
  2. package/api/blog/blog.doc.mjs +2 -2
  3. package/api/build/build.doc.mjs +1 -1
  4. package/api/component/_adapter.mjs +3 -0
  5. package/api/component/component.doc.mjs +1 -1
  6. package/api/discover/discover.doc.mjs +2 -2
  7. package/api/docs/docs.doc.mjs +2 -2
  8. package/api/doctor/doctor.doc.mjs +3 -3
  9. package/api/hook/hook.doc.mjs +1 -1
  10. package/api/init/init.doc.mjs +1 -1
  11. package/api/integration/summarizeIssues.doc.mjs +1 -1
  12. package/api/integration/validate-integration.d.mts +2 -18
  13. package/api/integration/validate-integration.mjs +16 -141
  14. package/api/integration/validateIntegration.doc.mjs +1 -1
  15. package/api/json/assertResponse.doc.mjs +2 -2
  16. package/api/json/isError.doc.mjs +1 -1
  17. package/api/json/parseResponse.doc.mjs +2 -2
  18. package/api/layout/layoutCheck.doc.mjs +1 -1
  19. package/api/layout/layoutExpand.doc.mjs +1 -1
  20. package/api/layout/layoutGrammar.doc.mjs +1 -1
  21. package/api/swizzle/swizzle.doc.mjs +1 -1
  22. package/api/template/copy/copy.d.mts +2 -2
  23. package/api/template/copy/copy.mjs +2 -2
  24. package/api/template/list/list.d.mts +2 -2
  25. package/api/template/list/list.mjs +2 -2
  26. package/api/template/show/show.d.mts +2 -2
  27. package/api/template/show/show.mjs +2 -2
  28. package/api/template/skeleton/skeleton.d.mts +3 -3
  29. package/api/template/skeleton/skeleton.mjs +3 -3
  30. package/api/template/template.d.mts +7 -7
  31. package/api/template/template.mjs +7 -7
  32. package/api/template/template.test.mjs +38 -13
  33. package/api/theme/listThemes.doc.mjs +2 -2
  34. package/api/theme/themeAdd.doc.mjs +1 -1
  35. package/api/theme/themeBuild.doc.mjs +3 -3
  36. package/api/theme/themeList.doc.mjs +2 -2
  37. package/api/upgrade/upgrade.doc.mjs +1 -1
  38. package/assets/codemods/transforms/v0.3.0/__tests__/migrate-grid-minchildwidth-to-columns.test.mjs +82 -0
  39. package/assets/codemods/transforms/v0.3.0/__tests__/migrate-table-rowexpansion-to-tree.test.mjs +201 -0
  40. package/assets/codemods/transforms/v0.3.0/index.mjs +8 -0
  41. package/assets/codemods/transforms/v0.3.0/migrate-grid-minchildwidth-to-columns.mjs +38 -2
  42. package/assets/codemods/transforms/v0.3.0/migrate-table-rowexpansion-to-tree.mjs +214 -0
  43. package/assets/docs/browser-support.doc.mjs +6 -6
  44. package/assets/docs/icons.doc.mjs +3 -3
  45. package/assets/docs/illustrations.doc.mjs +2 -2
  46. package/assets/docs/internationalization.doc.mjs +1 -1
  47. package/assets/docs/layout.doc.dense.mjs +1 -1
  48. package/assets/docs/migration.doc.mjs +1 -1
  49. package/assets/docs/principles.doc.mjs +1 -1
  50. package/assets/docs/styling-libraries.doc.mjs +1 -1
  51. package/assets/docs/styling.doc.mjs +4 -4
  52. package/assets/docs/theme.doc.mjs +3 -3
  53. package/assets/docs/typography.doc.mjs +2 -2
  54. package/assets/templates/blocks/components/AspectRatio/AspectRatioCircleImage.tsx +1 -1
  55. package/assets/templates/blocks/components/AspectRatio/AspectRatioImageGallery.tsx +1 -1
  56. package/assets/templates/blocks/components/AspectRatio/AspectRatioShowcase.tsx +3 -3
  57. package/assets/templates/blocks/components/AspectRatio/AspectRatioSquareImage.tsx +1 -1
  58. package/assets/templates/blocks/components/AspectRatio/AspectRatioWidescreen.tsx +1 -1
  59. package/assets/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +6 -6
  60. package/assets/templates/blocks/components/Avatar/AvatarGroup.tsx +5 -5
  61. package/assets/templates/blocks/components/Avatar/AvatarInteractive.tsx +2 -2
  62. package/assets/templates/blocks/components/Avatar/AvatarShowcase.tsx +4 -4
  63. package/assets/templates/blocks/components/Avatar/AvatarTooltip.tsx +4 -4
  64. package/assets/templates/blocks/components/Avatar/AvatarUserCard.tsx +3 -3
  65. package/assets/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
  66. package/assets/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
  67. package/assets/templates/blocks/components/ChatComposerDrawer/ChatComposerDrawerAttachments.tsx +5 -5
  68. package/assets/templates/blocks/components/Lightbox/LightboxGallery.tsx +4 -4
  69. package/assets/templates/blocks/components/Lightbox/LightboxShowcase.tsx +1 -1
  70. package/assets/templates/blocks/components/Lightbox/LightboxVideo.tsx +1 -1
  71. package/assets/templates/blocks/components/Lightbox/LightboxZoom.tsx +2 -2
  72. package/assets/templates/blocks/components/MediaTheme/MediaThemeImageOverlay.tsx +1 -1
  73. package/assets/templates/blocks/components/MediaTheme/MediaThemeLightScrim.tsx +1 -1
  74. package/assets/templates/blocks/components/MediaTheme/MediaThemeShowcase.tsx +1 -1
  75. package/assets/templates/blocks/components/Overlay/OverlayBottomStrip.tsx +1 -1
  76. package/assets/templates/blocks/components/Overlay/OverlayHoverReveal.tsx +1 -1
  77. package/assets/templates/blocks/components/Overlay/OverlayShowcase.tsx +1 -1
  78. package/assets/templates/blocks/components/Table/TableRowExpansionTable.tsx +61 -58
  79. package/assets/templates/blocks/components/TopNav/TopNavMegaMenu.tsx +1 -1
  80. package/assets/templates/pages/centered-hero/page.tsx +1 -1
  81. package/assets/templates/pages/classic-gallery/page.tsx +10 -10
  82. package/assets/templates/pages/detail-page/page.tsx +5 -5
  83. package/assets/templates/pages/form-two-column/page.tsx +1 -1
  84. package/assets/templates/pages/gallery-hero/page.tsx +3 -3
  85. package/assets/templates/pages/library/page.tsx +30 -30
  86. package/assets/templates/pages/login/page.tsx +1 -2
  87. package/assets/templates/pages/login-card/page.tsx +1 -2
  88. package/assets/templates/pages/login-split/page.tsx +5 -6
  89. package/assets/templates/pages/login-sso/page.tsx +2 -3
  90. package/assets/templates/pages/mixed-gallery/page.tsx +5 -5
  91. package/assets/templates/pages/payment-form/page.tsx +3 -3
  92. package/assets/templates/pages/product-detail/page.tsx +7 -7
  93. package/assets/templates/pages/product-gallery/page.tsx +6 -6
  94. package/assets/templates/pages/shell-top-nav/page.tsx +2 -2
  95. package/assets/templates/pages/side-gallery/page.tsx +9 -9
  96. package/assets/templates/pages/table-page-chart/page.tsx +6 -6
  97. package/assets/templates/pages/theme-showcase/page.tsx +6 -6
  98. package/assets/templates/themes/neutral/neutralTheme.ts +4 -1
  99. package/authoring/_shared/errors.d.mts +21 -0
  100. package/authoring/codemod/codemod.doc.d.mts +11 -0
  101. package/authoring/codemod/codemod.doc.mjs +2 -2
  102. package/authoring/codemod/parse.d.mts +48 -2
  103. package/authoring/config/config.doc.d.mts +10 -0
  104. package/authoring/config/config.doc.mjs +1 -1
  105. package/authoring/config/parse.d.mts +54 -2
  106. package/authoring/doctypes/_schema.d.mts +248 -0
  107. package/authoring/doctypes/base/type.ts +6 -0
  108. package/authoring/doctypes/command/command.doc.d.mts +12 -0
  109. package/authoring/doctypes/command/command.doc.mjs +2 -2
  110. package/authoring/doctypes/command/parse.d.mts +11 -2
  111. package/authoring/doctypes/component/component.doc.d.mts +11 -0
  112. package/authoring/doctypes/component/component.doc.mjs +7 -7
  113. package/authoring/doctypes/component/parse.d.mts +11 -2
  114. package/authoring/doctypes/enum/enum.doc.d.mts +11 -0
  115. package/authoring/doctypes/enum/enum.doc.mjs +2 -2
  116. package/authoring/doctypes/enum/parse.d.mts +11 -2
  117. package/authoring/doctypes/function/function.doc.d.mts +11 -0
  118. package/authoring/doctypes/function/function.doc.mjs +3 -3
  119. package/authoring/doctypes/function/parse.d.mts +11 -2
  120. package/authoring/doctypes/function/parse.mjs +24 -4
  121. package/authoring/doctypes/hook/hook.doc.d.mts +10 -0
  122. package/authoring/doctypes/hook/hook.doc.mjs +3 -3
  123. package/authoring/doctypes/hook/parse.d.mts +11 -2
  124. package/authoring/doctypes/legacy.d.mts +13 -2
  125. package/authoring/doctypes/parse.d.mts +29 -20
  126. package/authoring/doctypes/reference/parse.d.mts +11 -2
  127. package/authoring/doctypes/reference/reference.doc.d.mts +11 -0
  128. package/authoring/doctypes/reference/reference.doc.mjs +3 -3
  129. package/authoring/doctypes/schema/parse.d.mts +11 -2
  130. package/authoring/doctypes/schema/schema.doc.d.mts +11 -0
  131. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  132. package/authoring/doctypes/template/parse.d.mts +12 -2
  133. package/authoring/doctypes/template/template.doc.d.mts +11 -0
  134. package/authoring/doctypes/template/template.doc.mjs +3 -3
  135. package/authoring/index.d.mts +16 -0
  136. package/authoring/integration/integration.doc.d.mts +10 -0
  137. package/authoring/integration/parse.d.mts +30 -2
  138. package/clients/cli/commands/build-theme.registry.test.mjs +4 -1
  139. package/clients/cli/commands/build.doc.mjs +1 -1
  140. package/clients/cli/commands/component.doc.mjs +1 -1
  141. package/clients/cli/commands/doctor.doc.mjs +2 -2
  142. package/clients/cli/commands/hook.doc.mjs +1 -1
  143. package/clients/cli/commands/layout-expand.doc.mjs +1 -1
  144. package/clients/cli/commands/layout.doc.mjs +1 -1
  145. package/clients/cli/commands/manifest.doc.mjs +3 -3
  146. package/clients/cli/commands/search.doc.mjs +1 -1
  147. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  148. package/clients/cli/commands/theme-build.doc.mjs +1 -1
  149. package/clients/cli/commands/theme-list.doc.mjs +1 -1
  150. package/clients/cli/commands/theme.doc.mjs +2 -2
  151. package/clients/cli/commands/validate-integration.doc.mjs +2 -2
  152. package/clients/cli/lib/manifest.mjs +1 -1
  153. package/foundation/agent-docs/agent-docs.d.mts +197 -0
  154. package/foundation/agent-docs/agent-docs.mjs +3 -4
  155. package/foundation/agent-docs/agent-docs.test.mjs +8 -0
  156. package/foundation/config/config-cache.d.mts +53 -0
  157. package/foundation/config/project.d.mts +154 -0
  158. package/foundation/config/project.mjs +3 -3
  159. package/foundation/discovery/component-discovery.d.mts +140 -0
  160. package/foundation/discovery/component-loader.d.mts +50 -0
  161. package/foundation/discovery/hook-discovery.d.mts +28 -0
  162. package/{api/template/_adapter.d.mts → foundation/discovery/template-adapter.d.mts} +7 -4
  163. package/{api/template/_adapter.mjs → foundation/discovery/template-adapter.mjs} +53 -28
  164. package/foundation/env/node-version.d.mts +52 -0
  165. package/foundation/env/package-manager.d.mts +84 -0
  166. package/foundation/env/semver.d.mts +56 -0
  167. package/foundation/fs/module-loader.d.mts +36 -0
  168. package/foundation/fs/path-safety.d.mts +74 -0
  169. package/foundation/fs/paths.d.mts +35 -0
  170. package/foundation/integrations/integration-warnings.d.mts +17 -0
  171. package/foundation/integrations/integration-warnings.mjs +1 -1
  172. package/foundation/integrations/integrations.d.mts +80 -0
  173. package/foundation/integrations/validate-contributions.d.mts +22 -0
  174. package/foundation/integrations/validate-contributions.mjs +162 -0
  175. package/foundation/response/error-codes.d.mts +103 -0
  176. package/foundation/response/error-codes.doc.d.mts +11 -0
  177. package/foundation/response/json.d.mts +75 -0
  178. package/foundation/response/response-types.doc.d.mts +12 -0
  179. package/foundation/response/response-types.doc.mjs +7 -7
  180. package/foundation/response/response.doc.d.mts +11 -0
  181. package/foundation/response/response.doc.mjs +5 -5
  182. package/foundation/text/levenshtein.d.mts +21 -0
  183. package/foundation/text/string-utils.d.mts +43 -0
  184. package/foundation/xle/browser.d.mts +89 -0
  185. package/foundation/xle/expand.d.mts +23 -0
  186. package/foundation/xle/parse.d.mts +72 -0
  187. package/foundation/xle/print.d.mts +7 -0
  188. package/foundation/xle/registry-core.d.mts +168 -0
  189. package/foundation/xle/registry.d.mts +19 -0
  190. package/foundation/xle/splice.d.mts +42 -0
  191. package/foundation/xle/validate.d.mts +94 -0
  192. package/package.json +9 -9
package/README.md CHANGED
@@ -72,7 +72,7 @@ Options:
72
72
  | `search` | Search components, hooks, docs, and templates in one ranked list |
73
73
  | `swizzle` | Copy component source for customization |
74
74
  | `template` | Inject a page or block template |
75
- | `theme` | Theme tools — build, export, and manage themes |
75
+ | `theme` | Theme tools: build, export, and manage themes |
76
76
  | `upgrade` | Run codemods to migrate between versions |
77
77
  | `validate-integration` | Validate an Astryx integration package (manifest + contributions) |
78
78
 
@@ -385,7 +385,7 @@ Every response has a `type` discriminant. The full set is below (generated from
385
385
 
386
386
  | Type | What `data` carries |
387
387
  | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
388
- | `component.list` | The component catalog grouped by category: `detail` (the level — names \| compact \| full) and `components`, the grouped map of names+package, brief entries, or a full ComponentDoc per entry. |
388
+ | `component.list` | The component catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of names+package, brief entries, or a full ComponentDoc per entry. |
389
389
  | `component.detail` | One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, and whether source is available). |
390
390
  | `component.detail.props` | Just one component's props table (ComponentPropDoc[]). |
391
391
  | `component.detail.source` | One component's source file, as {component, source}. |
@@ -393,12 +393,12 @@ Every response has a `type` discriminant. The full set is below (generated from
393
393
  | `component.detail.blocks` | One component's example blocks, as {component, showcase, examples, related} of BlockEntry. |
394
394
  | `docs.list` | All reference-doc topics as DocsListEntry[] ({topic, description}), in discovery order. |
395
395
  | `docs.detail` | One topic's full ReferenceDoc, with token-ref blocks inlined. |
396
- | `docs.detail.section` | A single ReferenceSection of a topic — the first whose title contains the section query. |
397
- | `blog.list` | The feed URL plus every post parsed from the RSS feed — each with slug, title, description, date, type, authors, link, and plaintext URL. |
396
+ | `docs.detail.section` | A single ReferenceSection of a topic: the first whose title contains the section query. |
397
+ | `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. |
398
398
  | `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. |
399
399
  | `discover.list` | The configured external packages (name, category, components, version, description); when empty it carries meta.configured to tell "nothing configured" from "nothing discovered". |
400
400
  | `discover.detail` | A single external package entry, for an @scope/name query. |
401
- | `discover.detail.doc` | The validated ComponentDoc for one external component — an @scope/name/Component query, or a free-text term resolving to exactly one component. |
401
+ | `discover.detail.doc` | The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term resolving to exactly one component. |
402
402
  | `discover.search` | The echoed query plus the matching {package, component} pairs, when a free-text term matches several components. |
403
403
  | `search` | The echoed query plus a ranked SearchResultEntry[] (domain, name, score, reason, description, follow-up command, and import path where relevant). |
404
404
  | `build.help` | A marker (`playbook: true`) that the renderer expands into the how-to-build-a-page workflow; emitted when no query is given. |
@@ -409,15 +409,15 @@ Every response has a `type` discriminant. The full set is below (generated from
409
409
  | `template.show` | The resolved template's raw source plus its description, kind, and the component names it composes. |
410
410
  | `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. |
411
411
  | `template.copy` | A scaffold receipt: template id, output directory, written file name, and file count. |
412
- | `hook.list` | The hook catalog grouped by category: `detail` (the level — names \| compact \| full) and `components`, the grouped map of hook names, brief entries, or a full HookDoc per entry. |
412
+ | `hook.list` | The hook catalog grouped by category: `detail` (the level: names \| compact \| full) and `components`, the grouped map of hook names, brief entries, or a full HookDoc per entry. |
413
413
  | `hook.detail` | One hook's full authored HookDoc. |
414
414
  | `hook.detail.params` | Just one hook's parameters table (HookParamDoc[]). |
415
415
  | `theme.build` | A theme build receipt: name, token- and component-override counts, output size, the written outputs {css, js, dts, and variantsDts when applicable}, and any validation warnings. |
416
416
  | `theme.build.check` | The --check receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: missing \| outdated}), and the full list of checked paths. Writes nothing. |
417
- | `theme.list` | Every bundled theme as a ThemeListEntry[] — each with slug, displayName, description, and a maintained flag. |
417
+ | `theme.list` | Every bundled theme as a ThemeListEntry[]: each with slug, displayName, description, and a maintained flag. |
418
418
  | `theme.add` | A scaffold receipt: resolved slug, displayName, maintained flag, outputDir (relative to cwd), the theme entry file, its exportName, and the files written. |
419
419
  | `upgrade.list` | Every available codemod, oldest→newest, as {name, title, version, optional}; returned for --list without running anything. |
420
- | `upgrade.status` | A short-circuit outcome with no codemods run — up_to_date, no_codemods, or config_fixable — each carrying the agent-docs summary. |
420
+ | `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary. |
421
421
  | `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, and (apply mode) filesChanged, transformsApplied, and per-codemod errors. |
422
422
  | `manifest` | The self-describing CLI capability manifest: name, version, apiVersion, global options, the command tree (args, options, json flag, response types, examples), the jsonSupported allowlist, and the flat responseTypes index. |
423
423
  | `doctor` | The health-check report: `checks` (each with id, label, status: pass \| warn \| fail \| info, a message, and a fix when not passing) plus a `summary` of counts per status. |
@@ -14,7 +14,7 @@ export const doc = {
14
14
  displayName: 'blog()',
15
15
  summary: 'List blog posts, or read one, from the published RSS feed.',
16
16
  description:
17
- 'Reads the design system blog the same way any feed reader does — over the ' +
17
+ 'Reads the design system blog the same way any feed reader does, over the ' +
18
18
  "published RSS feed, never the blog's source files. With no slug it lists every " +
19
19
  "post parsed from the feed; with a slug it reads that post's full plaintext body " +
20
20
  'via the .txt alternate the feed advertises. Both envelopes carry feedUrl so a ' +
@@ -35,7 +35,7 @@ export const doc = {
35
35
  {
36
36
  type: 'blog.list',
37
37
  description:
38
- 'The feed URL plus every post parsed from the feed — each with slug, title, description, date, type, authors, link, and its plaintext URL.',
38
+ 'The feed URL plus every post parsed from the feed, each with slug, title, description, date, type, authors, link, and its plaintext URL.',
39
39
  },
40
40
  {
41
41
  type: 'blog.detail',
@@ -54,7 +54,7 @@ export const doc = {
54
54
  {
55
55
  type: 'build.help',
56
56
  description:
57
- 'Emitted when the query is omitted — a pure marker (`data.playbook: true`) that the command renderer expands into the page-building workflow prose.',
57
+ 'Emitted when the query is omitted: a pure marker (`data.playbook: true`) that the command renderer expands into the page-building workflow prose.',
58
58
  },
59
59
  {
60
60
  type: 'build.kit',
@@ -270,6 +270,9 @@ export async function resolveUnscopedDoc(dirName, {coreDir, cwd, name}) {
270
270
  let resolvedName = dirName;
271
271
  // Track the resolving owner so the detail payload can carry ownership info.
272
272
  // Defaults to core; the legacy-external fallback below may reassign it.
273
+ // Annotated because CORE_PACKAGE's generated declaration carries the literal
274
+ // type, which (unlike a fresh literal) does not widen on assignment.
275
+ /** @type {string} */
273
276
  let resolvedOwnerPackage = CORE_PACKAGE;
274
277
  let resolvedSourcePath = readmePath ? findComponentSource(coreDir, dirName) : null;
275
278
 
@@ -108,7 +108,7 @@ export const doc = {
108
108
  {
109
109
  type: 'component.list',
110
110
  description:
111
- "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map — names+package, brief entries, or full ComponentDoc per entry.",
111
+ "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: names+package, brief entries, or full ComponentDoc per entry.",
112
112
  },
113
113
  {
114
114
  type: 'component.detail',
@@ -15,7 +15,7 @@ export const doc = {
15
15
  summary: 'Browse and search components from configured external packages.',
16
16
  description:
17
17
  'Explores components contributed by configured external packages and integrations ' +
18
- '— the ones that declare a components root. With no query it lists those packages; ' +
18
+ 'the ones that declare a components root. With no query it lists those packages; ' +
19
19
  'an @scope/name query browses one package; @scope/name/Component (or a free-text ' +
20
20
  "term that resolves to a single component) returns that component's validated doc; " +
21
21
  'a free-text term with several matches returns the candidate list.',
@@ -68,7 +68,7 @@ export const doc = {
68
68
  {
69
69
  type: 'discover.detail.doc',
70
70
  description:
71
- 'The validated ComponentDoc for one external component — an @scope/name/Component query, or a free-text term that resolves to exactly one component.',
71
+ 'The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term that resolves to exactly one component.',
72
72
  },
73
73
  {
74
74
  type: 'discover.search',
@@ -13,7 +13,7 @@ export const doc = {
13
13
  name: 'docs',
14
14
  displayName: 'docs()',
15
15
  summary:
16
- 'Read the reference docs — list every topic, one topic, or a single section of a topic.',
16
+ 'Read the reference docs: list every topic, one topic, or a single section of a topic.',
17
17
  description:
18
18
  'Routes on its arguments: no topic lists every reference-doc topic; a topic ' +
19
19
  'returns that full ReferenceDoc (with token-ref blocks inlined); a topic ' +
@@ -75,7 +75,7 @@ export const doc = {
75
75
  {
76
76
  type: 'docs.detail.section',
77
77
  description:
78
- 'A single ReferenceSection of the topic — the first whose title contains the section query.',
78
+ 'A single ReferenceSection of the topic: the first whose title contains the section query.',
79
79
  },
80
80
  ],
81
81
  throws: [
@@ -14,10 +14,10 @@ export const doc = {
14
14
  displayName: 'doctor()',
15
15
  summary: 'Read-only project + environment health check.',
16
16
  description:
17
- 'Runs a series of side-effect-free diagnostics — Node version, ' +
17
+ 'Runs a series of side-effect-free diagnostics: Node version, ' +
18
18
  '@astryxdesign/core install and version alignment with the CLI, installed ' +
19
19
  'themes and wiring, astryx.config validity, agent docs, core peer ' +
20
- 'dependencies, and the detected package manager — and returns a structured ' +
20
+ 'dependencies, and the detected package manager, and returns a structured ' +
21
21
  'report. It only reads (never installs, writes, or mutates), so it is safe ' +
22
22
  'as a CI gate and for agents to invoke.',
23
23
  importPath: '@astryxdesign/cli/api',
@@ -34,7 +34,7 @@ export const doc = {
34
34
  {
35
35
  type: 'doctor',
36
36
  description:
37
- 'The diagnostic report: `data.checks` — each with a stable id, label, `status` (`pass` | `warn` | `fail` | `info`), a one-line message, and a `fix` when the status is not `pass` — plus `data.summary` with counts per status.',
37
+ 'The diagnostic report: `data.checks`, each with a stable id, label, `status` (`pass` | `warn` | `fail` | `info`), a one-line message, and a `fix` when the status is not `pass`; plus `data.summary` with counts per status.',
38
38
  },
39
39
  ],
40
40
  examples: [
@@ -70,7 +70,7 @@ export const doc = {
70
70
  {
71
71
  type: 'hook.list',
72
72
  description:
73
- "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map — hook names, brief entries, or full HookDoc per entry.",
73
+ "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: hook names, brief entries, or full HookDoc per entry.",
74
74
  },
75
75
  {
76
76
  type: 'hook.detail',
@@ -69,7 +69,7 @@ export const doc = {
69
69
  {
70
70
  type: 'init.remove',
71
71
  description:
72
- 'Confirmation that the managed agent-docs block was removed (`data.removed: true`) — returned when `removeAgents` is set.',
72
+ 'Confirmation that the managed agent-docs block was removed (`data.removed: true`), returned when `removeAgents` is set.',
73
73
  },
74
74
  ],
75
75
  throws: [
@@ -17,7 +17,7 @@ export const doc = {
17
17
  'Tally integration issues by severity into error and warning counts.',
18
18
  description:
19
19
  'A synchronous helper that reduces an AstryxIntegrationIssue[] (as returned ' +
20
- 'by validateIntegration) to counts of errors and warnings — the seam a ' +
20
+ 'by validateIntegration) to counts of errors and warnings: the seam a ' +
21
21
  'caller uses to decide an exit code or print a summary line. Issues of any ' +
22
22
  'other severity are ignored.',
23
23
  importPath: '@astryxdesign/cli/api',
@@ -1,24 +1,6 @@
1
1
  // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
- /**
5
- * Validate an already-LOADED integration (as produced by
6
- * `loadIntegrations` in lib/integrations.mjs — absolute contribution roots
7
- * plus identity) and return its issues. This is the reuse seam for everyday
8
- * commands that have already loaded the configured integrations and want the
9
- * SAME validators that `validate-integration` runs, without re-resolving the
10
- * manifest from disk.
11
- *
12
- * The manifest schema is intentionally NOT re-validated here: `loadIntegrations`
13
- * already validated it (and throws otherwise), so by the time a command holds a
14
- * loaded integration the manifest is known-good. We re-run the on-disk
15
- * contribution checks (roots + codemods/templates/components) because those can
16
- * regress independently of the manifest (a deleted directory, a broken template).
17
- *
18
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} loaded loaded-integration-shaped object
19
- * @returns {Promise<Issue[]>}
20
- */
21
- export function validateLoadedIntegration(loaded: import("./validate-integration.type.mjs").LoadedIntegration): Promise<Issue[]>;
22
4
  /**
23
5
  * Validate the LOCAL integration package rooted at `cwd`: nearest package.json
24
6
  * + a single sibling astryx.integration.{ts,mjs,js}. A missing manifest yields
@@ -59,6 +41,7 @@ export function summarizeIssues(issues: Issue[]): {
59
41
  errors: number;
60
42
  warnings: number;
61
43
  };
44
+ export { validateLoadedIntegration };
62
45
  export type Issue = import("../../foundation/integrations/issue").AstryxIntegrationIssue;
63
46
  export type ValidateResult = {
64
47
  /**
@@ -79,3 +62,4 @@ export type ValidateResult = {
79
62
  manifestFile?: string | undefined;
80
63
  issues: Issue[];
81
64
  };
65
+ import { validateLoadedIntegration } from '../../foundation/integrations/validate-contributions.mjs';
@@ -17,6 +17,14 @@
17
17
  * is false only for the no-manifest local case, which is guidance (not an
18
18
  * error) so `validate-integration` can stay exit-0 in a non-integration dir.
19
19
  *
20
+ * The on-disk contribution validators themselves (roots + codemods/templates/
21
+ * components, behind `validateLoadedIntegration`) live in
22
+ * `foundation/integrations/validate-contributions.mjs`, because foundation also
23
+ * runs them: `Project` collects integration issues and `integration-warnings`
24
+ * nudges about them on ordinary commands. This file re-exports
25
+ * `validateLoadedIntegration` so existing importers are unaffected, and keeps
26
+ * the command-level entry points that resolve a manifest from disk.
27
+ *
20
28
  * Validators are intentionally small and independent so more checks can be
21
29
  * appended without reshaping the result. Issue `code`s are stable public
22
30
  * strings.
@@ -30,9 +38,14 @@ import {
30
38
  loadManifestObject,
31
39
  resolvePackageDir,
32
40
  } from '../../foundation/integrations/integrations.mjs';
33
- import {discoverIntegrationCodemods} from '../../assets/codemods/integration-discovery.mjs';
34
- import {discoverIntegrationTemplatesForOne} from '../template/template.mjs';
35
- import * as componentDiscovery from '../../foundation/discovery/component-discovery.mjs';
41
+ // The on-disk contribution validators live in foundation: Project and
42
+ // integration-warnings need them too, and foundation must not depend on api.
43
+ import {
44
+ validateLoadedIntegration,
45
+ issueError as error,
46
+ } from '../../foundation/integrations/validate-contributions.mjs';
47
+
48
+ export {validateLoadedIntegration};
36
49
 
37
50
  /**
38
51
  * @typedef {import('../../foundation/integrations/issue').AstryxIntegrationIssue} Issue
@@ -63,144 +76,6 @@ function findNearestPackageJson(cwd) {
63
76
  }
64
77
  }
65
78
 
66
- /** @param {string} code @param {string} message @returns {Issue} */
67
- function error(code, message) {
68
- return {code, severity: 'error', message};
69
- }
70
-
71
- /**
72
- * Verify each declared contribution root exists on disk. A declared-but-missing
73
- * root is a `missing_root` error.
74
- * @param {{components?: string, templates?: string, codemods?: string}} resolved
75
- * absolute resolved roots (undefined when not declared)
76
- * @param {Issue[]} issues
77
- */
78
- function checkRoots(resolved, issues) {
79
- const kinds = /** @type {const} */ (['components', 'templates', 'codemods']);
80
- for (const kind of kinds) {
81
- const root = resolved[kind];
82
- if (root == null) continue;
83
- if (!fs.existsSync(root)) {
84
- issues.push(
85
- error(
86
- 'missing_root',
87
- `Declared ${kind} root does not exist on disk: ${root}`,
88
- ),
89
- );
90
- }
91
- }
92
- }
93
-
94
- /**
95
- * Validate the integration's codemods via the landed discovery. Discovery is
96
- * strict (throws on bad export / duplicate id); we convert any throw into an
97
- * `invalid_codemod` error.
98
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} integration loaded-integration-shaped object
99
- * @param {Issue[]} issues
100
- */
101
- async function checkCodemods(integration, issues) {
102
- if (!integration.codemods || !fs.existsSync(integration.codemods)) return;
103
- try {
104
- await discoverIntegrationCodemods([integration]);
105
- } catch (err) {
106
- issues.push(error('invalid_codemod', /** @type {any} */ (err).message));
107
- }
108
- }
109
-
110
- /**
111
- * Validate the integration's templates via the landed discovery. Per-template
112
- * problems are reported as `invalid_template` errors.
113
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} integration loaded-integration-shaped object
114
- * @param {Issue[]} issues
115
- */
116
- async function checkTemplates(integration, issues) {
117
- if (!integration.templates || !fs.existsSync(integration.templates)) return;
118
- try {
119
- const {errors} = await discoverIntegrationTemplatesForOne(integration);
120
- for (const e of errors) {
121
- issues.push(error('invalid_template', e.message));
122
- }
123
- } catch (err) {
124
- issues.push(error('invalid_template', /** @type {any} */ (err).message));
125
- }
126
- }
127
-
128
- /**
129
- * Validate the integration's components via the landed ownership discovery.
130
- * Feature-detected: if the component-ownership export isn't present in this
131
- * build (sibling PR not yet merged), component validation is skipped rather
132
- * than hard-failing.
133
- *
134
- * `discoverIntegrationComponents` returns ownership records and does not throw
135
- * on a missing same-stem source — it records `sourcePath: null`. We surface
136
- * each such record as an `invalid_component` error.
137
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} integration loaded-integration-shaped object
138
- * @param {Issue[]} issues
139
- */
140
- async function checkComponents(integration, issues) {
141
- if (!integration.components || !fs.existsSync(integration.components)) return;
142
- const discover = componentDiscovery.discoverIntegrationComponents;
143
- if (typeof discover !== 'function') return; // feature not present yet
144
- try {
145
- const records = (await discover(integration)) ?? [];
146
- for (const record of records) {
147
- if (record?.sourcePath == null) {
148
- issues.push(
149
- error(
150
- 'invalid_component',
151
- `Component "${record?.name}" is missing its same-stem source file ${record?.name}.tsx.`,
152
- ),
153
- );
154
- }
155
- }
156
- } catch (err) {
157
- issues.push(error('invalid_component', /** @type {any} */ (err).message));
158
- }
159
- }
160
-
161
- /**
162
- * Run every contribution validator against a loaded-integration-shaped object.
163
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} integration
164
- * @param {Issue[]} issues
165
- */
166
- async function runContributionChecks(integration, issues) {
167
- await checkCodemods(integration, issues);
168
- await checkTemplates(integration, issues);
169
- await checkComponents(integration, issues);
170
- }
171
-
172
- /**
173
- * Validate an already-LOADED integration (as produced by
174
- * `loadIntegrations` in lib/integrations.mjs — absolute contribution roots
175
- * plus identity) and return its issues. This is the reuse seam for everyday
176
- * commands that have already loaded the configured integrations and want the
177
- * SAME validators that `validate-integration` runs, without re-resolving the
178
- * manifest from disk.
179
- *
180
- * The manifest schema is intentionally NOT re-validated here: `loadIntegrations`
181
- * already validated it (and throws otherwise), so by the time a command holds a
182
- * loaded integration the manifest is known-good. We re-run the on-disk
183
- * contribution checks (roots + codemods/templates/components) because those can
184
- * regress independently of the manifest (a deleted directory, a broken template).
185
- *
186
- * @param {import('./validate-integration.type.mjs').LoadedIntegration} loaded loaded-integration-shaped object
187
- * @returns {Promise<Issue[]>}
188
- */
189
- export async function validateLoadedIntegration(loaded) {
190
- /** @type {Issue[]} */
191
- const issues = [];
192
- if (!loaded || typeof loaded !== 'object') return issues;
193
- checkRoots(
194
- {
195
- components: loaded.components,
196
- templates: loaded.templates,
197
- codemods: loaded.codemods,
198
- },
199
- issues,
200
- );
201
- await runContributionChecks(loaded, issues);
202
- return issues;
203
- }
204
79
 
205
80
  /**
206
81
  * Validate a single integration given its package directory and identity.
@@ -45,7 +45,7 @@ export const doc = {
45
45
  {
46
46
  type: 'integration.validate',
47
47
  description:
48
- 'The result envelope: `data.name` and `data.version` of the validated package (both null when no local manifest is found), plus `data.issues` — an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.',
48
+ 'The result envelope: `data.name` and `data.version` of the validated package (both null when no local manifest is found), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.',
49
49
  },
50
50
  ],
51
51
  examples: [
@@ -27,7 +27,7 @@ export const doc = {
27
27
  name: 'raw',
28
28
  type: 'unknown',
29
29
  description:
30
- 'The CLI stdout to parse — a JSON string, or an object that was already parsed.',
30
+ 'The CLI stdout to parse: a JSON string, or an object that was already parsed.',
31
31
  required: true,
32
32
  },
33
33
  {
@@ -42,7 +42,7 @@ export const doc = {
42
42
  {
43
43
  type: 'any',
44
44
  description:
45
- 'The parsed envelope, guaranteed at runtime to carry the requested `type`. The published signature is untyped — cast to the matching *Response type for typed access.',
45
+ 'The parsed envelope, guaranteed at runtime to carry the requested `type`. The published signature is untyped; cast to the matching *Response type for typed access.',
46
46
  },
47
47
  ],
48
48
  throws: [
@@ -14,7 +14,7 @@ export const doc = {
14
14
  displayName: 'isError()',
15
15
  summary: 'Did the CLI return an error envelope?',
16
16
  description:
17
- 'Tests a parsed response for an `error` key. Branch on this before touching `data` — ' +
17
+ 'Tests a parsed response for an `error` key. Branch on this before touching `data`: ' +
18
18
  'and prefer the stable `code` field over matching the human-readable message, which is ' +
19
19
  'not a contract. Note this returns a plain boolean, not a TypeScript type predicate, so ' +
20
20
  'it does not narrow on its own: cast to the matching *Response type to get typed access.',
@@ -26,7 +26,7 @@ export const doc = {
26
26
  name: 'raw',
27
27
  type: 'unknown',
28
28
  description:
29
- 'The CLI stdout to parse — a JSON string, or an object that was already parsed.',
29
+ 'The CLI stdout to parse: a JSON string, or an object that was already parsed.',
30
30
  required: true,
31
31
  },
32
32
  ],
@@ -34,7 +34,7 @@ export const doc = {
34
34
  {
35
35
  type: 'any',
36
36
  description:
37
- 'The { type, data, meta? } envelope, or a CLIError envelope. The published signature is intentionally untyped — narrow it by casting to the matching *Response type exported from @astryxdesign/cli/json.',
37
+ 'The { type, data, meta? } envelope, or a CLIError envelope. The published signature is intentionally untyped; narrow it by casting to the matching *Response type exported from @astryxdesign/cli/json.',
38
38
  },
39
39
  ],
40
40
  throws: [
@@ -18,7 +18,7 @@ export const doc = {
18
18
  'The validator behind `astryx layout check`. Parses and validates a compressed XLE/XLO ' +
19
19
  'expression without generating any TSX, and echoes it back in both canonical surfaces ' +
20
20
  '(compact and outline). Validation failures are reported in the layout.check envelope ' +
21
- '(valid: false) with line/col and suggestions — not thrown — so callers can lint an ' +
21
+ '(valid: false) with line/col and suggestions (not thrown) so callers can lint an ' +
22
22
  'expression and surface fixes.',
23
23
  importPath: '@astryxdesign/cli/api',
24
24
  signature:
@@ -16,7 +16,7 @@ export const doc = {
16
16
  summary: 'Expand a validated layout expression into XDS TSX.',
17
17
  description:
18
18
  'The generator behind `astryx layout expand`. Parses and validates a compressed XLE/XLO ' +
19
- 'expression, then expands it into ready-to-use XDS TSX — auto-routing structural children ' +
19
+ 'expression, then expands it into ready-to-use XDS TSX, auto-routing structural children ' +
20
20
  'into the right slots, scaffolding typed useState for interactive controls, and splicing or ' +
21
21
  'importing any referenced template blocks. Returns the code (and metadata) in a layout.expand ' +
22
22
  'envelope, optionally writing it to a path within cwd.',
@@ -15,7 +15,7 @@ export const doc = {
15
15
  displayName: 'layoutGrammar()',
16
16
  summary: 'Return the XLE/XLO grammar cheatsheet for this install.',
17
17
  description:
18
- 'The reference behind `astryx layout grammar` — the agent cheatsheet for writing XLE/XLO ' +
18
+ 'The reference behind `astryx layout grammar`: the agent cheatsheet for writing XLE/XLO ' +
19
19
  "layout expressions, with the alias table generated from this branch's registry rather than " +
20
20
  'hand-maintained, so short names always reflect the components actually installed.',
21
21
  importPath: '@astryxdesign/cli/api',
@@ -88,7 +88,7 @@ export const doc = {
88
88
  },
89
89
  {
90
90
  code: 'ERR_AMBIGUOUS_COMPONENT',
91
- when: 'more than one package provides the component — choose one with package',
91
+ when: 'more than one package provides the component; choose one with package',
92
92
  },
93
93
  {
94
94
  code: 'ERR_NO_SOURCE',
@@ -4,11 +4,11 @@
4
4
  /**
5
5
  * Scaffold an already-resolved template to `targetPath` (relative to `cwd`) and
6
6
  * return the `template.copy` receipt.
7
- * @param {import('../_adapter.mjs').DiscoveredTemplate} match
7
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate} match
8
8
  * @param {{targetPath: string, cwd: string, overwrite?: boolean}} ctx
9
9
  * @returns {import('../template.type.mjs').TemplateCopyResponse}
10
10
  */
11
- export function templateCopy(match: import("../_adapter.mjs").DiscoveredTemplate, { targetPath, cwd, overwrite }: {
11
+ export function templateCopy(match: import("../../../foundation/discovery/template-adapter.mjs").DiscoveredTemplate, { targetPath, cwd, overwrite }: {
12
12
  targetPath: string;
13
13
  cwd: string;
14
14
  overwrite?: boolean;
@@ -18,12 +18,12 @@ import {
18
18
  } from '../../../foundation/fs/path-safety.mjs';
19
19
  import {AstryxError} from '../../error.mjs';
20
20
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
21
- import {stripTemplateAssetRefs} from '../_adapter.mjs';
21
+ import {stripTemplateAssetRefs} from '../../../foundation/discovery/template-adapter.mjs';
22
22
 
23
23
  /**
24
24
  * Scaffold an already-resolved template to `targetPath` (relative to `cwd`) and
25
25
  * return the `template.copy` receipt.
26
- * @param {import('../_adapter.mjs').DiscoveredTemplate} match
26
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate} match
27
27
  * @param {{targetPath: string, cwd: string, overwrite?: boolean}} ctx
28
28
  * @returns {import('../template.type.mjs').TemplateCopyResponse}
29
29
  */
@@ -3,11 +3,11 @@
3
3
 
4
4
  /**
5
5
  * Project a discovered template set into the `template.list` envelope.
6
- * @param {import('../_adapter.mjs').DiscoveredTemplate[]} templates
6
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate[]} templates
7
7
  * @param {{type?: 'page' | 'block', package?: string}} [options]
8
8
  * @returns {import('../template.type.mjs').TemplateListResponse}
9
9
  */
10
- export function templateList(templates: import("../_adapter.mjs").DiscoveredTemplate[], options?: {
10
+ export function templateList(templates: import("../../../foundation/discovery/template-adapter.mjs").DiscoveredTemplate[], options?: {
11
11
  type?: "page" | "block";
12
12
  package?: string;
13
13
  }): import("../template.type.mjs").TemplateListResponse;
@@ -9,11 +9,11 @@
9
9
  * no-skeleton default) here.
10
10
  */
11
11
 
12
- import {pkgOf} from '../_adapter.mjs';
12
+ import {pkgOf} from '../../../foundation/discovery/template-adapter.mjs';
13
13
 
14
14
  /**
15
15
  * Project a discovered template set into the `template.list` envelope.
16
- * @param {import('../_adapter.mjs').DiscoveredTemplate[]} templates
16
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate[]} templates
17
17
  * @param {{type?: 'page' | 'block', package?: string}} [options]
18
18
  * @returns {import('../template.type.mjs').TemplateListResponse}
19
19
  */
@@ -3,7 +3,7 @@
3
3
 
4
4
  /**
5
5
  * Build the `template.show` envelope for an already-resolved template.
6
- * @param {import('../_adapter.mjs').DiscoveredTemplate} match
6
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate} match
7
7
  * @returns {import('../template.type.mjs').TemplateShowResponse}
8
8
  */
9
- export function templateShow(match: import("../_adapter.mjs").DiscoveredTemplate): import("../template.type.mjs").TemplateShowResponse;
9
+ export function templateShow(match: import("../../../foundation/discovery/template-adapter.mjs").DiscoveredTemplate): import("../template.type.mjs").TemplateShowResponse;
@@ -11,11 +11,11 @@
11
11
  import * as fs from 'node:fs';
12
12
  import {AstryxError} from '../../error.mjs';
13
13
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
14
- import {extractComponents} from '../_adapter.mjs';
14
+ import {extractComponents} from '../../../foundation/discovery/template-adapter.mjs';
15
15
 
16
16
  /**
17
17
  * Build the `template.show` envelope for an already-resolved template.
18
- * @param {import('../_adapter.mjs').DiscoveredTemplate} match
18
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate} match
19
19
  * @returns {import('../template.type.mjs').TemplateShowResponse}
20
20
  */
21
21
  export function templateShow(match) {
@@ -5,8 +5,8 @@
5
5
  * Build the `template.skeleton` envelope for an already-resolved template.
6
6
  * `match` may be undefined when `--skeleton` is run without a name — the same
7
7
  * "specify a template name" error the dispatcher's resolution would surface.
8
- * @param {import('../_adapter.mjs').DiscoveredTemplate | undefined} match
9
- * @param {import('../_adapter.mjs').DiscoveredTemplate[]} templates
8
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate | undefined} match
9
+ * @param {import('../../../foundation/discovery/template-adapter.mjs').DiscoveredTemplate[]} templates
10
10
  * @returns {import('../template.type.mjs').TemplateSkeletonResponse}
11
11
  */
12
- export function templateSkeleton(match: import("../_adapter.mjs").DiscoveredTemplate | undefined, templates: import("../_adapter.mjs").DiscoveredTemplate[]): import("../template.type.mjs").TemplateSkeletonResponse;
12
+ export function templateSkeleton(match: import("../../../foundation/discovery/template-adapter.mjs").DiscoveredTemplate | undefined, templates: import("../../../foundation/discovery/template-adapter.mjs").DiscoveredTemplate[]): import("../template.type.mjs").TemplateSkeletonResponse;