@astryxdesign/cli 0.7.2 → 0.7.3-canary.02f5fe4

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 (373) hide show
  1. package/README.md +104 -71
  2. package/api/build/_adapter.d.mts +58 -0
  3. package/api/build/_adapter.mjs +127 -3
  4. package/api/build/blocks/blocks.d.mts +92 -0
  5. package/api/build/blocks/blocks.mjs +528 -0
  6. package/api/build/blocks/blocks.test.mjs +238 -0
  7. package/api/build/blocks/blocks.weights.json +1 -0
  8. package/api/build/build.mjs +25 -6
  9. package/api/build/build.type.mjs +1 -1
  10. package/api/build/kit/answer.d.mts +18 -0
  11. package/api/build/kit/answer.mjs +195 -0
  12. package/api/build/kit/answer.test.mjs +108 -0
  13. package/api/build/kit/kind.d.mts +25 -0
  14. package/api/build/kit/kind.mjs +170 -0
  15. package/api/build/kit/kit.d.mts +2 -4
  16. package/api/build/kit/kit.mjs +8 -398
  17. package/api/build/kit/rank.d.mts +3 -32
  18. package/api/build/kit/rank.mjs +25 -342
  19. package/api/build/kit/rank.test.mjs +2 -1
  20. package/api/build/kit/signals.d.mts +79 -0
  21. package/api/build/kit/signals.mjs +295 -0
  22. package/api/build/kit/start.d.mts +32 -0
  23. package/api/build/kit/start.mjs +163 -0
  24. package/api/build/kit/words.d.mts +72 -0
  25. package/api/build/kit/words.mjs +202 -0
  26. package/api/build/tree.d.mts +20 -0
  27. package/api/build/tree.mjs +53 -0
  28. package/api/build/tree.test.mjs +185 -0
  29. package/api/build/tree.weights.json +1 -0
  30. package/api/component/_adapter.mjs +39 -5
  31. package/api/component/component-replacement.test.mjs +1 -0
  32. package/api/component/component.mjs +17 -3
  33. package/api/component/component.test.mjs +15 -0
  34. package/api/component/doc-links.test.mjs +2 -2
  35. package/api/discover/_adapter.d.mts +1 -2
  36. package/api/discover/_adapter.mjs +42 -17
  37. package/api/discover/_adapter.test.mjs +42 -0
  38. package/api/discover/discover.mjs +0 -1
  39. package/api/docs/_adapter.d.mts +2 -2
  40. package/api/docs/_adapter.mjs +82 -23
  41. package/api/docs/docs-homes.test.mjs +127 -0
  42. package/api/docs/docs.doc.mjs +3 -3
  43. package/api/docs/docs.test.mjs +35 -19
  44. package/api/docs/integration-tree.test.mjs +20 -20
  45. package/api/docs/integrationDocs.test.mjs +1 -1
  46. package/api/docs/namespace-section.test.mjs +6 -6
  47. package/api/docs/reference-blocks.test.mjs +2 -2
  48. package/api/doctor/_adapter.d.mts +33 -13
  49. package/api/doctor/_adapter.mjs +55 -25
  50. package/api/doctor/doctor.d.mts +23 -5
  51. package/api/doctor/doctor.mjs +183 -40
  52. package/api/doctor/doctor.test.mjs +95 -12
  53. package/api/hook/hook.mjs +1 -1
  54. package/api/init/init.doc.mjs +20 -6
  55. package/api/init/init.test.mjs +18 -2
  56. package/api/init/init.type.d.mts +3 -3
  57. package/api/init/init.type.mjs +3 -3
  58. package/api/init/remove/remove.mjs +17 -4
  59. package/api/init/remove/remove.test.mjs +114 -2
  60. package/api/init/run/run.mjs +69 -6
  61. package/api/integration/_adapter.d.mts +8 -0
  62. package/api/integration/_adapter.mjs +21 -1
  63. package/api/integration/authoring-checks.mjs +83 -9
  64. package/api/integration/authoring-checks.test.mjs +220 -0
  65. package/api/integration/pack-check.mjs +123 -4
  66. package/api/integration/pack-check.test.mjs +87 -0
  67. package/api/integration/validate-integration-case-disk.test.mjs +111 -0
  68. package/api/integration/validate-integration-fixes.test.mjs +6 -5
  69. package/api/integration/validate-integration-gaps.test.mjs +1975 -0
  70. package/api/integration/validate-integration.d.mts +15 -2
  71. package/api/integration/validate-integration.mjs +298 -39
  72. package/api/integration/validate-integration.type.d.mts +90 -1
  73. package/api/integration/validate-integration.type.mjs +67 -2
  74. package/api/integration/validateIntegration.doc.mjs +1 -1
  75. package/api/search/ORDERING.md +28 -0
  76. package/api/search/_adapter.d.mts +82 -2
  77. package/api/search/_adapter.mjs +157 -10
  78. package/api/search/_adapter.test.mjs +173 -0
  79. package/api/search/_candidate-score.d.mts +40 -0
  80. package/api/search/_candidate-score.mjs +238 -0
  81. package/api/search/_cards.json +6098 -0
  82. package/api/search/_compound.d.mts +50 -0
  83. package/api/search/_compound.mjs +170 -0
  84. package/api/search/_doc-searcher.d.mts +4 -0
  85. package/api/search/_doc-searcher.mjs +23 -0
  86. package/api/search/_doc-searcher.test.mjs +36 -0
  87. package/api/search/_doc-searcher.weights.json +1 -0
  88. package/api/search/_doc-text.d.mts +30 -0
  89. package/api/search/_doc-text.mjs +87 -0
  90. package/api/search/_entries.d.mts +63 -0
  91. package/api/search/_entries.mjs +232 -0
  92. package/api/search/_entries.test.mjs +48 -0
  93. package/api/search/_features.d.mts +35 -0
  94. package/api/search/_features.mjs +155 -0
  95. package/api/search/_gather-components.d.mts +26 -0
  96. package/api/search/_gather-components.mjs +284 -0
  97. package/api/search/_gather-docs.d.mts +20 -0
  98. package/api/search/_gather-docs.mjs +254 -0
  99. package/api/search/_gather-hooks.d.mts +12 -0
  100. package/api/search/_gather-hooks.mjs +52 -0
  101. package/api/search/_gather-templates.d.mts +25 -0
  102. package/api/search/_gather-templates.mjs +107 -0
  103. package/api/search/_lexical.d.mts +135 -0
  104. package/api/search/_lexical.mjs +351 -0
  105. package/api/search/_main-searcher.d.mts +19 -0
  106. package/api/search/_main-searcher.mjs +115 -0
  107. package/api/search/_main-searcher.test.mjs +106 -0
  108. package/api/search/_main-searcher.weights.json +1 -0
  109. package/api/search/_module-doc.d.mts +32 -0
  110. package/api/search/_module-doc.mjs +78 -0
  111. package/api/search/_order.d.mts +32 -0
  112. package/api/search/_order.mjs +162 -0
  113. package/api/search/_order.test.mjs +72 -0
  114. package/api/search/_priority.d.mts +50 -0
  115. package/api/search/_priority.mjs +139 -0
  116. package/api/search/_query-words.d.mts +25 -0
  117. package/api/search/_query-words.mjs +92 -0
  118. package/api/search/_query.d.mts +65 -0
  119. package/api/search/_query.mjs +176 -0
  120. package/api/search/_result.d.mts +97 -0
  121. package/api/search/_result.mjs +150 -0
  122. package/api/search/_score.d.mts +60 -0
  123. package/api/search/_score.mjs +283 -0
  124. package/api/search/_synonyms.d.mts +21 -0
  125. package/api/search/_synonyms.mjs +67 -0
  126. package/api/search/_template-searcher.d.mts +4 -0
  127. package/api/search/_template-searcher.mjs +23 -0
  128. package/api/search/_template-searcher.test.mjs +40 -0
  129. package/api/search/_template-searcher.weights.json +1 -0
  130. package/api/search/_titles.d.mts +33 -0
  131. package/api/search/_titles.mjs +65 -0
  132. package/api/search/_words.d.mts +64 -0
  133. package/api/search/_words.mjs +157 -0
  134. package/api/search/search.d.mts +22 -305
  135. package/api/search/search.doc.mjs +8 -6
  136. package/api/search/search.mjs +56 -2482
  137. package/api/search/search.test.mjs +14 -14
  138. package/api/search/search.type.d.mts +6 -1
  139. package/api/search/search.type.mjs +6 -1
  140. package/api/search/tree.d.mts +15 -0
  141. package/api/search/tree.mjs +40 -0
  142. package/api/search/tree.test.mjs +66 -0
  143. package/api/search/tree.weights.json +1 -0
  144. package/api/template/template.mjs +5 -1
  145. package/api/theme/build/build.packed-old-core.test.mjs +1 -0
  146. package/api/upgrade/_adapter.d.mts +57 -9
  147. package/api/upgrade/_adapter.mjs +198 -28
  148. package/api/upgrade/registry/registry.d.mts +10 -4
  149. package/api/upgrade/registry/registry.mjs +33 -16
  150. package/api/upgrade/registry/registry.test.mjs +85 -0
  151. package/api/upgrade/run/run.d.mts +4 -2
  152. package/api/upgrade/run/run.mjs +13 -2
  153. package/api/upgrade/run/run.test.mjs +417 -3
  154. package/api/upgrade/upgrade.doc.mjs +10 -5
  155. package/api/upgrade/upgrade.mjs +13 -2
  156. package/api/upgrade/upgrade.test.mjs +194 -0
  157. package/api/upgrade/upgrade.type.d.mts +5 -3
  158. package/api/upgrade/upgrade.type.mjs +8 -6
  159. package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
  160. package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
  161. package/assets/docs/author-a-theme.doc.mjs +2 -2
  162. package/assets/docs/is-my-code-good.doc.mjs +287 -0
  163. package/assets/docs/tree/add-a-component.doc.mjs +1 -1
  164. package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
  165. package/assets/docs/tree/add-a-topic.doc.mjs +2 -2
  166. package/assets/docs/tree/agent-guidance.doc.mjs +1 -1
  167. package/assets/docs/tree/api.doc.mjs +6 -0
  168. package/assets/docs/tree/{integrations.doc.mjs → authoring.doc.mjs} +15 -6
  169. package/assets/docs/tree/block-template.doc.mjs +1 -1
  170. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  171. package/assets/docs/tree/building-blocks.doc.mjs +2 -2
  172. package/assets/docs/tree/check-the-props.doc.mjs +1 -1
  173. package/assets/docs/tree/check-your-docs.doc.mjs +2 -2
  174. package/assets/docs/tree/checks.doc.mjs +3 -3
  175. package/assets/docs/tree/ci-and-containers.doc.mjs +13 -0
  176. package/assets/docs/tree/cli-command.doc.mjs +1 -1
  177. package/assets/docs/tree/cli.doc.mjs +1 -1
  178. package/assets/docs/tree/codemods.doc.mjs +1 -1
  179. package/assets/docs/tree/component-family.doc.mjs +1 -1
  180. package/assets/docs/tree/component-imports.doc.mjs +1 -1
  181. package/assets/docs/tree/components.doc.mjs +1 -1
  182. package/assets/docs/tree/configuration.doc.mjs +1 -1
  183. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +1 -1
  184. package/assets/docs/tree/define-the-theme.doc.mjs +1 -1
  185. package/assets/docs/tree/describe-the-component.doc.mjs +1 -1
  186. package/assets/docs/tree/docs.doc.mjs +1 -1
  187. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  188. package/assets/docs/tree/document-the-theme.doc.mjs +1 -1
  189. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  190. package/assets/docs/tree/extend-or-replace.doc.mjs +1 -1
  191. package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
  192. package/assets/docs/tree/fonts-and-assets.doc.mjs +1 -1
  193. package/assets/docs/tree/generate-a-palette.doc.mjs +1 -1
  194. package/assets/docs/tree/global-integrations.doc.mjs +2 -2
  195. package/assets/docs/tree/grade-template-with-agent.doc.mjs +4 -4
  196. package/assets/docs/tree/help.doc.mjs +2 -2
  197. package/assets/docs/tree/host-entry.doc.mjs +128 -0
  198. package/assets/docs/tree/links.doc.mjs +1 -1
  199. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  200. package/assets/docs/tree/page-template.doc.mjs +1 -1
  201. package/assets/docs/tree/publishing.doc.mjs +1 -1
  202. package/assets/docs/tree/quick-start.doc.mjs +1 -1
  203. package/assets/docs/tree/replace-a-core-component.doc.mjs +1 -1
  204. package/assets/docs/tree/replace-a-core-template.doc.mjs +1 -1
  205. package/assets/docs/tree/sections-and-placement.doc.mjs +1 -1
  206. package/assets/docs/tree/see-it-in-an-app.doc.mjs +1 -1
  207. package/assets/docs/tree/ship.doc.mjs +2 -2
  208. package/assets/docs/tree/short-and-findable.doc.mjs +1 -1
  209. package/assets/docs/tree/single-component.doc.mjs +1 -1
  210. package/assets/docs/tree/start-a-template.doc.mjs +1 -1
  211. package/assets/docs/tree/subcomponent.doc.mjs +1 -1
  212. package/assets/docs/tree/template-assets.doc.mjs +1 -1
  213. package/assets/docs/tree/template-doc-overview.doc.mjs +2 -2
  214. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  215. package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
  216. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  217. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  218. package/assets/docs/tree/template-styles.doc.mjs +1 -1
  219. package/assets/docs/tree/templates.doc.mjs +1 -1
  220. package/assets/docs/tree/test-in-an-app.doc.mjs +1 -1
  221. package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
  222. package/assets/docs/tree/themes.doc.mjs +1 -1
  223. package/assets/docs/tree/tokens-data.doc.mjs +2 -2
  224. package/assets/docs/tree/troubleshooting.doc.mjs +1 -1
  225. package/assets/docs/tree/upgrading.doc.mjs +1 -1
  226. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +1 -1
  227. package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
  228. package/assets/docs/tree/versioning.doc.mjs +5 -1
  229. package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
  230. package/assets/docs/tree/write-the-template-file.doc.mjs +1 -1
  231. package/assets/docs/use-integrations.doc.mjs +120 -0
  232. package/assets/docs/working-with-ai.doc.mjs +6 -2
  233. package/assets/templates/themes/butter/butterTheme.ts +4 -2
  234. package/assets/templates/themes/stone/stoneTheme.ts +4 -2
  235. package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
  236. package/authoring/debug/parse.d.mts +1 -1
  237. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  238. package/authoring/integration/integration.doc.mjs +1 -1
  239. package/authoring/integration/type.ts +1 -1
  240. package/clients/cli/bin/astryx.mjs +7 -78
  241. package/clients/cli/command-result-coverage.test.mjs +6 -5
  242. package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
  243. package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
  244. package/clients/cli/commands/component.test.mjs +6 -6
  245. package/clients/cli/commands/docs.doc.mjs +2 -2
  246. package/clients/cli/commands/docs.mjs +1 -1
  247. package/clients/cli/commands/docs.test.mjs +14 -14
  248. package/clients/cli/commands/doctor-integration.test.mjs +49 -1
  249. package/clients/cli/commands/doctor.doc.mjs +1 -1
  250. package/clients/cli/commands/doctor.mjs +40 -0
  251. package/clients/cli/commands/doctor.test.mjs +65 -0
  252. package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
  253. package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
  254. package/clients/cli/commands/init.behavior.test.mjs +230 -1
  255. package/clients/cli/commands/init.doc.mjs +28 -9
  256. package/clients/cli/commands/init.flag-help.test.mjs +1 -0
  257. package/clients/cli/commands/init.mjs +2 -2
  258. package/clients/cli/commands/integration-check.test.mjs +48 -0
  259. package/clients/cli/commands/integration.doc.mjs +1 -1
  260. package/clients/cli/commands/manifest.doc.mjs +1 -1
  261. package/clients/cli/commands/manifest.mjs +67 -0
  262. package/clients/cli/commands/outside-project.test.mjs +101 -1
  263. package/clients/cli/commands/postinstall.doc.mjs +23 -0
  264. package/clients/cli/commands/postinstall.mjs +31 -0
  265. package/clients/cli/commands/setup-nudge.test.mjs +78 -0
  266. package/clients/cli/commands/{build-theme.mjs → theme.mjs} +1 -1
  267. package/clients/cli/commands/upgrade.doc.mjs +4 -2
  268. package/clients/cli/commands/upgrade.mjs +9 -2
  269. package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
  270. package/clients/cli/index.mjs +54 -94
  271. package/clients/cli/lib/component-format.mjs +1 -1
  272. package/clients/cli/lib/define-command.mjs +12 -7
  273. package/clients/cli/lib/exit-codes.test.mjs +5 -0
  274. package/clients/cli/lib/manifest.test.mjs +12 -0
  275. package/clients/cli/lib/welcome-box.mjs +50 -0
  276. package/clients/cli/run.mjs +108 -0
  277. package/foundation/agent-docs/agent-doc-state.d.mts +32 -7
  278. package/foundation/agent-docs/agent-doc-state.mjs +58 -9
  279. package/foundation/agent-docs/agent-docs.d.mts +100 -12
  280. package/foundation/agent-docs/agent-docs.mjs +1017 -105
  281. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
  282. package/foundation/agent-docs/agent-docs.test.mjs +683 -39
  283. package/foundation/agent-docs/computer-agent-text.d.mts +39 -2
  284. package/foundation/agent-docs/computer-agent-text.mjs +135 -8
  285. package/foundation/agent-docs/computer-agent-text.test.mjs +99 -2
  286. package/foundation/config/project.mjs +20 -22
  287. package/foundation/config/project.test.mjs +56 -0
  288. package/foundation/discovery/authoring-self-docs.d.mts +7 -0
  289. package/foundation/discovery/authoring-self-docs.mjs +16 -4
  290. package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
  291. package/foundation/discovery/authoring-surface.d.mts +1 -1
  292. package/foundation/discovery/authoring-surface.mjs +2 -2
  293. package/foundation/discovery/authoring-surface.test.mjs +1 -1
  294. package/foundation/discovery/cli-self-docs.d.mts +2 -1
  295. package/foundation/discovery/cli-self-docs.mjs +4 -3
  296. package/foundation/discovery/cli-self-docs.test.mjs +2 -2
  297. package/foundation/discovery/component-discovery.d.mts +37 -0
  298. package/foundation/discovery/component-discovery.mjs +80 -5
  299. package/foundation/discovery/component-loader.d.mts +1 -1
  300. package/foundation/discovery/docs-discovery.mjs +14 -1
  301. package/foundation/discovery/module-exports.d.mts +41 -0
  302. package/foundation/discovery/module-exports.mjs +253 -0
  303. package/foundation/discovery/runner-allowlist.d.mts +2 -4
  304. package/foundation/discovery/runner-allowlist.mjs +2 -4
  305. package/foundation/discovery/runner-commands.d.mts +77 -0
  306. package/foundation/discovery/runner-commands.mjs +294 -0
  307. package/foundation/discovery/runner-commands.test.mjs +128 -0
  308. package/foundation/discovery/stray-pointers.test.mjs +1 -1
  309. package/foundation/discovery/template-adapter.mjs +18 -1
  310. package/foundation/discovery/template-needs.mjs +1 -44
  311. package/foundation/discovery/theme-discovery.mjs +147 -3
  312. package/foundation/doc-compiler/doc-loads.test.mjs +33 -9
  313. package/foundation/doc-compiler/read.mjs +59 -1
  314. package/foundation/doc-compiler/read.test.mjs +11 -2
  315. package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
  316. package/foundation/doc-compiler/tree.d.mts +32 -6
  317. package/foundation/doc-compiler/tree.mjs +77 -43
  318. package/foundation/doc-compiler/tree.test.mjs +7 -7
  319. package/foundation/fs/paths.d.mts +70 -8
  320. package/foundation/fs/paths.mjs +556 -38
  321. package/foundation/fs/paths.test.mjs +430 -54
  322. package/foundation/fs/read-record.d.mts +18 -0
  323. package/foundation/fs/read-record.mjs +131 -0
  324. package/foundation/fs/read-record.test.mjs +77 -0
  325. package/foundation/integrations/autolink.d.mts +2 -1
  326. package/foundation/integrations/autolink.mjs +4 -13
  327. package/foundation/integrations/cli-peer-version.d.mts +36 -0
  328. package/foundation/integrations/cli-peer-version.mjs +132 -0
  329. package/foundation/integrations/cli-peer-version.test.mjs +354 -0
  330. package/foundation/integrations/computer-integrations.d.mts +6 -3
  331. package/foundation/integrations/computer-integrations.mjs +38 -9
  332. package/foundation/integrations/contribution-inventory.d.mts +15 -20
  333. package/foundation/integrations/contribution-inventory.mjs +41 -5
  334. package/foundation/integrations/exports-subpaths.d.mts +57 -0
  335. package/foundation/integrations/exports-subpaths.mjs +113 -0
  336. package/foundation/integrations/integrations.d.mts +27 -1
  337. package/foundation/integrations/integrations.mjs +61 -2
  338. package/foundation/integrations/public-imports.d.mts +118 -0
  339. package/foundation/integrations/public-imports.mjs +1769 -0
  340. package/foundation/integrations/public-imports.test.mjs +1793 -0
  341. package/foundation/integrations/validate-contributions.d.mts +115 -0
  342. package/foundation/integrations/validate-contributions.mjs +1168 -13
  343. package/foundation/release/cache.test.mjs +24 -21
  344. package/foundation/release/global-state.d.mts +8 -4
  345. package/foundation/release/global-state.mjs +4 -2
  346. package/foundation/release/handoff.d.mts +23 -4
  347. package/foundation/release/handoff.mjs +175 -8
  348. package/foundation/release/notices.d.mts +62 -8
  349. package/foundation/release/notices.mjs +136 -25
  350. package/foundation/release/notices.test.mjs +21 -0
  351. package/foundation/release/run-context.mjs +14 -0
  352. package/foundation/response/response-types.doc.mjs +1 -1
  353. package/foundation/route/route.d.mts +285 -0
  354. package/foundation/route/route.mjs +324 -0
  355. package/foundation/route/route.test.mjs +153 -0
  356. package/foundation/runtime/hosted-runtime.test.mjs +403 -0
  357. package/foundation/runtime/locked-versions.d.mts +32 -0
  358. package/foundation/runtime/locked-versions.mjs +65 -0
  359. package/foundation/runtime/package-root.d.mts +91 -0
  360. package/foundation/runtime/package-root.mjs +174 -0
  361. package/foundation/runtime/package-set.d.mts +62 -0
  362. package/foundation/runtime/package-set.mjs +130 -0
  363. package/foundation/runtime/package-set.test.mjs +432 -0
  364. package/foundation/text/string-utils.d.mts +2 -1
  365. package/foundation/text/string-utils.mjs +16 -5
  366. package/foundation/text/suggest-order.d.mts +72 -0
  367. package/foundation/text/suggest-order.mjs +363 -0
  368. package/foundation/text/suggest-order.test.mjs +259 -0
  369. package/host/door-conformance.test.mjs +274 -0
  370. package/host/index.d.ts +116 -0
  371. package/host/index.mjs +295 -0
  372. package/host/index.test.mjs +302 -0
  373. package/package.json +14 -9
@@ -0,0 +1,238 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file One search term's score against one candidate: name, keyword, prose,
5
+ * and typo signals.
6
+ *
7
+ * Scoring is keyword + fuzzy ranking (NOT semantic / embeddings — that is a
8
+ * deliberate future follow-up). It reuses the same signal weighting as the
9
+ * component fuzzy resolver in lib/string-utils.mjs:
10
+ *
11
+ * 100 exact name match
12
+ * 95 name is the term's plural or stem form ("buttons" -> Button)
13
+ * 90 exact keyword match
14
+ * 88 keyword is the term's plural or stem form
15
+ * 80 name Levenshtein distance 1 (one-word lookups, words of 5+ letters)
16
+ * 70 keyword word prefix / distance 1 (distance: one-word lookups, 5+ letters)
17
+ * 60 name word prefix (>=4 chars, >=50% coverage)
18
+ * 60 exact weak-keyword match
19
+ * 50 description / prose mentions the term
20
+ * 45 usage guidance mentions the term
21
+ * 40 name Levenshtein distance 2 (one-word lookups, 8+ letters)
22
+ * 40 weak-keyword word prefix
23
+ * 30 keyword Levenshtein distance 2 (one-word lookups, 8+ letters)
24
+ * 20 name Levenshtein distance 3 (one-word lookups, 11+ letters)
25
+ *
26
+ * Name + keyword signals always outweigh description/prose, so an exact match
27
+ * sorts above an incidental mention.
28
+ *
29
+ * A term matches inside a name or keyword only at the start of one of its
30
+ * words: "dash" finds "dashboard" and "input" finds "TextInput", but "file"
31
+ * does not find "profile". Edit distance is typo tolerance, so it applies only
32
+ * to a one-word lookup, where a typo is the likely explanation, and only to
33
+ * words long enough that one edit rarely makes another real word. In a
34
+ * sentence, a near miss is usually a different word: "site" is not "side",
35
+ * "cable" is not "table".
36
+ */
37
+
38
+ import {levenshteinDistance} from '../../foundation/text/string-utils.mjs';
39
+ import {
40
+ stem,
41
+ wordForms,
42
+ sameWord,
43
+ startsAWordOf,
44
+ joined,
45
+ isTypo,
46
+ } from './_words.mjs';
47
+ import {pluralOf} from './_query.mjs';
48
+
49
+ /**
50
+ * Score a single candidate against the search term across name, keywords,
51
+ * and prose signals. Returns the best (highest) score plus a human reason,
52
+ * or null if nothing matched above the floor.
53
+ *
54
+ * @param {string} term - Lowercased search term.
55
+ * @param {object} candidate
56
+ * @param {string} candidate.name - Primary identifier (component/hook name, topic, template name).
57
+ * @param {string[]} [candidate.aliases] - Other names, scored like the name (a theme's display name).
58
+ * @param {string} [candidate.domain] - A component, hook, or template name
59
+ * also matches typed as words: `command palette` is CommandPalette.
60
+ * @param {string[]} [candidate.keywords] - Authored intent (componentsUsed, category words).
61
+ * @param {string[]} [candidate.weakKeywords] - Derived signal (components a page renders).
62
+ * @param {string} [candidate.description]
63
+ * @param {string[]} [candidate.prose] - Extra free-text blobs (doc section text, best practices).
64
+ * @param {string[]} [candidate.guidance] - Usage guidance (features, best practices) — scored a tier below description.
65
+ * @param {{fuzzy?: boolean, joins?: boolean}} [opts] - `fuzzy`: allow edit-distance (typo) matches. Default true; multi-word queries pass false. `joins`: read a spaced query joined into a name or keyword (default true); off when the query names an entry outright.
66
+ * @returns {{score: number, reason: string, alias?: 'partial' | 'keyword'} | null}
67
+ * `alias` marks a hit that read the query's words joined.
68
+ */
69
+ export function scoreCandidate(
70
+ term,
71
+ {
72
+ name,
73
+ aliases = [],
74
+ domain,
75
+ keywords = [],
76
+ weakKeywords = [],
77
+ description = '',
78
+ prose = [],
79
+ guidance = [],
80
+ },
81
+ {fuzzy = true, joins = true} = {},
82
+ ) {
83
+ let best = 0;
84
+ let reason = '';
85
+ /** @type {'partial' | 'keyword' | false} */
86
+ let alias = false;
87
+ /**
88
+ * @param {number} score
89
+ * @param {string} why
90
+ * @param {'partial' | 'keyword' | false} [byAlias] - the hit reads the
91
+ * query's words joined, into part of a name or into a keyword
92
+ */
93
+ const consider = (score, why, byAlias = false) => {
94
+ if (score > best) {
95
+ best = score;
96
+ reason = why;
97
+ alias = byAlias;
98
+ }
99
+ };
100
+
101
+ // ── Name signals ────────────────────────────────────────────────
102
+ // An alias is a name too: a theme answers to its display name as well as
103
+ // its slug.
104
+ for (const candidateName of [name, ...aliases.filter(Boolean)]) {
105
+ const nameLower = candidateName.toLowerCase();
106
+ // A placed guide's name is its route, and the route's last segment is its
107
+ // name too, as a flat topic's is: `codemods` is authoring/building-blocks/codemods.
108
+ const leafLower = nameLower.slice(nameLower.lastIndexOf('/') + 1);
109
+
110
+ // A plural of the name is the name: `integration` is the `integrations`
111
+ // guides, `tab` the `tabs` doc.
112
+ // A component, hook, or template name typed as words is its name:
113
+ // `command palette` is CommandPalette. A doc's name is a route or key,
114
+ // matched as written.
115
+ const spelled =
116
+ domain !== 'doc' &&
117
+ !/[\s_-]/.test(nameLower) &&
118
+ nameLower === term.replace(/\s+/g, '');
119
+ if (nameLower === term || leafLower === term || spelled) {
120
+ consider(100, 'exact name');
121
+ } else if (
122
+ joins &&
123
+ (domain === 'component' || domain === 'hook') &&
124
+ /\s/.test(term) &&
125
+ nameLower.startsWith(term.replace(/\s+/g, '')) &&
126
+ term.replace(/\s+/g, '').length / nameLower.length >= 0.75
127
+ ) {
128
+ // Most of the name typed as words, cut short: `complex select` is
129
+ // ComplexSelector, ahead of a one-word keyword elsewhere.
130
+ consider(95, `name "${candidateName}" spelled`, 'partial');
131
+ } else if (pluralOf(nameLower, term) || pluralOf(term, nameLower)) {
132
+ // One point under the exact spelling, so the doc named `tokens` still
133
+ // outranks the Token component for `tokens`.
134
+ consider(99, 'plural of the name');
135
+ } else {
136
+ if (sameWord(term, nameLower)) consider(95, `name "${candidateName}"`);
137
+ // The term is a word of the name, or starts one: "input" in TextInput.
138
+ else if (startsAWordOf(term, candidateName)) {
139
+ consider(60, `name contains "${term}"`);
140
+ }
141
+ if (fuzzy) {
142
+ const dist = levenshteinDistance(term, nameLower);
143
+ if (isTypo(term, nameLower, dist)) {
144
+ consider(
145
+ dist === 1 ? 80 : dist === 2 ? 40 : 20,
146
+ `similar name (distance ${dist})`,
147
+ );
148
+ }
149
+ }
150
+ }
151
+ }
152
+
153
+ // ── Keyword signals ─────────────────────────────────────────────
154
+ const termJoined = joined(term);
155
+ for (const kw of keywords) {
156
+ const kwLower = String(kw).toLowerCase();
157
+ // A one-word keyword typed as separate words is the keyword: `number
158
+ // field` is `numberfield`. Only a
159
+ // lowercase keyword, one an author declares for a reader to type: a
160
+ // capitalized one names another entry (a block's `componentsUsed`). A
161
+ // doc's keywords include code terms, matched as written.
162
+ if (kwLower === term) {
163
+ consider(90, `keyword "${kw}"`);
164
+ continue;
165
+ }
166
+ if (
167
+ joins &&
168
+ domain !== 'doc' &&
169
+ /\s/.test(term) &&
170
+ String(kw) === termJoined
171
+ ) {
172
+ consider(90, `keyword "${kw}"`, 'keyword');
173
+ continue;
174
+ }
175
+ if (sameWord(term, kwLower)) {
176
+ consider(88, `keyword "${kw}"`);
177
+ continue;
178
+ }
179
+ if (startsAWordOf(term, kw)) consider(70, `keyword "${kw}"`);
180
+ if (fuzzy) {
181
+ const dist = levenshteinDistance(term, kwLower);
182
+ if (isTypo(term, kwLower, dist) && dist <= 2) {
183
+ consider(dist === 1 ? 70 : 30, `keyword "${kw}" (distance ${dist})`);
184
+ }
185
+ }
186
+ }
187
+
188
+ // ── Weak keyword signals (derived, not authored) ─────────────────
189
+ // Capped at 60 so one incidental component match cannot clear the
190
+ // confident-match gate on its own; it still counts toward multi-term
191
+ // coverage, which is where "this page renders that" is real evidence.
192
+ // No Levenshtein tier — fuzzy matching a derived signal is pure noise.
193
+ for (const kw of weakKeywords) {
194
+ const kwLower = String(kw).toLowerCase();
195
+ if (kwLower === term || sameWord(term, kwLower)) {
196
+ consider(60, `renders ${kw}`);
197
+ continue;
198
+ }
199
+ if (startsAWordOf(term, kw)) consider(40, `renders ${kw}`);
200
+ }
201
+
202
+ // ── Prose / description / guidance signals (stem-tolerant whole word) ──
203
+ // Match the term's stem as a whole word, tolerating plural/gerund suffixes
204
+ // so "chart" matches "charts" and "filter" matches "filtering".
205
+ if (term.length >= 3) {
206
+ // Any form of the term, with any common suffix: `spacing` finds
207
+ // "space" and "spaces", `tables` finds "table".
208
+ const roots = [...new Set([stem(term), ...wordForms(term)])]
209
+ .filter(f => f.length >= 3)
210
+ .map(f => f.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
211
+ const re = new RegExp(`\\b(?:${roots.join('|')})(s|es|ing|ed|ies)?\\b`);
212
+ if (description && re.test(description.toLowerCase())) {
213
+ consider(50, `description mentions "${term}"`);
214
+ } else {
215
+ let matchedProse = false;
216
+ for (const blob of prose) {
217
+ if (blob && re.test(String(blob).toLowerCase())) {
218
+ consider(50, `docs mention "${term}"`);
219
+ matchedProse = true;
220
+ break;
221
+ }
222
+ }
223
+ // A tier below prose: guidance is what a component says about USING it,
224
+ // so the term appearing there is weaker evidence than the component's own
225
+ // summary. Only consulted when nothing stronger matched.
226
+ if (!matchedProse) {
227
+ for (const blob of guidance) {
228
+ if (blob && re.test(String(blob).toLowerCase())) {
229
+ consider(45, `guidance mentions "${term}"`);
230
+ break;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ return best > 0 ? {score: best, reason, ...(alias ? {alias} : {})} : null;
238
+ }