@astryxdesign/cli 0.6.4 → 0.6.5-canary.01972bc

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 (405) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +103 -95
  3. package/api/build/_adapter.d.mts +36 -2
  4. package/api/build/_adapter.mjs +41 -10
  5. package/api/build/build.doc.mjs +8 -3
  6. package/api/build/build.test.mjs +60 -2
  7. package/api/build/kit/kit.mjs +109 -26
  8. package/api/build/kit/rank.d.mts +24 -8
  9. package/api/build/kit/rank.mjs +277 -97
  10. package/api/build/kit/rank.test.mjs +231 -48
  11. package/api/component/_adapter.d.mts +25 -0
  12. package/api/component/_adapter.mjs +59 -5
  13. package/api/component/component.d.mts +6 -3
  14. package/api/component/component.doc.mjs +37 -17
  15. package/api/component/component.mjs +249 -9
  16. package/api/component/component.type.d.mts +25 -0
  17. package/api/component/component.type.mjs +44 -0
  18. package/api/discover/_adapter.d.mts +114 -6
  19. package/api/discover/_adapter.mjs +372 -17
  20. package/api/discover/_adapter.test.mjs +215 -0
  21. package/api/discover/_catalog-view.d.mts +115 -0
  22. package/api/discover/_catalog-view.mjs +203 -0
  23. package/api/discover/_catalog-view.test.mjs +128 -0
  24. package/api/discover/detail/detail.d.mts +18 -6
  25. package/api/discover/detail/detail.mjs +67 -13
  26. package/api/discover/detail/detail.test.mjs +85 -0
  27. package/api/discover/detail/item/item.d.mts +26 -0
  28. package/api/discover/detail/item/item.mjs +78 -0
  29. package/api/discover/detail/item/item.test.mjs +73 -0
  30. package/api/discover/discover.d.mts +3 -9
  31. package/api/discover/discover.doc.mjs +61 -18
  32. package/api/discover/discover.mjs +220 -36
  33. package/api/discover/discover.test.mjs +11 -2
  34. package/api/discover/discover.type.d.mts +147 -8
  35. package/api/discover/discover.type.mjs +102 -12
  36. package/api/discover/list/list.d.mts +20 -6
  37. package/api/discover/list/list.mjs +45 -12
  38. package/api/discover/list/list.test.mjs +46 -0
  39. package/api/discover/search/search.d.mts +18 -16
  40. package/api/discover/search/search.mjs +102 -56
  41. package/api/discover/search/search.test.mjs +144 -10
  42. package/api/docs/_adapter.d.mts +8 -3
  43. package/api/docs/_adapter.mjs +14 -6
  44. package/api/docs/docOverlays.test.mjs +27 -1
  45. package/api/docs/docs.doc.mjs +2 -2
  46. package/api/docs/docs.test.mjs +54 -18
  47. package/api/docs/integration-tree.test.mjs +17 -0
  48. package/api/docs/integrationDocs.test.mjs +27 -5
  49. package/api/doctor/doctor.d.mts +8 -3
  50. package/api/doctor/doctor.doc.mjs +17 -8
  51. package/api/doctor/doctor.mjs +90 -9
  52. package/api/doctor/doctor.test.mjs +122 -10
  53. package/api/doctor/doctor.type.d.mts +1 -1
  54. package/api/doctor/doctor.type.mjs +1 -1
  55. package/api/error.d.mts +22 -0
  56. package/api/error.mjs +42 -0
  57. package/api/gap-report/gap-report.doc.mjs +19 -10
  58. package/api/hook/hook.doc.mjs +6 -3
  59. package/api/index.d.mts +1 -0
  60. package/api/index.mjs +5 -3
  61. package/api/init/init.doc.mjs +17 -12
  62. package/api/integration/add-contribution.d.mts +2 -1
  63. package/api/integration/add-contribution.mjs +7 -3
  64. package/api/integration/add-contribution.test.mjs +3 -3
  65. package/api/integration/add-helpers.d.mts +5 -2
  66. package/api/integration/add-helpers.mjs +36 -9
  67. package/api/integration/add-theme.mjs +266 -23
  68. package/api/integration/add-theme.test.mjs +247 -0
  69. package/api/integration/authoring-checks.mjs +12 -9
  70. package/api/integration/authoring-checks.type.d.mts +8 -0
  71. package/api/integration/authoring-checks.type.mjs +7 -3
  72. package/api/integration/integration-authoring.type.d.mts +4 -1
  73. package/api/integration/integration-authoring.type.mjs +6 -1
  74. package/api/integration/integrationAdd.doc.mjs +6 -0
  75. package/api/integration/integrationAddTheme.doc.mjs +10 -0
  76. package/api/integration/integrationComponentConflicts.doc.mjs +1 -1
  77. package/api/integration/integrationDocConflicts.doc.mjs +1 -1
  78. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  79. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -1
  80. package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
  81. package/api/integration/pack-check.mjs +92 -10
  82. package/api/integration/pack-check.test.mjs +140 -1
  83. package/api/integration/pack-check.type.mjs +1 -1
  84. package/api/integration/validate-integration.d.mts +4 -2
  85. package/api/integration/validate-integration.mjs +7 -2
  86. package/api/integration/validate-integration.test.mjs +55 -0
  87. package/api/integration/validate-integration.type.d.mts +5 -0
  88. package/api/integration/validate-integration.type.mjs +5 -1
  89. package/api/integration/validateIntegration.doc.mjs +1 -1
  90. package/api/json/assertResponse.doc.mjs +1 -1
  91. package/api/json/isError.doc.mjs +1 -1
  92. package/api/layout/expand/expand.mjs +12 -7
  93. package/api/layout/expand/expand.receipt.test.mjs +74 -0
  94. package/api/layout/layout.type.d.mts +1 -0
  95. package/api/layout/layout.type.mjs +1 -0
  96. package/api/layout/layoutExpand.doc.mjs +1 -1
  97. package/api/search/search.d.mts +51 -1
  98. package/api/search/search.doc.mjs +2 -2
  99. package/api/search/search.mjs +299 -17
  100. package/api/search/search.test.mjs +216 -18
  101. package/api/swizzle/copy/copy.mjs +66 -3
  102. package/api/swizzle/swizzle.doc.mjs +11 -5
  103. package/api/template/copy/copy.mjs +15 -9
  104. package/api/template/copy/copy.receipt.test.mjs +77 -0
  105. package/api/template/copy/copy.test.mjs +9 -0
  106. package/api/template/show/show.mjs +15 -4
  107. package/api/template/show/show.test.mjs +76 -0
  108. package/api/template/template-integration.test.mjs +14 -0
  109. package/api/template/template.d.mts +1 -1
  110. package/api/template/template.doc.mjs +8 -3
  111. package/api/template/template.mjs +1 -0
  112. package/api/template/template.type.d.mts +2 -0
  113. package/api/template/template.type.mjs +2 -0
  114. package/api/theme/add/add.mjs +17 -25
  115. package/api/theme/add/add.rollback.test.mjs +158 -0
  116. package/api/theme/add/add.staging.test.mjs +40 -23
  117. package/api/theme/build/build.d.mts +24 -0
  118. package/api/theme/build/build.family.test.mjs +7 -12
  119. package/api/theme/build/build.mjs +243 -26
  120. package/api/theme/build/build.project-core.test.mjs +165 -0
  121. package/api/theme/build/build.rollback.test.mjs +148 -0
  122. package/api/theme/generateTonalPalette.doc.mjs +1 -2
  123. package/api/theme/listThemes.doc.mjs +1 -1
  124. package/api/theme/themeAdd.doc.mjs +9 -10
  125. package/api/theme/themeBuild.doc.mjs +13 -13
  126. package/api/theme/themeList.doc.mjs +1 -1
  127. package/api/theme/themeListAvailable.doc.mjs +2 -1
  128. package/api/theme/themePaletteGenerate.doc.mjs +15 -8
  129. package/api/theme/themeTargets.doc.mjs +3 -2
  130. package/api/theme/themeTemplate.doc.mjs +2 -1
  131. package/api/upgrade/run/files-changed.test.mjs +111 -0
  132. package/api/upgrade/run/run.mjs +25 -6
  133. package/api/upgrade/run/run.test.mjs +45 -1
  134. package/api/upgrade/upgrade.doc.mjs +24 -22
  135. package/api/upgrade/upgrade.type.d.mts +1 -0
  136. package/api/upgrade/upgrade.type.mjs +3 -2
  137. package/assets/codemods/__tests__/runner.test.mjs +3 -1
  138. package/assets/codemods/file-count.test.mjs +163 -0
  139. package/assets/codemods/integration-runner.mjs +3 -3
  140. package/assets/codemods/runner.mjs +5 -4
  141. package/assets/docs/README.md +4 -2
  142. package/assets/docs/browser-support.doc.mjs +11 -11
  143. package/assets/docs/color.doc.mjs +8 -2
  144. package/assets/docs/elevation.doc.mjs +6 -4
  145. package/assets/docs/getting-started.doc.mjs +5 -16
  146. package/assets/docs/icons.doc.mjs +3 -21
  147. package/assets/docs/illustrations.doc.mjs +7 -15
  148. package/assets/docs/internationalization.doc.mjs +7 -5
  149. package/assets/docs/layout.doc.dense.mjs +130 -82
  150. package/assets/docs/layout.doc.mjs +133 -77
  151. package/assets/docs/migration.doc.mjs +19 -21
  152. package/assets/docs/motion.doc.mjs +16 -3
  153. package/assets/docs/principles.doc.dense.mjs +5 -5
  154. package/assets/docs/principles.doc.mjs +8 -0
  155. package/assets/docs/principles.doc.zh.mjs +6 -6
  156. package/assets/docs/shape.doc.mjs +8 -3
  157. package/assets/docs/spacing.doc.mjs +7 -2
  158. package/assets/docs/styling-libraries.doc.mjs +6 -2
  159. package/assets/docs/styling.doc.mjs +19 -23
  160. package/assets/docs/theme.doc.dense.mjs +58 -18
  161. package/assets/docs/theme.doc.mjs +57 -47
  162. package/assets/docs/theme.doc.zh.mjs +9 -8
  163. package/assets/docs/tokens.doc.dense.mjs +2 -2
  164. package/assets/docs/tokens.doc.mjs +389 -8
  165. package/assets/docs/tokens.doc.zh.mjs +2 -2
  166. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  167. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  168. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  169. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  170. package/assets/docs/tree/block-template.doc.mjs +130 -0
  171. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  172. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  173. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  174. package/assets/docs/tree/checks.doc.mjs +119 -0
  175. package/assets/docs/tree/codemods.doc.mjs +147 -0
  176. package/assets/docs/tree/component-family.doc.mjs +113 -0
  177. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  178. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  179. package/assets/docs/tree/components.doc.mjs +23 -0
  180. package/assets/docs/tree/configuration.doc.mjs +23 -0
  181. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  182. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  183. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  184. package/assets/docs/tree/docs.doc.mjs +21 -0
  185. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  186. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  187. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  188. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  189. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  190. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  191. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  192. package/assets/docs/tree/help.doc.mjs +16 -0
  193. package/assets/docs/tree/integrations.doc.mjs +25 -451
  194. package/assets/docs/tree/links.doc.mjs +98 -0
  195. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  196. package/assets/docs/tree/page-template.doc.mjs +71 -0
  197. package/assets/docs/tree/publishing.doc.mjs +111 -0
  198. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  199. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  200. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  201. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  202. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  203. package/assets/docs/tree/ship.doc.mjs +16 -0
  204. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  205. package/assets/docs/tree/single-component.doc.mjs +165 -0
  206. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  207. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  208. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  209. package/assets/docs/tree/template-doc-overview.doc.mjs +121 -0
  210. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  211. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  212. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  213. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  214. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  215. package/assets/docs/tree/templates.doc.mjs +34 -0
  216. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  217. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  218. package/assets/docs/tree/themes.doc.mjs +39 -0
  219. package/assets/docs/tree/troubleshooting.doc.mjs +153 -0
  220. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  221. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  222. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  223. package/assets/docs/tree/versioning.doc.mjs +162 -0
  224. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  225. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  226. package/assets/docs/typography.doc.mjs +24 -4
  227. package/assets/docs/working-with-ai.doc.mjs +30 -22
  228. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  229. package/assets/templates/pages/ai-chat/template.doc.mjs +16 -1
  230. package/assets/templates/pages/ai-chat-landing/template.doc.mjs +9 -1
  231. package/assets/templates/pages/blank/template.doc.mjs +3 -1
  232. package/assets/templates/pages/canvas-editor/template.doc.mjs +9 -1
  233. package/assets/templates/pages/centered-hero/template.doc.mjs +3 -1
  234. package/assets/templates/pages/checkout-wizard/template.doc.mjs +1 -0
  235. package/assets/templates/pages/classic-gallery/template.doc.mjs +3 -1
  236. package/assets/templates/pages/contact-form/template.doc.mjs +16 -1
  237. package/assets/templates/pages/dashboard/template.doc.mjs +15 -1
  238. package/assets/templates/pages/dashboard-alert-rail/template.doc.mjs +23 -1
  239. package/assets/templates/pages/dashboard-cohort-funnel/template.doc.mjs +10 -1
  240. package/assets/templates/pages/dashboard-comparison/template.doc.mjs +9 -1
  241. package/assets/templates/pages/dashboard-composition/template.doc.mjs +10 -1
  242. package/assets/templates/pages/dashboard-progress/template.doc.mjs +17 -1
  243. package/assets/templates/pages/dashboard-scorecard/template.doc.mjs +2 -1
  244. package/assets/templates/pages/detail-page/template.doc.mjs +8 -0
  245. package/assets/templates/pages/documentation/template.doc.mjs +10 -1
  246. package/assets/templates/pages/documentation-design/template.doc.mjs +10 -1
  247. package/assets/templates/pages/documentation-technical/template.doc.mjs +10 -1
  248. package/assets/templates/pages/editor/template.doc.mjs +9 -1
  249. package/assets/templates/pages/file-explorer/template.doc.mjs +3 -1
  250. package/assets/templates/pages/form-two-column/template.doc.mjs +17 -1
  251. package/assets/templates/pages/form-wizard/template.doc.mjs +14 -1
  252. package/assets/templates/pages/form-wizard-dialog/template.doc.mjs +1 -0
  253. package/assets/templates/pages/gallery-hero/template.doc.mjs +10 -1
  254. package/assets/templates/pages/ide/template.doc.mjs +9 -1
  255. package/assets/templates/pages/incident-console/template.doc.mjs +10 -1
  256. package/assets/templates/pages/kanban-board/template.doc.mjs +11 -1
  257. package/assets/templates/pages/library/template.doc.mjs +15 -1
  258. package/assets/templates/pages/login/template.doc.mjs +10 -1
  259. package/assets/templates/pages/login-card/template.doc.mjs +11 -1
  260. package/assets/templates/pages/login-split/template.doc.mjs +10 -1
  261. package/assets/templates/pages/login-sso/template.doc.mjs +10 -1
  262. package/assets/templates/pages/messaging-shell/template.doc.mjs +11 -1
  263. package/assets/templates/pages/mixed-gallery/template.doc.mjs +10 -1
  264. package/assets/templates/pages/payment-form/template.doc.mjs +3 -1
  265. package/assets/templates/pages/product-detail/template.doc.mjs +9 -1
  266. package/assets/templates/pages/product-gallery/template.doc.mjs +10 -1
  267. package/assets/templates/pages/settings/template.doc.mjs +3 -1
  268. package/assets/templates/pages/settings-dialog/template.doc.mjs +9 -1
  269. package/assets/templates/pages/settings-sidebar/template.doc.mjs +9 -1
  270. package/assets/templates/pages/shell-nav/template.doc.mjs +10 -1
  271. package/assets/templates/pages/shell-side-nav/template.doc.mjs +14 -1
  272. package/assets/templates/pages/shell-top-nav/template.doc.mjs +11 -1
  273. package/assets/templates/pages/side-gallery/template.doc.mjs +3 -1
  274. package/assets/templates/pages/table/template.doc.mjs +11 -1
  275. package/assets/templates/pages/table-filter/template.doc.mjs +21 -1
  276. package/assets/templates/pages/table-grouped/template.doc.mjs +15 -1
  277. package/assets/templates/pages/table-inbox/template.doc.mjs +18 -6
  278. package/assets/templates/pages/table-page/template.doc.mjs +20 -1
  279. package/assets/templates/pages/table-tree/template.doc.mjs +14 -1
  280. package/assets/templates/pages/theme-showcase/template.doc.mjs +10 -1
  281. package/assets/templates/pages/work-item-detail/template.doc.mjs +10 -0
  282. package/assets/templates/themes/butter/icons.tsx +2 -0
  283. package/assets/templates/themes/chocolate/icons.tsx +2 -0
  284. package/assets/templates/themes/gothic/icons.tsx +2 -0
  285. package/assets/templates/themes/matcha/icons.tsx +2 -0
  286. package/assets/templates/themes/neutral/icons.tsx +2 -0
  287. package/assets/templates/themes/stone/icons.tsx +2 -0
  288. package/assets/templates/themes/y2k/icons.tsx +2 -0
  289. package/authoring/config/config.doc.mjs +9 -1
  290. package/authoring/config/parse.d.mts +2 -0
  291. package/authoring/config/parse.mjs +19 -0
  292. package/authoring/config/parse.test.mjs +8 -0
  293. package/authoring/config/type.ts +11 -0
  294. package/authoring/discover/discover.doc.d.mts +13 -0
  295. package/authoring/discover/discover.doc.mjs +138 -0
  296. package/authoring/discover/parse.d.mts +24 -0
  297. package/authoring/discover/parse.mjs +128 -0
  298. package/authoring/discover/parse.test.mjs +124 -0
  299. package/authoring/discover/type.ts +87 -0
  300. package/authoring/doctypes/_schema.d.mts +3 -2
  301. package/authoring/doctypes/_schema.mjs +6 -0
  302. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  303. package/authoring/doctypes/base/type.ts +4 -2
  304. package/authoring/doctypes/component/component.doc.mjs +6 -0
  305. package/authoring/doctypes/component/type.ts +8 -0
  306. package/authoring/doctypes/reference/reference.doc.mjs +7 -0
  307. package/authoring/doctypes/reference/type.ts +5 -0
  308. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  309. package/authoring/doctypes/template/parse.d.mts +2 -0
  310. package/authoring/doctypes/template/parse.mjs +1 -0
  311. package/authoring/doctypes/template/parse.test.mjs +21 -0
  312. package/authoring/doctypes/template/template.doc.mjs +7 -1
  313. package/authoring/doctypes/template/type.ts +12 -2
  314. package/authoring/index.d.mts +1 -0
  315. package/authoring/index.d.ts +10 -0
  316. package/authoring/index.mjs +1 -0
  317. package/authoring/integration/integration.doc.mjs +12 -10
  318. package/clients/cli/commands/component/index.mjs +152 -55
  319. package/clients/cli/commands/component-batch.test.mjs +341 -0
  320. package/clients/cli/commands/component-ownership.test.mjs +89 -0
  321. package/clients/cli/commands/component.doc.mjs +27 -9
  322. package/clients/cli/commands/discover.doc.mjs +53 -9
  323. package/clients/cli/commands/discover.mjs +393 -118
  324. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  325. package/clients/cli/commands/docs.doc.mjs +1 -1
  326. package/clients/cli/commands/docs.mjs +60 -17
  327. package/clients/cli/commands/docs.test.mjs +113 -24
  328. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
  329. package/clients/cli/commands/doctor-integration.test.mjs +53 -0
  330. package/clients/cli/commands/doctor.doc.mjs +3 -1
  331. package/clients/cli/commands/doctor.mjs +53 -9
  332. package/clients/cli/commands/gap-report.doc.mjs +10 -9
  333. package/clients/cli/commands/init.doc.mjs +9 -6
  334. package/clients/cli/commands/integration-add.doc.mjs +17 -7
  335. package/clients/cli/commands/integration-authoring.test.mjs +70 -9
  336. package/clients/cli/commands/integration-pack.doc.mjs +5 -9
  337. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  338. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  339. package/clients/cli/commands/integration.doc.mjs +4 -4
  340. package/clients/cli/commands/integration.mjs +76 -43
  341. package/clients/cli/commands/layout-expand.doc.mjs +3 -1
  342. package/clients/cli/commands/layout.expand-receipt.test.mjs +94 -0
  343. package/clients/cli/commands/layout.mjs +16 -0
  344. package/clients/cli/commands/manifest.doc.mjs +1 -1
  345. package/clients/cli/commands/search.doc.mjs +10 -3
  346. package/clients/cli/commands/search.mjs +21 -2
  347. package/clients/cli/commands/search.test.mjs +21 -4
  348. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  349. package/clients/cli/commands/template.copy-receipt.test.mjs +60 -0
  350. package/clients/cli/commands/template.doc.mjs +1 -1
  351. package/clients/cli/commands/template.mjs +19 -5
  352. package/clients/cli/commands/template.show-media.test.mjs +62 -0
  353. package/clients/cli/commands/text-json-parity.test.mjs +7 -1
  354. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  355. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
  356. package/clients/cli/commands/theme-palette.doc.mjs +1 -2
  357. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  358. package/clients/cli/commands/theme.doc.mjs +2 -1
  359. package/clients/cli/commands/upgrade.ascii-output.test.mjs +14 -0
  360. package/clients/cli/commands/upgrade.doc.mjs +62 -3
  361. package/clients/cli/commands/write-failure.test.mjs +175 -0
  362. package/clients/cli/index.mjs +28 -6
  363. package/clients/cli/lib/define-command.mjs +28 -4
  364. package/clients/cli/lib/define-command.test.mjs +54 -0
  365. package/clients/cli/lib/exit-codes.test.mjs +17 -1
  366. package/clients/cli/lib/json-shim.mjs +24 -14
  367. package/clients/cli/lib/manifest.mjs +48 -156
  368. package/clients/cli/lib/manifest.test.mjs +103 -9
  369. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  370. package/foundation/agent-docs/agent-docs.mjs +1 -1
  371. package/foundation/agent-docs/agent-docs.test.mjs +3 -2
  372. package/foundation/discovery/authoring-self-docs.mjs +1 -0
  373. package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
  374. package/foundation/discovery/cli-self-docs.mjs +16 -2
  375. package/foundation/discovery/cli-self-docs.test.mjs +20 -0
  376. package/foundation/discovery/docs-discovery.mjs +5 -1
  377. package/foundation/discovery/docs-discovery.test.mjs +21 -0
  378. package/foundation/discovery/docs-section-key.d.mts +1 -1
  379. package/foundation/discovery/docs-section-key.mjs +1 -1
  380. package/foundation/discovery/template-adapter.d.mts +14 -0
  381. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +37 -1
  382. package/foundation/discovery/template-adapter.mjs +21 -1
  383. package/foundation/doc-compiler/doc-loads.test.mjs +5 -4
  384. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  385. package/foundation/doc-compiler/tree.d.mts +4 -0
  386. package/foundation/doc-compiler/tree.mjs +6 -1
  387. package/foundation/doc-compiler/tree.test.mjs +65 -14
  388. package/foundation/integrations/cli-requirement.d.mts +75 -11
  389. package/foundation/integrations/cli-requirement.mjs +120 -23
  390. package/foundation/integrations/cli-requirement.test.mjs +141 -9
  391. package/foundation/integrations/contribution-inventory.mjs +1 -1
  392. package/foundation/integrations/integrations.d.mts +14 -1
  393. package/foundation/integrations/integrations.mjs +41 -1
  394. package/foundation/integrations/integrations.test.mjs +31 -0
  395. package/foundation/response/batch.type.d.mts +33 -0
  396. package/foundation/response/batch.type.mjs +34 -0
  397. package/foundation/response/error-codes.doc.mjs +6 -8
  398. package/foundation/response/error-codes.test.mjs +30 -5
  399. package/foundation/response/response-types.doc.d.mts +5 -4
  400. package/foundation/response/response-types.doc.mjs +49 -19
  401. package/foundation/response/response-types.doc.test.mjs +23 -0
  402. package/foundation/response/response.doc.mjs +11 -10
  403. package/package.json +9 -9
  404. package/assets/docs/tree/integrations.test.mjs +0 -62
  405. package/assets/docs/tree/writing-docs.doc.mjs +0 -286
@@ -2,20 +2,23 @@
2
2
 
3
3
  /**
4
4
  * @file The build subject's environment access: the page templates a project
5
- * can scaffold.
5
+ * can scaffold, and the components it can use.
6
6
  *
7
- * @input Template discovery for `cwd` — the CLI's own templates plus any that
8
- * the project's configured integrations contribute.
7
+ * @input Template and component discovery for `cwd` — the CLI's own templates
8
+ * and Core's components, plus any that the project's configured integrations
9
+ * contribute.
9
10
  * @output Ready page templates as `{name, displayName, description, category,
10
- * command}`, where `command` is the `astryx template` command that selects
11
- * exactly that template.
12
- * @position Beside build.mjs (api/build/). The kit leaf reads templates only
13
- * through here, because a subject's `_adapter.mjs` is its only environment
14
- * access. Search keeps its own discovery; this adds none of its own, it
15
- * reuses the template subject's.
11
+ * keywords, command}`, where `command` is the `astryx template` command that
12
+ * selects exactly that template; components as `{name, keywords}`.
13
+ * @position Beside build.mjs (api/build/). The kit leaf reads templates and
14
+ * components only through here, because a subject's `_adapter.mjs` is its
15
+ * only environment access. This adds no discovery of its own: templates come
16
+ * from the template subject's, components from search's.
16
17
  */
17
18
 
18
19
  import {discoverTemplates} from '../template/template.mjs';
20
+ import {componentKeywords} from '../search/search.mjs';
21
+ import {findCoreDir} from '../../foundation/fs/paths.mjs';
19
22
 
20
23
  /**
21
24
  * A page template the kit can recommend starting from.
@@ -23,8 +26,16 @@ import {discoverTemplates} from '../template/template.mjs';
23
26
  * @property {string} name The template's own id, as search reports it.
24
27
  * @property {string} command `astryx template <id> --type page`, the command that selects exactly this template: an integration replacement is selected by the Core id it replaces, and `--type page` keeps a block with the same id from making it ambiguous. Search prints template commands the same way.
25
28
  * @property {string} displayName Human-facing name.
26
- * @property {string} description What the page is: its layout and the ideas it serves.
29
+ * @property {string} description What the page is and how it is laid out.
27
30
  * @property {string} category The template's own `Family - Variant` label; empty when it declares none.
31
+ * @property {string[]} keywords The ideas the page serves, as its own descriptor names them; empty when it declares none.
32
+ */
33
+
34
+ /**
35
+ * A component the project can use, as the ranker reads it.
36
+ * @typedef {object} ComponentWords
37
+ * @property {string} name The component's name, e.g. `DateRangeInput`.
38
+ * @property {string[]} keywords The keywords its own doc declares.
28
39
  */
29
40
 
30
41
  /**
@@ -53,8 +64,28 @@ export async function loadPageTemplates(cwd) {
53
64
  displayName: t.displayName || t.name,
54
65
  description: t.description || '',
55
66
  category: t.category || '',
67
+ keywords: t.keywords ?? [],
56
68
  // The id `template()` resolves back to this entry: an active replacement
57
69
  // owns the Core id it names, so that id selects it, not its own.
58
70
  command: `astryx template ${t.replaces ?? t.dirName} --type page`,
59
71
  }));
60
72
  }
73
+
74
+ /**
75
+ * The components the project can use, Core's and its integrations', each with
76
+ * the keywords its own doc declares: what the ranker reads to tell a part of a
77
+ * page from a page. Search's own discovery, so both agree on what exists; empty
78
+ * when Core cannot be found.
79
+ *
80
+ * @param {string} cwd
81
+ * @returns {Promise<ComponentWords[]>}
82
+ */
83
+ export async function loadComponents(cwd) {
84
+ const coreDir = findCoreDir(cwd);
85
+ if (!coreDir) return [];
86
+ try {
87
+ return await componentKeywords(coreDir, cwd);
88
+ } catch {
89
+ return [];
90
+ }
91
+ }
@@ -19,8 +19,8 @@ export const doc = {
19
19
  'The "build a page" entry point. Called with no query it returns the ' +
20
20
  'how-to-build-a-page playbook as data: the workflow steps with their ' +
21
21
  'commands, the on-system rules, and related lookups. Called with a query it names the page template to ' +
22
- 'START from (always one: the page template a ranker built for long descriptions puts first, else the app ' +
23
- 'shell) and the next two templates, ' +
22
+ 'START from (always one: the page template a ranker built for long descriptions puts first; for a part ' +
23
+ 'of a page, the page it names; else the app shell) and the next two templates, ' +
24
24
  'and the unified search grouped around it: the other close page templates, drop-in blocks, and ' +
25
25
  'idea-specific components/hooks, plus the always-on frame + foundation. A template carries the page ' +
26
26
  'frame and spacing, so the kit never recommends composing a page from components.',
@@ -40,6 +40,7 @@ export const doc = {
40
40
  type: 'string',
41
41
  description:
42
42
  'Directory to resolve @astryxdesign/core and templates from.',
43
+ default: 'process.cwd()',
43
44
  },
44
45
  {
45
46
  name: 'options.type',
@@ -69,7 +70,11 @@ export const doc = {
69
70
  throws: [
70
71
  {
71
72
  code: 'ERR_INVALID_ARGUMENT',
72
- when: 'options.type is not a known domain, or options.limit is not a positive integer',
73
+ when: 'a query is given and options.type is not a known domain, or options.limit is not a positive integer',
74
+ },
75
+ {
76
+ code: 'ERR_CORE_NOT_FOUND',
77
+ when: 'a query is given and @astryxdesign/core cannot be found from cwd',
73
78
  },
74
79
  ],
75
80
  examples: [
@@ -8,7 +8,7 @@ import {describe, it, expect, vi} from 'vitest';
8
8
  import * as path from 'node:path';
9
9
  import {fileURLToPath} from 'node:url';
10
10
  import {build} from './build.mjs';
11
- import {search} from '../search/search.mjs';
11
+ import {search, searchedComponents} from '../search/search.mjs';
12
12
 
13
13
  // api/build/ -> up 3 = packages/cli, up 4 = repo root (has packages/core).
14
14
  const REPO = path.resolve(
@@ -152,6 +152,16 @@ describe('build API', () => {
152
152
  });
153
153
  });
154
154
 
155
+ describe('build kit — reuses the components its search gathered', () => {
156
+ it('keeps them beside the search response, out of its JSON', async () => {
157
+ const all = await search('date picker', {cwd: REPO});
158
+ expect(searchedComponents(all)?.map(c => c.name)).toContain('DateRangeInput');
159
+ expect(JSON.stringify(all)).not.toContain('"keywords"');
160
+ const pagesOnly = await search('date picker', {cwd: REPO, type: 'template'});
161
+ expect(searchedComponents(pagesOnly)).toBeNull();
162
+ }, 60_000);
163
+ });
164
+
155
165
  describe('build kit — coverage gates the pages group', () => {
156
166
  it('does not call a one-word coincidence a direct match', async () => {
157
167
  // A page's keywords include every component its source renders, so any
@@ -179,6 +189,28 @@ describe('build kit — coverage gates the pages group', () => {
179
189
  }
180
190
  });
181
191
 
192
+ it('does not call a page that only mentions every word a direct match', async () => {
193
+ // `empty state` and `command palette` name components. A page whose text
194
+ // mentions both words, or that renders the component, is a layout
195
+ // reference, not the page the reader asked for.
196
+ for (const query of ['empty state', 'command palette']) {
197
+ const r = await build(query, {cwd: REPO});
198
+ if (r.type !== 'build.kit') throw new Error('expected build.kit');
199
+ expect(r.data.directMatch, query).toBe(false);
200
+ }
201
+ });
202
+
203
+ it('keeps the page and component a query names first', async () => {
204
+ const pageOf = async (/** @type {string} */ query) => {
205
+ const r = await build(query, {cwd: REPO});
206
+ if (r.type !== 'build.kit') throw new Error('expected build.kit');
207
+ return r.data;
208
+ };
209
+ expect((await pageOf('checkout flow')).pages[0]).toMatchObject({name: 'checkout-wizard'});
210
+ expect((await pageOf('sign in with sso')).pages[0]).toMatchObject({name: 'login-sso'});
211
+ expect((await pageOf('search results')).domain.map(e => e.name)).toContain('PowerSearch');
212
+ });
213
+
182
214
  it('leaves single-concept queries alone (nothing to cover)', async () => {
183
215
  const r = await build('dashboard', {cwd: REPO});
184
216
  expect(r.type).toBe('build.kit');
@@ -237,7 +269,7 @@ describe('build kit — a thin kit says what to try next', () => {
237
269
  // A skeleton is a 35-line excerpt: a reader who studies it and composes
238
270
  // the rest loses the spacing the template exists to carry. A loose match
239
271
  // is still the best start there is, so `start` scaffolds it.
240
- const r = await build('executive summary', {cwd: REPO});
272
+ const r = await build('quarterly business review', {cwd: REPO});
241
273
  expect(r.type).toBe('build.kit');
242
274
  if (r.type !== 'build.kit') return;
243
275
  expect(r.data.directMatch).toBe(false);
@@ -335,9 +367,35 @@ describe('build kit — every page starts from a template', () => {
335
367
  const placed = await build('an empty state for a settings page', {cwd: REPO});
336
368
  if (placed.type !== 'build.kit') throw new Error(placed.type);
337
369
  expect(placed.data.start).toMatchObject({name: 'settings', basis: 'closest'});
370
+ expect(placed.data.start?.reason).toMatch(/part of a page, so it starts from the page it names/);
338
371
  const loose = await build('a date range picker', {cwd: REPO});
339
372
  if (loose.type !== 'build.kit') throw new Error(loose.type);
340
373
  expect(loose.data.start).toMatchObject({name: 'shell-top-nav', basis: 'fallback'});
374
+ expect(loose.data.start?.reason).toMatch(/part of a page and names no page, so it starts from the app shell/);
375
+ });
376
+
377
+ it('starts a change to an existing page from the app shell', async () => {
378
+ // The page is the builder's to keep; no template scaffolds it.
379
+ const r = await build('add a sort toggle to the existing reports dashboard', {cwd: REPO});
380
+ if (r.type !== 'build.kit') throw new Error(r.type);
381
+ expect(r.data.start).toMatchObject({name: 'shell-top-nav', basis: 'fallback'});
382
+ expect(r.data.start?.reason).toMatch(/changes a page you already have, so keep it/);
383
+ expect(r.data.start?.reason).not.toMatch(/too little of the idea fits/);
384
+ // A direct match the response reports is still named.
385
+ if (r.data.directMatch) expect(r.data.start?.reason).toContain(`\`${r.data.pages[0].name}\``);
386
+ });
387
+
388
+ it('does not call a new page that mentions something existing a change', async () => {
389
+ for (const idea of [
390
+ 'a new dashboard inspired by the existing one',
391
+ 'a new dashboard based on the existing dashboard',
392
+ 'clone the existing dashboard as a new page',
393
+ ]) {
394
+ const r = await build(idea, {cwd: REPO});
395
+ if (r.type !== 'build.kit') throw new Error(r.type);
396
+ expect(r.data.start?.name).toBe('dashboard');
397
+ expect(r.data.start?.reason).not.toMatch(/already have/);
398
+ }
341
399
  });
342
400
 
343
401
  it('names a direct match the ranker outweighed in the reason', async () => {
@@ -27,10 +27,13 @@
27
27
  * the invocation stays the renderer's job.
28
28
  */
29
29
 
30
- import {search} from '../../search/search.mjs';
30
+ import {search, searchedComponents} from '../../search/search.mjs';
31
+ import {findCoreDir} from '../../../foundation/fs/paths.mjs';
32
+ import {AstryxError} from '../../error.mjs';
33
+ import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
31
34
  import {getResultCoverage} from '../../search/coverage.mjs';
32
- import {loadPageTemplates} from '../_adapter.mjs';
33
- import {pickAlternatives, pickStart, rankPages} from './rank.mjs';
35
+ import {loadComponents, loadPageTemplates} from '../_adapter.mjs';
36
+ import {ideaKind, pickAlternatives, pickStart, rankPages} from './rank.mjs';
34
37
 
35
38
  /** A page at/above this score is a confident direct match. */
36
39
  const PAGE_DIRECT = 95;
@@ -115,6 +118,24 @@ const asTemplate = t => ({
115
118
  command: `${t.command} <path>`,
116
119
  });
117
120
 
121
+ /**
122
+ * Why a part of a page, or a change to a page the builder already has, starts
123
+ * where it does (spec:AST-048/FR3, FR9): the rest of the start's reason, or
124
+ * null for a whole page.
125
+ * @param {import('./rank.mjs').IdeaKind} kind
126
+ * @param {boolean} inPage whether the start is the page the idea names
127
+ * @returns {string | null}
128
+ */
129
+ function placement(kind, inPage) {
130
+ if (kind === 'edit')
131
+ return 'the idea changes a page you already have, so keep it and add blocks to it; a new page starts from the app shell.';
132
+ if (kind === 'part')
133
+ return inPage
134
+ ? 'the idea is a part of a page, so it starts from the page it names.'
135
+ : 'the idea is a part of a page and names no page, so it starts from the app shell.';
136
+ return null;
137
+ }
138
+
118
139
  /**
119
140
  * The template to start from: the ready page the ranker puts first when it
120
141
  * has the evidence to lead, else the first fallback shell the project can
@@ -126,12 +147,13 @@ const asTemplate = t => ({
126
147
  * the reason names it, so the reader knows why the kit starts elsewhere.
127
148
  *
128
149
  * @param {import('./rank.mjs').RankedPage[]} ranked
150
+ * @param {import('./rank.mjs').IdeaKind} kind
129
151
  * @param {SearchResultEntry[]} pages
130
152
  * @param {boolean} directMatch
131
153
  * @param {PageTemplate[]} catalog
132
154
  * @returns {Omit<BuildStart, 'alternatives'> | null}
133
155
  */
134
- function chooseStart(ranked, pages, directMatch, catalog) {
156
+ function chooseStart(ranked, kind, pages, directMatch, catalog) {
135
157
  const direct = directMatch ? pages[0].name : null;
136
158
  const unready =
137
159
  direct && !catalog.some(t => t.name === direct) ? direct : null;
@@ -139,20 +161,32 @@ function chooseStart(ranked, pages, directMatch, catalog) {
139
161
  // match the ranker outweighed is named, and so are the loose page matches
140
162
  // search listed when the kit falls back to the shell.
141
163
  const loose = pages.map(p => `\`${p.name}\``).join(', ');
142
- const pick = pickStart(ranked);
164
+ /**
165
+ * A part's or an edit's reason, naming a direct match that is not the start.
166
+ * @param {string} place
167
+ * @param {string} startName
168
+ */
169
+ const placed = (place, startName) =>
170
+ direct && direct !== startName
171
+ ? `Search matched \`${direct}\` by name, but ${place}`
172
+ : place[0].toUpperCase() + place.slice(1);
173
+ const pick = pickStart(ranked, kind);
143
174
  const closest = pick && catalog.find(t => t.name === pick.name);
144
- if (closest) {
175
+ if (pick && closest) {
145
176
  const agrees = closest.name === direct;
177
+ const place = placement(kind, pick.base && pick.familyNamed);
146
178
  return {
147
179
  ...asTemplate(closest),
148
180
  basis: agrees ? 'direct' : 'closest',
149
- reason: agrees
150
- ? 'Matches the idea.'
151
- : unready
152
- ? `\`${unready}\` matches but is not ready yet; this is the closest ready template.`
153
- : direct
154
- ? `Search matched \`${direct}\` by name, but this template fits more of the idea.`
155
- : 'The closest template; none is exactly this page.',
181
+ reason: unready
182
+ ? `\`${unready}\` matches but is not ready yet; this is the closest ready template.`
183
+ : place
184
+ ? placed(place, closest.name)
185
+ : agrees
186
+ ? 'Matches the idea.'
187
+ : direct
188
+ ? `Search matched \`${direct}\` by name, but this template fits more of the idea.`
189
+ : 'The closest template; none is exactly this page.',
156
190
  };
157
191
  }
158
192
  for (const id of FALLBACK_STARTS) {
@@ -161,18 +195,21 @@ function chooseStart(ranked, pages, directMatch, catalog) {
161
195
  // The shell can also be the ranker's best guess without the evidence to
162
196
  // lead ("horizontal site navigation"); say so rather than "no match".
163
197
  const nearest = ranked[0]?.name === shell.name && ranked[0].hits > 0;
198
+ const place = placement(kind, false);
164
199
  return {
165
200
  ...asTemplate(shell),
166
201
  basis: 'fallback',
167
202
  reason: unready
168
203
  ? `\`${unready}\` matches but is not ready yet, so start from the app shell.`
169
- : direct
170
- ? `Search matched \`${direct}\` by name, but too little of the idea fits it, so start from the app shell.`
171
- : nearest
172
- ? 'No template is a clear match; the app shell is the closest.'
173
- : loose
174
- ? `Search matched ${loose} only loosely, so start from the app shell.`
175
- : 'No template matched, so start from the app shell.',
204
+ : place
205
+ ? placed(place, shell.name)
206
+ : direct
207
+ ? `Search matched \`${direct}\` by name, but too little of the idea fits it, so start from the app shell.`
208
+ : nearest
209
+ ? 'No template is a clear match; the app shell is the closest.'
210
+ : loose
211
+ ? `Search matched ${loose} only loosely, so start from the app shell.`
212
+ : 'No template matched, so start from the app shell.',
176
213
  };
177
214
  }
178
215
  }
@@ -188,12 +225,30 @@ function chooseStart(ranked, pages, directMatch, catalog) {
188
225
  */
189
226
  export async function buildKit(query, options = {}) {
190
227
  const {cwd = process.cwd(), type, limit = 60} = options;
228
+ // A kit is built from Core's components, hooks, and templates. An open
229
+ // search without core covers the docs alone, so the kit asks for core here.
230
+ if (type !== 'doc' && !findCoreDir(cwd)) {
231
+ throw new AstryxError(
232
+ 'Could not find @astryxdesign/core package',
233
+ undefined,
234
+ ERROR_CODES.ERR_CORE_NOT_FOUND,
235
+ );
236
+ }
191
237
  // search()'s JSDoc @returns widens results to object[]; the SearchResponse
192
238
  // shape is the contract (api/search/search.type.mjs). Cast locally rather than
193
239
  // tightening the search @returns (a separate follow-up).
194
240
  const result =
195
241
  /** @type {import('../../search/search.type.mjs').SearchResponse} */ (
196
- await search(query, {cwd, type, limit})
242
+ await search(query, {
243
+ cwd,
244
+ type,
245
+ // Search wider than the surfaced kit so a flood of doc matches cannot
246
+ // bury the page templates past the cutoff; the caller's `limit` still
247
+ // caps the kit below. A non-positive or non-integer limit is passed
248
+ // through unchanged so search rejects it (ERR_INVALID_ARGUMENT).
249
+ limit:
250
+ Number.isInteger(limit) && limit > 0 ? Math.max(limit, 200) : limit,
251
+ })
197
252
  );
198
253
  const results = result.data.results;
199
254
  // The TOTAL number of matches, not the number that survived `limit`. The kit
@@ -257,13 +312,41 @@ export async function buildKit(query, options = {}) {
257
312
  command: `${page.command} --skeleton`,
258
313
  }));
259
314
 
315
+ // The caller's `limit` caps the surfaced kit, even though the search above
316
+ // ran wider to find templates that a flood of doc matches would otherwise
317
+ // bury past the cutoff. Keep pages first, then blocks, then components.
318
+ let budget = limit;
319
+ /**
320
+ * @template T
321
+ * @param {T[]} arr
322
+ * @returns {T[]}
323
+ */
324
+ const toLimit = arr => {
325
+ const out = arr.slice(0, Math.max(0, budget));
326
+ budget -= out.length;
327
+ return out;
328
+ };
329
+ const pagesKept = toLimit(pages);
330
+ const blocksKept = toLimit(blocks);
331
+ const domainKept = toLimit(domain);
332
+
260
333
  // A kit narrowed to components or hooks has no page to start from; every
261
334
  // other kit does, so the reader is never left to compose a page from scratch.
262
335
  const wantsPages = !type || type === 'template';
263
336
  const catalog = wantsPages ? await loadPageTemplates(cwd) : [];
264
337
  const ranked = wantsPages ? rankPages(query, catalog) : [];
338
+ // A part of a page starts where it lives (spec:AST-048/FR3); the project's
339
+ // own components say what a part is. The search above already gathered them
340
+ // unless it was narrowed to templates.
341
+ const kind = wantsPages
342
+ ? ideaKind(
343
+ query,
344
+ catalog,
345
+ searchedComponents(result) ?? (await loadComponents(cwd)),
346
+ )
347
+ : 'page';
265
348
  const chosen = wantsPages
266
- ? chooseStart(ranked, matchedPages, directMatch, catalog)
349
+ ? chooseStart(ranked, kind, matchedPages, directMatch, catalog)
267
350
  : null;
268
351
  // Name the ranker's next two templates beside the start: the reader judges
269
352
  // meaning better than keywords do, and an acceptable template is in these
@@ -288,7 +371,7 @@ export async function buildKit(query, options = {}) {
288
371
  // not resolve — the same defect `getCliInvocation` exists to prevent, and
289
372
  // the renderer applies it. A JSON caller gets the parts, not a sentence.
290
373
  const hint =
291
- pages.length + blocks.length + domain.length < THIN_KIT
374
+ pagesKept.length + blocksKept.length + domainKept.length < THIN_KIT
292
375
  ? {
293
376
  reason:
294
377
  'Few matches. This is keyword search, not semantic — try other wordings.',
@@ -306,9 +389,9 @@ export async function buildKit(query, options = {}) {
306
389
  matchCount,
307
390
  directMatch,
308
391
  start,
309
- pages,
310
- blocks,
311
- domain,
392
+ pages: pagesKept,
393
+ blocks: blocksKept,
394
+ domain: domainKept,
312
395
  frame: FRAME,
313
396
  foundation: FOUNDATION,
314
397
  hint,
@@ -1,10 +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
- * @typedef {import('../_adapter.mjs').PageTemplate} PageTemplate
6
- * @typedef {{name: string, score: number, hits: number, familyNamed: boolean, containerMatched: boolean}} RankedPage
7
- */
8
4
  /**
9
5
  * Rank page templates against an idea, best first. Ties go to the template
10
6
  * with the shorter id (the family's broader page), then by name.
@@ -14,6 +10,17 @@
14
10
  * @returns {RankedPage[]}
15
11
  */
16
12
  export function rankPages(query: string, pages: PageTemplate[]): RankedPage[];
13
+ /**
14
+ * What an idea asks for (spec:AST-048/FR3): a whole `page`; a `part` of one,
15
+ * when its head noun names one of the system's components and it lists fewer
16
+ * than PAGE_PIECES pieces; or an `edit` of a page the builder already has.
17
+ *
18
+ * @param {string} query
19
+ * @param {PageTemplate[]} pages
20
+ * @param {ComponentWords[]} components
21
+ * @returns {IdeaKind}
22
+ */
23
+ export function ideaKind(query: string, pages: PageTemplate[], components: ComponentWords[]): IdeaKind;
17
24
  /**
18
25
  * The next closest templates after the start, best first: the ones a reader
19
26
  * should check the idea against when the start's shape is wrong. Each matched
@@ -26,19 +33,28 @@ export function rankPages(query: string, pages: PageTemplate[]): RankedPage[];
26
33
  */
27
34
  export function pickAlternatives(ranked: RankedPage[], startName: string, count?: number): RankedPage[];
28
35
  /**
29
- * The template to start from, or null when the best one has too little
30
- * evidence to lead and the page should start from the app shell. Evidence is
31
- * two matched terms, the idea naming the template's family, or its container.
36
+ * The template to start from, or null for the kit's neutral app shell. A page
37
+ * needs evidence to lead: two matched terms, the idea naming the template's
38
+ * family, or its container. A part starts from the base template of the family
39
+ * the idea places it in, else from the app shell (spec:AST-048/FR3); an edit of
40
+ * a page the builder already has starts from the app shell (FR9). Either way,
41
+ * the app shell is the shell template the idea describes when one leads.
32
42
  *
33
43
  * @param {RankedPage[]} ranked
44
+ * @param {IdeaKind} [kind]
34
45
  * @returns {RankedPage | null}
35
46
  */
36
- export function pickStart(ranked: RankedPage[]): RankedPage | null;
47
+ export function pickStart(ranked: RankedPage[], kind?: IdeaKind): RankedPage | null;
37
48
  export type PageTemplate = import("../_adapter.mjs").PageTemplate;
49
+ export type ComponentWords = import("../_adapter.mjs").ComponentWords;
38
50
  export type RankedPage = {
39
51
  name: string;
40
52
  score: number;
41
53
  hits: number;
42
54
  familyNamed: boolean;
43
55
  containerMatched: boolean;
56
+ family: string;
57
+ base: boolean;
58
+ matched: Set<string>;
44
59
  };
60
+ export type IdeaKind = "page" | "part" | "edit";