@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,232 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The entry table search's searchers rank over: every returnable entry
5
+ * with its name words and the BM25 postings of its name, docs text, and card.
6
+ * Built once per gathered catalog.
7
+ */
8
+
9
+ import {createHash} from 'node:crypto';
10
+ import {DOMAINS, words, fold, nameWords} from './_query-words.mjs';
11
+
12
+ /** @param {string[]} list @returns {Map<string, number>} */
13
+ const counts = list => {
14
+ const m = new Map();
15
+ for (const w of list) m.set(w, (m.get(w) ?? 0) + 1);
16
+ return m;
17
+ };
18
+
19
+ /**
20
+ * @typedef {object} EntryTable
21
+ * @property {string[]} ids every returnable `<domain>:<name>`, in code-point order
22
+ * @property {Map<string, number>} index id -> position
23
+ * @property {any[]} candidate one candidate per id, for its result
24
+ * @property {number[]} domain domain index per id
25
+ * @property {string[][]} name each id's name words
26
+ * @property {Record<'name'|'desc'|'card', {post: Map<string, [number, number][]>, idf: Map<string, number>, len: number[], avg: number}>} fields
27
+ */
28
+
29
+ const tables = new WeakMap();
30
+
31
+ /**
32
+ * The entry a lexical result answers as.
33
+ * @param {{index: Map<string, number>}} table
34
+ * @param {{domain: string, name: string, package?: string, section?: string}} res
35
+ * @returns {number | undefined}
36
+ */
37
+ export const entryOf = (table, res) => {
38
+ const id = `${res.domain}:${res.name}${res.section ? `#${res.section}` : ''}`;
39
+ return table.index.get(`${id}|${res.package}`) ?? table.index.get(id);
40
+ };
41
+
42
+ /**
43
+ * The id a candidate answers as: a doc section is its own entry, beside its
44
+ * topic. @param {any} c
45
+ */
46
+ export const entryId = c =>
47
+ c.domain === 'doc'
48
+ ? `doc:${c._topic ?? c.name}${c._section ? `#${c._section}` : ''}`
49
+ : `${c.domain}:${c._resultName ?? c.name}`;
50
+
51
+ /**
52
+ * The entries search can answer with and their text, by field. Each doc
53
+ * section is its own entry. Built once per gathered catalog.
54
+ * @param {any[]} all the gathered candidates
55
+ * @param {Record<string, {what?: string, synonyms?: string[], props?: string[]}>} cards
56
+ * @returns {EntryTable}
57
+ */
58
+ export function entryTable(all, cards) {
59
+ const hit = tables.get(all);
60
+ if (hit) return hit;
61
+ // Each search gathers a fresh candidate list, so the table is also kept by
62
+ // the text it is built from: an unchanged catalog reuses it.
63
+ const key = fingerprint(all, cards);
64
+ if (last && last.key === key) {
65
+ tables.set(all, last.table);
66
+ return last.table;
67
+ }
68
+ const built = buildTable(all, cards);
69
+ last = {key, table: built};
70
+ tables.set(all, built);
71
+ return built;
72
+ }
73
+
74
+ /** @type {{key: string, table: EntryTable} | null} */
75
+ let last = null;
76
+ /** @type {WeakMap<object, number>} */
77
+ const cardIds = new WeakMap();
78
+ let nextCardId = 0;
79
+
80
+ /**
81
+ * The candidate fields buildTable reads, all of them hashed by fingerprint;
82
+ * `_entries.test.mjs` fails if buildTable starts reading another.
83
+ */
84
+ /** How many guidance lines and prose paragraphs of a candidate the index reads. */
85
+ const GUIDANCE_LINES = 10;
86
+ const PROSE_PARAGRAPHS = 4;
87
+
88
+ export const HASHED_FIELDS = Object.freeze([
89
+ 'domain',
90
+ 'name',
91
+ '_topic',
92
+ '_section',
93
+ '_resultName',
94
+ '_package',
95
+ 'description',
96
+ 'keywords',
97
+ 'aliases',
98
+ 'titles',
99
+ 'guidance',
100
+ 'prose',
101
+ ]);
102
+
103
+ /**
104
+ * Everything the table reads from the catalog, hashed.
105
+ * @param {any[]} all
106
+ * @param {object} cards
107
+ * @returns {string}
108
+ */
109
+ function fingerprint(all, cards) {
110
+ if (!cardIds.has(cards)) cardIds.set(cards, nextCardId++);
111
+ const h = createHash('sha1');
112
+ h.update(String(cardIds.get(cards)));
113
+ for (const c of all) {
114
+ h.update(
115
+ JSON.stringify(
116
+ HASHED_FIELDS.map(f =>
117
+ f === 'guidance'
118
+ ? (c.guidance ?? []).slice(0, GUIDANCE_LINES)
119
+ : f === 'prose'
120
+ ? (c.prose ?? []).slice(0, PROSE_PARAGRAPHS)
121
+ : c[f],
122
+ ),
123
+ ),
124
+ );
125
+ }
126
+ return h.digest('hex');
127
+ }
128
+
129
+ /**
130
+ * @param {any[]} all
131
+ * @param {Record<string, {what?: string, synonyms?: string[], props?: string[]}>} cards
132
+ * @returns {EntryTable}
133
+ */
134
+ export function buildTable(all, cards) {
135
+ /** @type {Map<string, any[]>} */
136
+ const by = new Map();
137
+ /** @type {Map<string, string>} each id's first package */
138
+ const owner = new Map();
139
+ for (const c of all) {
140
+ // Two packages may each give an entry the same name (an integration's
141
+ // Dialog beside Core's): the later package's entry keeps its own id.
142
+ const plain = entryId(c);
143
+ if (!owner.has(plain)) owner.set(plain, c._package ?? '');
144
+ const id =
145
+ (c._package ?? '') === owner.get(plain)
146
+ ? plain
147
+ : `${plain}|${c._package}`;
148
+ if (!by.has(id)) by.set(id, []);
149
+ /** @type {any[]} */ (by.get(id)).push(c);
150
+ }
151
+ const ids = [...by.keys()].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
152
+ /** @type {Record<'name'|'desc'|'card', Map<string, number>[]>} */
153
+ const docs = {name: [], desc: [], card: []};
154
+ const table = /** @type {EntryTable} */ (
155
+ /** @type {unknown} */ ({
156
+ ids,
157
+ index: new Map(ids.map((id, k) => [id, k])),
158
+ candidate: [],
159
+ domain: [],
160
+ name: [],
161
+ fields: {},
162
+ })
163
+ );
164
+ for (const id of ids) {
165
+ const group = /** @type {any[]} */ (by.get(id));
166
+ const first = group.find(c => !c._section) ?? group[0];
167
+ const plain = id.split('|')[0].split('#')[0];
168
+ const [domain, name] = [
169
+ plain.slice(0, plain.indexOf(':')),
170
+ plain.slice(plain.indexOf(':') + 1),
171
+ ];
172
+ const nw = nameWords(name).map(fold);
173
+ table.candidate.push(first);
174
+ table.domain.push(DOMAINS.indexOf(domain));
175
+ table.name.push(nw);
176
+ const text = [];
177
+ for (const c of group) {
178
+ text.push(
179
+ c.description ?? '',
180
+ ...(c.keywords ?? []),
181
+ ...(c.aliases ?? []),
182
+ ...(c.titles ?? []),
183
+ );
184
+ text.push(
185
+ ...(c.guidance ?? []).slice(0, GUIDANCE_LINES),
186
+ ...(c.prose ?? []).slice(0, PROSE_PARAGRAPHS),
187
+ );
188
+ }
189
+ const card =
190
+ domain === 'component' || domain === 'hook' ? cards[name] : undefined;
191
+ docs.name.push(counts([...nw, nw.join('')]));
192
+ docs.desc.push(counts(words(text.join(' ')).map(fold)));
193
+ docs.card.push(
194
+ counts(
195
+ card
196
+ ? words(
197
+ [
198
+ card.what ?? '',
199
+ ...(card.synonyms ?? []),
200
+ ...(card.props ?? []),
201
+ ].join(' '),
202
+ ).map(fold)
203
+ : [],
204
+ ),
205
+ );
206
+ }
207
+ const n = ids.length;
208
+ for (const f of /** @type {const} */ (['name', 'desc', 'card'])) {
209
+ /** @type {Map<string, [number, number][]>} */
210
+ const post = new Map();
211
+ /** @type {Map<string, number>} */
212
+ const df = new Map();
213
+ /** @type {number[]} */
214
+ const len = [];
215
+ docs[f].forEach((m, k) => {
216
+ let l = 1;
217
+ for (const [w, c] of m) {
218
+ l += c;
219
+ df.set(w, (df.get(w) ?? 0) + 1);
220
+ const list = post.get(w) ?? [];
221
+ list.push([k, c]);
222
+ post.set(w, list);
223
+ }
224
+ len.push(l);
225
+ });
226
+ const idf = new Map();
227
+ for (const [w, d] of df)
228
+ idf.set(w, Math.log(1 + (n - d + 0.5) / (d + 0.5)));
229
+ table.fields[f] = {post, idf, len, avg: len.reduce((a, b) => a + b, 0) / n};
230
+ }
231
+ return table;
232
+ }
@@ -0,0 +1,48 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The entry index is reused while the catalog's text is unchanged, so
5
+ * every field it reads must be part of the hash that decides reuse.
6
+ */
7
+
8
+ import {describe, it, expect} from 'vitest';
9
+ import * as path from 'node:path';
10
+ import {fileURLToPath} from 'node:url';
11
+ import {gatherCandidates, loadSearchData} from './_adapter.mjs';
12
+ import {HASHED_FIELDS, buildTable, entryTable} from './_entries.mjs';
13
+
14
+ const cwd = path.resolve(
15
+ path.dirname(fileURLToPath(import.meta.url)),
16
+ '../../../..',
17
+ );
18
+
19
+ describe('entry index cache', () => {
20
+ it('hashes every candidate field the index reads', async () => {
21
+ const {all} = await gatherCandidates({cwd});
22
+ /** @type {Set<string>} */
23
+ const read = new Set();
24
+ const watched = all.map(
25
+ c =>
26
+ new Proxy(c, {
27
+ get(target, key, receiver) {
28
+ if (typeof key === 'string') read.add(key);
29
+ return Reflect.get(target, key, receiver);
30
+ },
31
+ }),
32
+ );
33
+ buildTable(watched, loadSearchData().cards);
34
+ const unhashed = [...read].filter(k => !HASHED_FIELDS.includes(k));
35
+ expect(unhashed).toEqual([]);
36
+ }, 60_000);
37
+
38
+ it('rebuilds when a candidate text changes and reuses it otherwise', async () => {
39
+ const {all} = await gatherCandidates({cwd});
40
+ const {cards} = loadSearchData();
41
+ const first = entryTable([...all], cards);
42
+ expect(entryTable([...all], cards)).toBe(first);
43
+ const changed = all.map((c, i) =>
44
+ i === 0 ? {...c, description: `${c.description ?? ''} changed`} : c,
45
+ );
46
+ expect(entryTable(changed, cards)).not.toBe(first);
47
+ }, 60_000);
48
+ });
@@ -0,0 +1,35 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * Every entry's signals for one query, as rows of numbers.
6
+ * @param {EntryTable} table
7
+ * @param {string} query
8
+ * @param {{domain: string, name: string, score?: number}[]} lexical the lexical ranking, best first
9
+ * @param {number[] | null} route the router's class probabilities
10
+ * @returns {Float64Array[]}
11
+ */
12
+ export function signals(table: EntryTable, query: string, lexical: {
13
+ domain: string;
14
+ name: string;
15
+ score?: number;
16
+ }[], route: number[] | null): Float64Array[];
17
+ /**
18
+ * Ranks the entries by a searcher's weights: the weighted sum of each entry's
19
+ * standardized signals and per-domain copies; ties go to the earlier id.
20
+ * @param {EntryTable} table
21
+ * @param {Float64Array[]} rows
22
+ * @param {{w: number[], mu: number[], sd: number[]}} weights
23
+ * @returns {number[]} entry positions, best first
24
+ */
25
+ export function rank(table: EntryTable, rows: Float64Array[], weights: {
26
+ w: number[];
27
+ mu: number[];
28
+ sd: number[];
29
+ }): number[];
30
+ /** @typedef {import('./_entries.mjs').EntryTable} EntryTable */
31
+ /** The signal names, in weights-file order (before the per-domain copies). */
32
+ export const SIGNALS: string[];
33
+ /** The signals that also get one copy per domain. */
34
+ export const PER_DOMAIN: string[];
35
+ export type EntryTable = import("./_entries.mjs").EntryTable;
@@ -0,0 +1,155 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The plain signals search's learned searchers score with. Every one
5
+ * is a deterministic count over the query's words and each entry's own text:
6
+ * BM25 over the entry's name, its docs text, and its source-built card; how
7
+ * many query words it covers; whether the query holds its name; the lexical
8
+ * ranker's score and rank; and the router's guess of the domain the query
9
+ * wants. A searcher's weights file holds one number per signal (and per
10
+ * signal and domain); its score is their weighted sum.
11
+ * @input a query, the lexical ranking, the gathered candidates, static weights
12
+ * @output ranked entry ids, and the search response built from them
13
+ * @position api/search; the searchers and the root router import it
14
+ */
15
+
16
+ import {DOMAINS, ROUTES, words, fold, queryWords} from './_query-words.mjs';
17
+ import {entryOf} from './_entries.mjs';
18
+
19
+ /** @typedef {import('./_entries.mjs').EntryTable} EntryTable */
20
+
21
+ /** The signal names, in weights-file order (before the per-domain copies). */
22
+ export const SIGNALS = [
23
+ 's_score',
24
+ 's_rr',
25
+ 's_in',
26
+ 's_top20',
27
+ 'd_component',
28
+ 'd_hook',
29
+ 'd_doc',
30
+ 'd_template',
31
+ 'd_theme',
32
+ 'bm_name',
33
+ 'bm_desc',
34
+ 'bm_card',
35
+ 'cover',
36
+ 'cover_all',
37
+ 'head',
38
+ 'r_dom',
39
+ 'r_none',
40
+ 'name_in_q',
41
+ 'name_exact',
42
+ ];
43
+
44
+ /** The signals that also get one copy per domain. */
45
+ export const PER_DOMAIN = [
46
+ 's_score',
47
+ 's_rr',
48
+ 'bm_name',
49
+ 'bm_desc',
50
+ 'bm_card',
51
+ 'cover',
52
+ 'r_dom',
53
+ 'name_in_q',
54
+ ];
55
+
56
+ /**
57
+ * Every entry's signals for one query, as rows of numbers.
58
+ * @param {EntryTable} table
59
+ * @param {string} query
60
+ * @param {{domain: string, name: string, score?: number}[]} lexical the lexical ranking, best first
61
+ * @param {number[] | null} route the router's class probabilities
62
+ * @returns {Float64Array[]}
63
+ */
64
+ export function signals(table, query, lexical, route) {
65
+ const n = table.ids.length;
66
+ const S = SIGNALS.length;
67
+ const rows = table.ids.map(() => new Float64Array(S));
68
+ const seen = new Set();
69
+ let r = 0;
70
+ for (const res of lexical) {
71
+ const k = entryOf(table, res);
72
+ if (k === undefined || seen.has(k)) continue;
73
+ seen.add(k);
74
+ r++;
75
+ const x = rows[k];
76
+ x[0] = (res.score ?? 0) / 100;
77
+ x[1] = 1 / r;
78
+ x[2] = 1;
79
+ x[3] = r <= 20 ? 1 : 0;
80
+ }
81
+ for (let k = 0; k < n; k++) rows[k][4 + table.domain[k]] = 1;
82
+ const qw = [...new Set(queryWords(query))];
83
+ if (qw.length) {
84
+ const hits = qw.map(() => new Uint8Array(n));
85
+ /** @type {const} */ (['name', 'desc', 'card']).forEach((f, j) => {
86
+ const {post, idf, len, avg} = table.fields[f];
87
+ qw.forEach((w, a) => {
88
+ for (const [k, c] of post.get(w) ?? []) {
89
+ rows[k][9 + j] +=
90
+ ((idf.get(w) ?? 0) * c * 2.2) /
91
+ (c + 1.2 * (0.25 + (0.75 * len[k]) / avg));
92
+ hits[a][k] = 1;
93
+ }
94
+ });
95
+ });
96
+ for (let k = 0; k < n; k++) {
97
+ let cov = 0;
98
+ for (let a = 0; a < qw.length; a++) cov += hits[a][k];
99
+ rows[k][12] = cov / qw.length;
100
+ rows[k][13] = cov === qw.length && qw.length > 1 ? 1 : 0;
101
+ rows[k][14] = hits[qw.length - 1][k];
102
+ }
103
+ }
104
+ if (route) {
105
+ for (let k = 0; k < n; k++) {
106
+ rows[k][15] = route[table.domain[k]];
107
+ rows[k][16] = route[ROUTES.length - 1];
108
+ }
109
+ }
110
+ const all = words(query).map(fold);
111
+ const spaced = ` ${all.join(' ')} `;
112
+ const runs = new Set();
113
+ for (let len = 1; len <= 3; len++) {
114
+ for (let a = 0; a + len <= all.length; a++)
115
+ runs.add(all.slice(a, a + len).join(''));
116
+ }
117
+ const whole = all.join('');
118
+ for (let k = 0; k < n; k++) {
119
+ const nw = table.name[k];
120
+ if (!nw.length) continue;
121
+ const j = nw.join('');
122
+ if (spaced.includes(` ${nw.join(' ')} `) || runs.has(j)) {
123
+ rows[k][17] = 1;
124
+ if (j === whole) rows[k][18] = 1;
125
+ }
126
+ }
127
+ return rows;
128
+ }
129
+
130
+ /**
131
+ * Ranks the entries by a searcher's weights: the weighted sum of each entry's
132
+ * standardized signals and per-domain copies; ties go to the earlier id.
133
+ * @param {EntryTable} table
134
+ * @param {Float64Array[]} rows
135
+ * @param {{w: number[], mu: number[], sd: number[]}} weights
136
+ * @returns {number[]} entry positions, best first
137
+ */
138
+ export function rank(table, rows, weights) {
139
+ const {w, mu, sd} = weights;
140
+ const S = SIGNALS.length;
141
+ const per = PER_DOMAIN.map(s => SIGNALS.indexOf(s));
142
+ const score = rows.map((x, k) => {
143
+ let s = 0;
144
+ for (let j = 0; j < S; j++) s += ((x[j] - mu[j]) / sd[j]) * w[j];
145
+ const d = table.domain[k];
146
+ per.forEach((j, p) => {
147
+ for (let dd = 0; dd < DOMAINS.length; dd++) {
148
+ const c = S + p * DOMAINS.length + dd;
149
+ s += (((dd === d ? x[j] : 0) - mu[c]) / sd[c]) * w[c];
150
+ }
151
+ });
152
+ return Math.round(s * 1e9) / 1e9;
153
+ });
154
+ return score.map((s, k) => k).sort((a, b) => score[b] - score[a] || a - b);
155
+ }
@@ -0,0 +1,26 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * Build component candidates: core's own tree plus every configured
6
+ * integration's components.
7
+ * @param {string} coreDir
8
+ * @param {string} cwd
9
+ * @returns {Promise<Candidate[]>}
10
+ */
11
+ export function gatherComponents(coreDir: string, cwd: string): Promise<Candidate[]>;
12
+ /**
13
+ * Every component the project can use, Core's and its integrations', with the
14
+ * keywords its own doc declares: the discovery and doc reads search's own
15
+ * candidates use, without the import paths and prose a result carries. `build`
16
+ * reads it to tell a part of a page from a page when its search was narrowed
17
+ * away from components.
18
+ * @param {string} coreDir
19
+ * @param {string} cwd
20
+ * @returns {Promise<{name: string, keywords: string[]}[]>}
21
+ */
22
+ export function componentKeywords(coreDir: string, cwd: string): Promise<{
23
+ name: string;
24
+ keywords: string[];
25
+ }[]>;
26
+ export type Candidate = import("./_lexical.mjs").Candidate;