@shoalrun/cli 0.1.0-alpha.17 → 0.1.0-alpha.19

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 (686) hide show
  1. package/AUTHORING.md +29 -0
  2. package/CHANGELOG.md +54 -0
  3. package/DEPLOYMENT-PROFILES.md +96 -5
  4. package/README.md +106 -25
  5. package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +23 -17
  6. package/agent-docs/SNAPSHOT.json +5 -5
  7. package/agent-docs/api-docs/focused-contracts.md +4 -4
  8. package/agent-docs/api-docs/generate.md +11 -11
  9. package/agent-docs/api-docs/generate.sections/add-useful-examples.md +3 -3
  10. package/agent-docs/api-docs/generate.sections/choose-generated-references-or-mdx.md +4 -4
  11. package/agent-docs/api-docs/generate.sections/describe-filters-that-do-not-use-their-openapi-parameter-name.md +1 -1
  12. package/agent-docs/api-docs/generate.sections/generate-many-pages-selectively.md +2 -2
  13. package/agent-docs/api-docs/generate.sections/link-guides-to-api-references.md +1 -1
  14. package/agent-docs/api-docs/generate.sections/map-extension-values-to-shoalrun-status.md +1 -1
  15. package/agent-docs/api-docs/generate.sections/override-generated-reference-order-in-navigation.md +4 -4
  16. package/agent-docs/api-docs/generate.sections/related-reading.md +1 -1
  17. package/agent-docs/api-docs/generate.sections/use-a-template-for-editorial-context.md +2 -2
  18. package/agent-docs/api-docs/support.md +7 -7
  19. package/agent-docs/author/add-page.md +3 -3
  20. package/agent-docs/author/agent-overview.md +3 -3
  21. package/agent-docs/author/agent-workflow.md +7 -7
  22. package/agent-docs/author/analytics.md +27 -27
  23. package/agent-docs/author/analytics.sections/adapter-exports-and-consent.md +3 -3
  24. package/agent-docs/author/analytics.sections/built-in-events.md +15 -15
  25. package/agent-docs/author/analytics.sections/configure-an-adapter.md +1 -1
  26. package/agent-docs/author/analytics.sections/custom-interactions.md +2 -2
  27. package/agent-docs/author/analytics.sections/event-format.md +2 -2
  28. package/agent-docs/author/analytics.sections/html-markdown-and-agents.md +4 -4
  29. package/agent-docs/author/analytics.sections/inspect-events-locally.md +2 -2
  30. package/agent-docs/author/analytics.sections/map-events-to-your-service.md +3 -3
  31. package/agent-docs/author/analytics.sections/posthog-example.md +3 -3
  32. package/agent-docs/author/analytics.sections/related-reading.md +1 -1
  33. package/agent-docs/author/authoring-agent.md +3 -3
  34. package/agent-docs/author/coding-agent.md +4 -4
  35. package/agent-docs/author/components/api-embeds.md +6 -6
  36. package/agent-docs/author/components/api-embeds.sections/apiexample.md +3 -3
  37. package/agent-docs/author/components/api-embeds.sections/html-markdown-and-agents.md +1 -1
  38. package/agent-docs/author/components/api-embeds.sections/related-reading.md +1 -1
  39. package/agent-docs/author/components/badge.md +2 -2
  40. package/agent-docs/author/components/callout.md +2 -2
  41. package/agent-docs/author/components/cards.md +16 -16
  42. package/agent-docs/author/components/cards.sections/add-a-lucide-icon.md +4 -4
  43. package/agent-docs/author/components/cards.sections/build-a-collection.md +7 -7
  44. package/agent-docs/author/components/cards.sections/curate-a-reading-list.md +9 -9
  45. package/agent-docs/author/components/cards.sections/html-markdown-and-agents.md +3 -3
  46. package/agent-docs/author/components/cards.sections/link-to-one-document.md +3 -3
  47. package/agent-docs/author/components/cards.sections/override-card-text.md +5 -5
  48. package/agent-docs/author/components/cards.sections/related-reading.md +3 -3
  49. package/agent-docs/author/components/code-blocks.md +2 -2
  50. package/agent-docs/author/components/collapsible.md +3 -3
  51. package/agent-docs/author/components/cookbook-chooser.md +5 -5
  52. package/agent-docs/author/components/custom/react.md +8 -8
  53. package/agent-docs/author/components/custom/react.sections/html-markdown-and-agents.md +3 -3
  54. package/agent-docs/author/components/custom/react.sections/interactive-react-example.md +2 -2
  55. package/agent-docs/author/components/custom/react.sections/registration.md +1 -1
  56. package/agent-docs/author/components/custom/react.sections/related-reading.md +1 -1
  57. package/agent-docs/author/components/custom/react.sections/share-the-model-with-the-browser.md +3 -3
  58. package/agent-docs/author/components/custom/react.sections/where-the-content-lives.md +3 -3
  59. package/agent-docs/author/components/custom.md +7 -7
  60. package/agent-docs/author/components/definition-list.md +2 -2
  61. package/agent-docs/author/components/diagrams/d2-gallery.md +2 -2
  62. package/agent-docs/author/components/diagrams/d2-gallery.sections/basic-shapes.md +2 -2
  63. package/agent-docs/author/components/diagrams/d2-gallery.sections/flows-and-structures.md +2 -2
  64. package/agent-docs/author/components/diagrams/d2-gallery.sections/html-markdown-and-agents.md +2 -2
  65. package/agent-docs/author/components/diagrams/d2-gallery.sections/layout-engines.md +2 -2
  66. package/agent-docs/author/components/diagrams/d2-gallery.sections/related-reading.md +2 -2
  67. package/agent-docs/author/components/diagrams/d2-gallery.sections/sequences-and-grids.md +2 -2
  68. package/agent-docs/author/components/diagrams/d2-gallery.sections/styles-and-code.md +2 -2
  69. package/agent-docs/author/components/diagrams/pele-gallery.md +3 -3
  70. package/agent-docs/author/components/diagrams/pele-gallery.sections/charts-and-planning.md +2 -2
  71. package/agent-docs/author/components/diagrams/pele-gallery.sections/flowchart-shapes.md +2 -2
  72. package/agent-docs/author/components/diagrams/pele-gallery.sections/flows-and-behavior.md +2 -2
  73. package/agent-docs/author/components/diagrams/pele-gallery.sections/html-markdown-and-agents.md +3 -3
  74. package/agent-docs/author/components/diagrams/pele-gallery.sections/related-reading.md +2 -2
  75. package/agent-docs/author/components/diagrams/pele-gallery.sections/specialized-diagrams.md +2 -2
  76. package/agent-docs/author/components/diagrams/pele-gallery.sections/systems-and-structures.md +2 -2
  77. package/agent-docs/author/components/diagrams.md +8 -8
  78. package/agent-docs/author/components/doc-link.md +3 -3
  79. package/agent-docs/author/components/fields.md +18 -18
  80. package/agent-docs/author/components/file-tree.md +2 -2
  81. package/agent-docs/author/components/images.md +5 -5
  82. package/agent-docs/author/components/info-hint.md +3 -3
  83. package/agent-docs/author/components/kbd.md +2 -2
  84. package/agent-docs/author/components/math.md +2 -2
  85. package/agent-docs/author/components/only.md +3 -3
  86. package/agent-docs/author/components/progress.md +3 -3
  87. package/agent-docs/author/components/steps.md +2 -2
  88. package/agent-docs/author/components/tables.md +2 -2
  89. package/agent-docs/author/components/tabs.md +5 -5
  90. package/agent-docs/author/components/timeline.md +2 -2
  91. package/agent-docs/author/components/tooltips.md +2 -2
  92. package/agent-docs/author/components/walkthroughs.md +2 -2
  93. package/agent-docs/author/components/walkthroughs.sections/attributes.md +1 -1
  94. package/agent-docs/author/components/walkthroughs.sections/build-up-code.md +1 -1
  95. package/agent-docs/author/components/walkthroughs.sections/choose-a-layout.md +2 -2
  96. package/agent-docs/author/components/walkthroughs.sections/explain-one-file.md +1 -1
  97. package/agent-docs/author/components/walkthroughs.sections/html-markdown-and-agents.md +1 -1
  98. package/agent-docs/author/components/walkthroughs.sections/related-reading.md +1 -1
  99. package/agent-docs/author/components/walkthroughs.sections/syntax.md +1 -1
  100. package/agent-docs/author/components/walkthroughs.sections/take-code-from-a-file.md +1 -1
  101. package/agent-docs/author/components.md +2 -2
  102. package/agent-docs/author/content.md +3 -3
  103. package/agent-docs/author/cookbooks.md +9 -9
  104. package/agent-docs/author/css.md +4 -4
  105. package/agent-docs/author/css.sections/borders-fields-and-navigation-tokens.md +3 -3
  106. package/agent-docs/author/css.sections/core-color-tokens.md +3 -3
  107. package/agent-docs/author/css.sections/html-markdown-and-agents.md +4 -4
  108. package/agent-docs/author/css.sections/page-attributes.md +3 -3
  109. package/agent-docs/author/css.sections/page-transitions.md +3 -3
  110. package/agent-docs/author/css.sections/responsive-behavior.md +3 -3
  111. package/agent-docs/author/css.sections/status-code-and-callout-tokens.md +3 -3
  112. package/agent-docs/author/css.sections/typography-shape-and-width-tokens.md +3 -3
  113. package/agent-docs/author/custom-metadata.md +13 -13
  114. package/agent-docs/author/custom-metadata.sections/add-a-custom-page-field.md +4 -4
  115. package/agent-docs/author/custom-metadata.sections/choose-text-for-each-surface.md +3 -3
  116. package/agent-docs/author/custom-metadata.sections/preview-changes-to-metadata-providers.md +2 -2
  117. package/agent-docs/author/custom-metadata.sections/read-metadata-from-a-project-module.md +3 -3
  118. package/agent-docs/author/custom-metadata.sections/related-reading.md +1 -1
  119. package/agent-docs/author/design-templates.md +3 -3
  120. package/agent-docs/author/design-writing-guides.md +3 -3
  121. package/agent-docs/author/frontmatter-reference.md +45 -6
  122. package/agent-docs/author/frontmatter-reference.sections/categorize-connect-and-present-the-page.md +64 -0
  123. package/agent-docs/author/frontmatter-reference.sections/choose-a-publication-and-visibility.md +2 -2
  124. package/agent-docs/author/frontmatter-reference.sections/control-output-details.md +2 -2
  125. package/agent-docs/author/frontmatter-reference.sections/feature-availability.md +59 -0
  126. package/agent-docs/author/frontmatter-reference.sections/global-defaults-and-enforced-values.md +2 -2
  127. package/agent-docs/author/frontmatter-reference.sections/html-markdown-and-agents.md +3 -3
  128. package/agent-docs/author/frontmatter-reference.sections/identify-and-route-a-page.md +2 -2
  129. package/agent-docs/author/frontmatter-reference.sections/point-agents-to-it.md +2 -2
  130. package/agent-docs/author/frontmatter-reference.sections/product-publication-fields.md +37 -0
  131. package/agent-docs/author/frontmatter-reference.sections/project-defined-fields.md +2 -2
  132. package/agent-docs/author/frontmatter-reference.sections/related-reading.md +2 -2
  133. package/agent-docs/author/frontmatter-reference.sections/use-the-local-files-while-authoring.md +4 -4
  134. package/agent-docs/author/frontmatter-reference.sections/when-the-files-update.md +2 -2
  135. package/agent-docs/author/frontmatter.md +13 -13
  136. package/agent-docs/author/frontmatter.sections/audience-badges.md +3 -3
  137. package/agent-docs/author/frontmatter.sections/give-deprecation-guidance.md +4 -4
  138. package/agent-docs/author/frontmatter.sections/global-defaults-and-enforced-values.md +1 -1
  139. package/agent-docs/author/frontmatter.sections/optional-native-fields.md +4 -4
  140. package/agent-docs/author/frontmatter.sections/publication-fields.md +2 -2
  141. package/agent-docs/author/frontmatter.sections/publishing-policy.md +1 -1
  142. package/agent-docs/author/frontmatter.sections/related-metadata-tasks.md +1 -1
  143. package/agent-docs/author/frontmatter.sections/related-reading.md +1 -1
  144. package/agent-docs/author/frontmatter.sections/required-after-inheritance.md +1 -1
  145. package/agent-docs/author/frontmatter.sections/seo-fields.md +2 -2
  146. package/agent-docs/author/frontmatter.sections/validation-rules.md +3 -3
  147. package/agent-docs/author/markdown-metadata.md +20 -20
  148. package/agent-docs/author/navigation.md +12 -12
  149. package/agent-docs/author/navigation.sections/arrange-authored-pages.md +4 -4
  150. package/agent-docs/author/navigation.sections/fill-an-api-tag-group.md +2 -2
  151. package/agent-docs/author/navigation.sections/hide-group-page-counts.md +4 -4
  152. package/agent-docs/author/navigation.sections/html-markdown-and-agents.md +4 -4
  153. package/agent-docs/author/navigation.sections/local-api-preview.md +2 -2
  154. package/agent-docs/author/navigation.sections/mix-guides-and-api-references.md +3 -3
  155. package/agent-docs/author/navigation.sections/optionally-split-a-large-menu-into-files.md +2 -2
  156. package/agent-docs/author/navigation.sections/reach-navigation-while-reading.md +2 -2
  157. package/agent-docs/author/navigation.sections/related-reading.md +2 -2
  158. package/agent-docs/author/navigation.sections/split-navigation-into-tabs.md +4 -4
  159. package/agent-docs/author/navigation.sections/subject-lifecycle-labels.md +3 -3
  160. package/agent-docs/author/reader-views.md +9 -9
  161. package/agent-docs/author/reader-views.sections/configure-the-choices.md +2 -2
  162. package/agent-docs/author/reader-views.sections/connect-your-own-control.md +1 -1
  163. package/agent-docs/author/reader-views.sections/how-it-works-for-agents.md +3 -3
  164. package/agent-docs/author/reader-views.sections/mark-pages.md +3 -3
  165. package/agent-docs/author/reader-views.sections/mark-sections-and-add-an-entry-choice.md +2 -2
  166. package/agent-docs/author/reader-views.sections/place-filter-controls.md +2 -2
  167. package/agent-docs/author/reader-views.sections/try-the-controls-here.md +2 -2
  168. package/agent-docs/author/recipe-drafts.md +5 -5
  169. package/agent-docs/author/recipe-drafts.sections/1-write-one-reusable-step.md +2 -2
  170. package/agent-docs/author/recipe-drafts.sections/2-list-the-steps-for-one-complete-goal.md +2 -2
  171. package/agent-docs/author/recipe-drafts.sections/3-generate-a-draft-and-review-it.md +1 -1
  172. package/agent-docs/author/recipe-drafts.sections/4-maintain-shoalrun-s-published-recipe-snapshots.md +2 -2
  173. package/agent-docs/author/recipe-drafts.sections/related-reading.md +1 -1
  174. package/agent-docs/author/recipe-drafts.sections/start-an-ingredient-from-an-api-example.md +2 -2
  175. package/agent-docs/author/recipes.md +7 -7
  176. package/agent-docs/author/recipes.sections/how-agents-use-this.md +2 -2
  177. package/agent-docs/author/recipes.sections/one-example-from-shoalrun.md +2 -2
  178. package/agent-docs/author/recipes.sections/related-reading.md +1 -1
  179. package/agent-docs/author/recipes.sections/try-a-complete-workflow.md +1 -1
  180. package/agent-docs/author/recipes.sections/use-recipes-for-task-oriented-how-tos.md +3 -3
  181. package/agent-docs/author/recipes.sections/what-changing-an-ingredient-updates.md +2 -2
  182. package/agent-docs/author/recipes.sections/what-each-file-does.md +1 -1
  183. package/agent-docs/author/recipes.sections/what-happens-and-when.md +2 -2
  184. package/agent-docs/author/related-reading.md +11 -11
  185. package/agent-docs/author/related-reading.sections/automatic-footers.md +3 -3
  186. package/agent-docs/author/related-reading.sections/declare-relationships.md +3 -3
  187. package/agent-docs/author/related-reading.sections/display-related-documents.md +3 -3
  188. package/agent-docs/author/related-reading.sections/html-markdown-and-agents.md +1 -1
  189. package/agent-docs/author/related-reading.sections/inspect-output-and-changes.md +2 -2
  190. package/agent-docs/author/related-reading.sections/reading-paths-in-section-markdown.md +3 -3
  191. package/agent-docs/author/related-reading.sections/related-reading.md +1 -1
  192. package/agent-docs/author/related-reading.sections/where-relationship-explanations-come-from.md +2 -2
  193. package/agent-docs/author/release-notes.md +8 -8
  194. package/agent-docs/author/search.md +43 -39
  195. package/agent-docs/author/search.sections/agent-and-mcp-search-scope.md +12 -8
  196. package/agent-docs/author/search.sections/choose-a-provider.md +8 -8
  197. package/agent-docs/author/search.sections/cli-and-mcp-ranking-details.md +4 -4
  198. package/agent-docs/author/search.sections/enable-included-semantic-search.md +5 -5
  199. package/agent-docs/author/search.sections/hosted-semantic-search-limits.md +3 -3
  200. package/agent-docs/author/search.sections/html-markdown-and-agents.md +3 -3
  201. package/agent-docs/author/search.sections/lexical-search.md +6 -6
  202. package/agent-docs/author/search.sections/local-semantic-preview.md +3 -3
  203. package/agent-docs/author/search.sections/read-a-search-result-with-an-agent.md +2 -2
  204. package/agent-docs/author/search.sections/related-reading.md +2 -2
  205. package/agent-docs/author/search.sections/reuse-the-lexical-index.md +5 -5
  206. package/agent-docs/author/search.sections/turn-search-off.md +3 -3
  207. package/agent-docs/author/search.sections/use-the-search-box.md +2 -2
  208. package/agent-docs/author/search.sections/write-a-custom-provider.md +11 -11
  209. package/agent-docs/author/snippets.md +3 -3
  210. package/agent-docs/author/taxonomy.md +3 -3
  211. package/agent-docs/author/templates.md +16 -14
  212. package/agent-docs/author/templates.sections/built-in-feature-templates.md +2 -2
  213. package/agent-docs/author/templates.sections/built-in-templates.md +2 -2
  214. package/agent-docs/author/templates.sections/choose-formatting-enforcement-for-your-project.md +7 -7
  215. package/agent-docs/author/templates.sections/create-or-edit-a-project-template.md +8 -6
  216. package/agent-docs/author/templates.sections/keep-the-four-shapes-distinct.md +2 -2
  217. package/agent-docs/author/templates.sections/project-added-templates.md +3 -3
  218. package/agent-docs/author/templates.sections/related-reading.md +2 -2
  219. package/agent-docs/author/templates.sections/scaffold-a-page.md +2 -2
  220. package/agent-docs/author/templates.sections/short-cli-and-derived-values.md +3 -3
  221. package/agent-docs/author/templates.sections/what-every-template-gives-you.md +3 -3
  222. package/agent-docs/author/workspace/commands.md +4 -4
  223. package/agent-docs/author/workspace.md +7 -7
  224. package/agent-docs/author/writing-style.md +33 -18
  225. package/agent-docs/author/writing-style.sections/adapt-this-example.md +2 -2
  226. package/agent-docs/author/writing-style.sections/choose-components-by-reader-need.md +3 -3
  227. package/agent-docs/author/writing-style.sections/evidence-and-uncertainty.md +4 -4
  228. package/agent-docs/author/writing-style.sections/example-audience-and-scope.md +2 -2
  229. package/agent-docs/author/writing-style.sections/feature-availability.md +20 -7
  230. package/agent-docs/author/writing-style.sections/ingredients-recipes-and-cookbooks.md +5 -5
  231. package/agent-docs/author/writing-style.sections/page-purpose-and-structure.md +4 -4
  232. package/agent-docs/author/writing-style.sections/procedures-and-examples.md +4 -4
  233. package/agent-docs/author/writing-style.sections/related-reading.md +2 -2
  234. package/agent-docs/author/writing-style.sections/review-a-draft.md +3 -3
  235. package/agent-docs/author/writing-style.sections/reviewed-writing-examples.md +2 -2
  236. package/agent-docs/author/writing-style.sections/voice-and-explanations.md +4 -2
  237. package/agent-docs/changelog/2026-10-14-agent-readiness.md +2 -2
  238. package/agent-docs/changelog/2026-10-15-evaluation-builds.md +9 -9
  239. package/agent-docs/changelog/2026-10-16-navigation-layouts.md +4 -4
  240. package/agent-docs/changelog/2026-10-17-mcp-hosting.md +2 -2
  241. package/agent-docs/changelog/2026-10-18-search-and-tooltips.md +3 -3
  242. package/agent-docs/changelog/2026-10-19-visual-navigation.md +3 -3
  243. package/agent-docs/changelog/2026-10-25.md +2 -2
  244. package/agent-docs/changelog/2026-10-26.md +4 -4
  245. package/agent-docs/changelog/2026-10-27.md +1 -1
  246. package/agent-docs/changelog/2026-10-28.md +3 -3
  247. package/agent-docs/changelog/2026-10-30.md +1 -1
  248. package/agent-docs/changelog/2026-11-03.md +5 -5
  249. package/agent-docs/changelog/2026-11-04-runtime-packaging.md +46 -0
  250. package/agent-docs/changelog/authoring-preview.md +3 -3
  251. package/agent-docs/changelog/authoring-search.md +1 -1
  252. package/agent-docs/changelog/authoring-tools.md +2 -2
  253. package/agent-docs/changelog/branding-security.md +66 -0
  254. package/agent-docs/changelog/product-publications.md +60 -0
  255. package/agent-docs/changelog/working-tree-skill.md +1 -1
  256. package/agent-docs/changelog.md +25 -1
  257. package/agent-docs/chat/checks.md +11 -11
  258. package/agent-docs/chat/checks.sections/answer-ahead-of-time.md +1 -1
  259. package/agent-docs/chat/checks.sections/answer-for-one-audience.md +2 -2
  260. package/agent-docs/chat/checks.sections/answer-without-a-model.md +2 -2
  261. package/agent-docs/chat/checks.sections/follow-up-questions.md +2 -2
  262. package/agent-docs/chat/checks.sections/how-an-answer-is-checked.md +3 -3
  263. package/agent-docs/chat/checks.sections/questions-with-several-parts.md +3 -3
  264. package/agent-docs/chat/checks.sections/related-reading.md +1 -1
  265. package/agent-docs/chat/checks.sections/reuse-answers.md +4 -4
  266. package/agent-docs/chat/host.md +28 -10
  267. package/agent-docs/chat/host.sections/cap-the-daily-spend.md +2 -2
  268. package/agent-docs/chat/host.sections/keep-a-record-of-questions.md +3 -3
  269. package/agent-docs/chat/host.sections/related-reading.md +2 -2
  270. package/agent-docs/chat/passage-index.md +17 -17
  271. package/agent-docs/chat/passage-index.sections/build-the-index.md +2 -2
  272. package/agent-docs/chat/passage-index.sections/embed-passages.md +3 -3
  273. package/agent-docs/chat/passage-index.sections/how-the-default-chunker-splits-a-page.md +2 -2
  274. package/agent-docs/chat/passage-index.sections/limits.md +2 -2
  275. package/agent-docs/chat/passage-index.sections/passage-ids-and-links.md +3 -3
  276. package/agent-docs/chat/passage-index.sections/related-reading.md +2 -2
  277. package/agent-docs/chat/passage-index.sections/what-a-passage-contains.md +15 -15
  278. package/agent-docs/chat/prepared-answers.md +4 -4
  279. package/agent-docs/chat/settings.md +4 -4
  280. package/agent-docs/chat/settings.sections/choose-the-scorer.md +1 -1
  281. package/agent-docs/chat/settings.sections/configure-chat.md +2 -2
  282. package/agent-docs/chat/settings.sections/configure-retrieval.md +1 -1
  283. package/agent-docs/chat/settings.sections/related-reading.md +1 -1
  284. package/agent-docs/chat/settings.sections/send-extra-request-fields.md +2 -2
  285. package/agent-docs/chat/settings.sections/use-more-than-one-model.md +2 -2
  286. package/agent-docs/chat/settings.sections/when-the-scorer-is-down.md +1 -1
  287. package/agent-docs/chat/setup.md +2 -2
  288. package/agent-docs/chat.md +3 -3
  289. package/agent-docs/cli.md +73 -59
  290. package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +11 -7
  291. package/agent-docs/cli.sections/author-pages.md +16 -12
  292. package/agent-docs/cli.sections/build-and-serve.md +30 -18
  293. package/agent-docs/cli.sections/inspect-config-and-operations.md +13 -9
  294. package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +7 -3
  295. package/agent-docs/cli.sections/related-reading.md +6 -2
  296. package/agent-docs/cli.sections/search-and-chat.md +24 -18
  297. package/agent-docs/cli.sections/start-a-project.md +7 -3
  298. package/agent-docs/cli.sections/working-tree-authoring-tools.md +7 -3
  299. package/agent-docs/concepts.md +2 -2
  300. package/agent-docs/config/apis.md +2 -2
  301. package/agent-docs/config/content.md +3 -3
  302. package/agent-docs/config/content.sections/authoring.md +3 -3
  303. package/agent-docs/config/content.sections/badges.md +1 -1
  304. package/agent-docs/config/content.sections/callouts.md +1 -1
  305. package/agent-docs/config/content.sections/cookbooks.md +1 -1
  306. package/agent-docs/config/content.sections/frontmatter.md +1 -1
  307. package/agent-docs/config/content.sections/readerfilters.md +1 -1
  308. package/agent-docs/config/content.sections/related-reading.md +1 -1
  309. package/agent-docs/config/content.sections/relationships.md +1 -1
  310. package/agent-docs/config/content.sections/snippets.md +1 -1
  311. package/agent-docs/config/content.sections/templates.md +1 -1
  312. package/agent-docs/config/content.sections/variables.md +1 -1
  313. package/agent-docs/config/examples.md +4 -4
  314. package/agent-docs/config/examples.sections/feature-showcase.md +4 -4
  315. package/agent-docs/config/examples.sections/minimal-site.md +2 -2
  316. package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
  317. package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
  318. package/agent-docs/config/examples.sections/related-reading.md +2 -2
  319. package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
  320. package/agent-docs/config/integrations.md +4 -4
  321. package/agent-docs/config/outputs.md +22 -16
  322. package/agent-docs/config/outputs.sections/exports.md +19 -13
  323. package/agent-docs/config/outputs.sections/metadata.md +2 -2
  324. package/agent-docs/config/outputs.sections/related-reading.md +1 -1
  325. package/agent-docs/config/publishing.md +29 -19
  326. package/agent-docs/config/publishing.sections/navigation.md +2 -2
  327. package/agent-docs/config/publishing.sections/redirects.md +8 -8
  328. package/agent-docs/config/publishing.sections/related-reading.md +2 -2
  329. package/agent-docs/config/site.md +42 -18
  330. package/agent-docs/config/site.sections/related-reading.md +1 -1
  331. package/agent-docs/config/site.sections/theme.md +1 -1
  332. package/agent-docs/config.md +2 -2
  333. package/agent-docs/configuration.md +19 -19
  334. package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
  335. package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +5 -5
  336. package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
  337. package/agent-docs/configuration.sections/inspect-and-validate-changes.md +5 -5
  338. package/agent-docs/configuration.sections/related-reading.md +1 -1
  339. package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +5 -5
  340. package/agent-docs/configuration.sections/share-defaults-through-extends.md +3 -3
  341. package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
  342. package/agent-docs/configuration.sections/understand-the-three-stages.md +3 -3
  343. package/agent-docs/configuration.sections/understand-where-paths-point.md +2 -2
  344. package/agent-docs/connect/mcp.md +24 -15
  345. package/agent-docs/content-delivery/agents.md +6 -6
  346. package/agent-docs/content-delivery/api.md +29 -16
  347. package/agent-docs/content-delivery/client.md +14 -8
  348. package/agent-docs/content-delivery/http-api/operations/get-content-representation-fa1d2e3f.md +10 -2
  349. package/agent-docs/content-delivery/http-api/operations/get-content-representation-head-4052375c.md +10 -2
  350. package/agent-docs/content-delivery/http-api/operations/get-content-resource-849f1c49.md +537 -3
  351. package/agent-docs/content-delivery/http-api/operations/get-content-resource-head-0a352acd.md +10 -2
  352. package/agent-docs/content-delivery/http-api/operations/list-content-resources-8e977ec7.md +545 -3
  353. package/agent-docs/content-delivery/http-api/operations/list-content-resources-head-b67cbad9.md +10 -2
  354. package/agent-docs/content-delivery/http-api.md +21 -7
  355. package/agent-docs/content-delivery/manifest.md +30 -8
  356. package/agent-docs/content-delivery/publish.md +5 -5
  357. package/agent-docs/content-delivery/render.md +6 -6
  358. package/agent-docs/content-delivery/rest.md +16 -8
  359. package/agent-docs/content-delivery/sections.md +11 -11
  360. package/agent-docs/content-delivery/select.md +6 -6
  361. package/agent-docs/content-delivery.md +4 -4
  362. package/agent-docs/contribute/agent-skills.md +3 -3
  363. package/agent-docs/cookbooks/authoring.md +3 -3
  364. package/agent-docs/cookbooks/site-workflows.md +2 -2
  365. package/agent-docs/cookbooks/welcome-email.md +3 -3
  366. package/agent-docs/documents.json +2500 -1927
  367. package/agent-docs/example-api/cedar.md +4 -4
  368. package/agent-docs/features.md +49 -0
  369. package/agent-docs/glossary.md +22 -22
  370. package/agent-docs/index.md +5 -5
  371. package/agent-docs/ingredients/audit-site.md +2 -2
  372. package/agent-docs/ingredients/build-site.md +2 -2
  373. package/agent-docs/ingredients/complete-page.md +2 -2
  374. package/agent-docs/ingredients/refresh-agent-bundle.md +2 -2
  375. package/agent-docs/non-goals.md +4 -4
  376. package/agent-docs/provenance.json +10 -4
  377. package/agent-docs/publish/agent-discovery.md +8 -2
  378. package/agent-docs/publish/agent-friendliness.md +21 -21
  379. package/agent-docs/publish/agent-friendliness.sections/discover-a-page-with-a-small-context-budget.md +5 -5
  380. package/agent-docs/publish/agent-friendliness.sections/distinguish-examples-from-a-real-service.md +5 -5
  381. package/agent-docs/publish/agent-friendliness.sections/evidence-has-a-scope.md +5 -5
  382. package/agent-docs/publish/agent-friendliness.sections/keep-shared-instructions-complete.md +5 -5
  383. package/agent-docs/publish/agent-friendliness.sections/related-reading.md +3 -3
  384. package/agent-docs/publish/agent-friendliness.sections/secret-handshake.md +3 -3
  385. package/agent-docs/publish/agent-friendliness.sections/try-the-page-controls.md +3 -3
  386. package/agent-docs/publish/agent-friendliness.sections/use-the-transport-your-client-supports.md +4 -4
  387. package/agent-docs/publish/agent-friendliness.sections/verify-the-page-and-detect-changes.md +9 -9
  388. package/agent-docs/publish/agent-friendliness.sections/what-an-agent-reads.md +5 -5
  389. package/agent-docs/publish/agent-friendliness.sections/what-happens-to-an-unsupported-component.md +4 -4
  390. package/agent-docs/publish/api-references.md +5 -5
  391. package/agent-docs/publish/api-references.sections/author-the-reference-page.md +2 -2
  392. package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -3
  393. package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +2 -2
  394. package/agent-docs/publish/api-references.sections/next-steps.md +2 -2
  395. package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +2 -2
  396. package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +2 -2
  397. package/agent-docs/publish/api-references.sections/register-the-operation.md +2 -2
  398. package/agent-docs/publish/api-references.sections/related-reading.md +2 -2
  399. package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -3
  400. package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -3
  401. package/agent-docs/publish/audit.md +8 -8
  402. package/agent-docs/publish/audit.sections/add-project-tests.md +2 -2
  403. package/agent-docs/publish/audit.sections/check-agent-evaluation-reports.md +2 -2
  404. package/agent-docs/publish/audit.sections/check-before-pushing.md +3 -3
  405. package/agent-docs/publish/audit.sections/connect-a-documentation-test-suite.md +2 -2
  406. package/agent-docs/publish/audit.sections/read-the-report.md +3 -3
  407. package/agent-docs/publish/audit.sections/related-reading.md +1 -1
  408. package/agent-docs/publish/content-export.md +37 -15
  409. package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +4 -4
  410. package/agent-docs/publish/content-export.sections/check-the-result.md +2 -2
  411. package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +3 -3
  412. package/agent-docs/publish/content-export.sections/prerequisites.md +4 -4
  413. package/agent-docs/publish/content-export.sections/related-reading.md +2 -2
  414. package/agent-docs/publish/content-export.sections/review-exported-api-material.md +3 -3
  415. package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +2 -2
  416. package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +4 -4
  417. package/agent-docs/publish/content-negotiation.md +10 -10
  418. package/agent-docs/publish/content-negotiation.sections/hosting-contract.md +2 -2
  419. package/agent-docs/publish/content-negotiation.sections/missing-pages.md +3 -3
  420. package/agent-docs/publish/content-negotiation.sections/related-reading.md +1 -1
  421. package/agent-docs/publish/content-negotiation.sections/validators-and-manifest-links.md +2 -2
  422. package/agent-docs/publish/content-negotiation.sections/verify-the-deployed-url.md +2 -2
  423. package/agent-docs/publish/content-negotiation.sections/what-if-the-host-cannot-negotiate.md +3 -3
  424. package/agent-docs/publish/content-negotiation.sections/what-shoalrun-builds-and-what-the-host-does.md +2 -2
  425. package/agent-docs/publish/content-negotiation.sections/why-this-matters.md +2 -2
  426. package/agent-docs/publish/deployment-check.md +6 -6
  427. package/agent-docs/publish/deployment-profiles.md +60 -26
  428. package/agent-docs/publish/deployment-profiles.sections/before-you-begin.md +5 -5
  429. package/agent-docs/publish/deployment-profiles.sections/build-and-inspect-the-edition.md +9 -9
  430. package/agent-docs/publish/deployment-profiles.sections/check-the-result.md +7 -7
  431. package/agent-docs/publish/deployment-profiles.sections/choose-navigation-labels.md +6 -6
  432. package/agent-docs/publish/deployment-profiles.sections/current-limits.md +7 -7
  433. package/agent-docs/publish/deployment-profiles.sections/define-the-shared-sku-manifest.md +6 -6
  434. package/agent-docs/publish/deployment-profiles.sections/html-markdown-and-agents.md +7 -7
  435. package/agent-docs/publish/deployment-profiles.sections/mark-pages-and-shared-sections.md +13 -13
  436. package/agent-docs/publish/deployment-profiles.sections/preview-and-edit-a-customer-edition.md +55 -0
  437. package/agent-docs/publish/deployment-profiles.sections/related-reading.md +6 -6
  438. package/agent-docs/publish/deployment-profiles.sections/select-each-product-release.md +55 -0
  439. package/agent-docs/publish/deployment-profiles.sections/supply-the-profile-from-the-deployment.md +6 -6
  440. package/agent-docs/publish/evals.md +16 -16
  441. package/agent-docs/publish/evals.sections/add-the-audit-hook.md +5 -5
  442. package/agent-docs/publish/evals.sections/check-the-report.md +4 -4
  443. package/agent-docs/publish/evals.sections/define-a-task-file.md +5 -5
  444. package/agent-docs/publish/evals.sections/diagnose-a-different-build.md +5 -5
  445. package/agent-docs/publish/evals.sections/prepare-a-report-for-the-built-site.md +5 -5
  446. package/agent-docs/publish/evals.sections/related-reading.md +3 -3
  447. package/agent-docs/publish/evals.sections/run-and-review-the-tasks.md +4 -4
  448. package/agent-docs/publish/evals.sections/shoalrun-s-own-example.md +6 -6
  449. package/agent-docs/publish/host-adapters.md +6 -6
  450. package/agent-docs/publish/manni.md +16 -16
  451. package/agent-docs/publish/manni.sections/check-the-result.md +3 -3
  452. package/agent-docs/publish/manni.sections/how-this-site-uses-manni.md +6 -6
  453. package/agent-docs/publish/manni.sections/optional-custom-policies.md +4 -4
  454. package/agent-docs/publish/manni.sections/prerequisites.md +2 -2
  455. package/agent-docs/publish/mcp-analytics.md +12 -12
  456. package/agent-docs/publish/mcp-analytics.sections/adapter-exports.md +4 -4
  457. package/agent-docs/publish/mcp-analytics.sections/enable-analytics.md +4 -4
  458. package/agent-docs/publish/mcp-analytics.sections/event-fields-and-service-mappings.md +4 -4
  459. package/agent-docs/publish/mcp-analytics.sections/optionally-collect-intent-and-group-calls.md +4 -4
  460. package/agent-docs/publish/mcp-analytics.sections/optionally-identify-the-client-and-model.md +5 -5
  461. package/agent-docs/publish/mcp-analytics.sections/related-reading.md +3 -3
  462. package/agent-docs/publish/mcp-analytics.sections/safeguards-and-limits.md +5 -5
  463. package/agent-docs/publish/mcp.md +56 -29
  464. package/agent-docs/publish/mcp.sections/check-budgets-and-errors.md +8 -8
  465. package/agent-docs/publish/mcp.sections/choose-the-documentation-source.md +4 -4
  466. package/agent-docs/publish/mcp.sections/configure-the-client.md +4 -4
  467. package/agent-docs/publish/mcp.sections/discover-product-releases-before-searching.md +52 -0
  468. package/agent-docs/publish/mcp.sections/generate-a-vercel-endpoint.md +6 -6
  469. package/agent-docs/publish/mcp.sections/html-markdown-and-agents.md +38 -0
  470. package/agent-docs/publish/mcp.sections/related-reading.md +3 -3
  471. package/agent-docs/publish/mcp.sections/search-then-read.md +13 -12
  472. package/agent-docs/publish/mcp.sections/serve-a-public-endpoint-on-node.md +12 -8
  473. package/agent-docs/publish/mcp.sections/verify-the-connection.md +4 -4
  474. package/agent-docs/publish/mcp.sections/why-offer-mcp-for-public-docs.md +4 -4
  475. package/agent-docs/publish/openapi-extension-mappings.md +12 -12
  476. package/agent-docs/publish/output.md +20 -20
  477. package/agent-docs/publish/output.sections/api-contracts.md +1 -1
  478. package/agent-docs/publish/output.sections/code-highlighting.md +1 -1
  479. package/agent-docs/publish/output.sections/current-limits.md +1 -1
  480. package/agent-docs/publish/output.sections/incremental-sync.md +4 -4
  481. package/agent-docs/publish/output.sections/manifest-records-and-sections.md +3 -3
  482. package/agent-docs/publish/output.sections/navigation-section-indexes.md +1 -1
  483. package/agent-docs/publish/output.sections/page-formats.md +2 -2
  484. package/agent-docs/publish/output.sections/published-output-contract.md +5 -5
  485. package/agent-docs/publish/output.sections/reader-appearance-and-controls.md +1 -1
  486. package/agent-docs/publish/output.sections/related-reading.md +1 -1
  487. package/agent-docs/publish/output.sections/response-identity.md +1 -1
  488. package/agent-docs/publish/output.sections/site-files.md +6 -6
  489. package/agent-docs/publish/output.sections/validate-an-existing-build-locally.md +3 -3
  490. package/agent-docs/publish/output.sections/where-files-go.md +3 -3
  491. package/agent-docs/publish/publications.md +108 -19
  492. package/agent-docs/publish/publications.sections/add-a-language.md +60 -0
  493. package/agent-docs/publish/publications.sections/change-just-one-part-of-a-shared-page.md +63 -0
  494. package/agent-docs/publish/publications.sections/give-each-api-version-its-own-contract.md +34 -0
  495. package/agent-docs/publish/publications.sections/keep-an-unchanged-page-in-one-file.md +53 -0
  496. package/agent-docs/publish/publications.sections/publish-versions-without-a-product-catalog.md +49 -0
  497. package/agent-docs/publish/publications.sections/related-reading.md +42 -0
  498. package/agent-docs/publish/publications.sections/version-products-independently.md +115 -0
  499. package/agent-docs/publish/publications.sections/what-agents-receive.md +38 -0
  500. package/agent-docs/publish/revisions.md +4 -4
  501. package/agent-docs/publish/seo.md +10 -10
  502. package/agent-docs/publish/seo.sections/related-reading.md +2 -2
  503. package/agent-docs/publish/seo.sections/set-the-public-address.md +3 -3
  504. package/agent-docs/publish/seo.sections/what-agents-receive.md +3 -3
  505. package/agent-docs/publish/seo.sections/what-the-build-adds.md +2 -2
  506. package/agent-docs/publish/seo.sections/write-the-page-title-and-summary.md +2 -2
  507. package/agent-docs/publish/single-source-sites.md +5 -5
  508. package/agent-docs/publish/troubleshooting.md +10 -10
  509. package/agent-docs/publish/vercel.md +5 -5
  510. package/agent-docs/publish/vercel.sections/check-the-deployment.md +1 -1
  511. package/agent-docs/publish/vercel.sections/include-an-mcp-endpoint.md +2 -2
  512. package/agent-docs/publish/vercel.sections/prepare-your-project.md +2 -2
  513. package/agent-docs/publish/vercel.sections/related-reading.md +1 -1
  514. package/agent-docs/publish.md +2 -2
  515. package/agent-docs/recipes/add-page.md +5 -5
  516. package/agent-docs/recipes/add-page.sections/audit-the-shoalrun-docs-project.md +2 -2
  517. package/agent-docs/recipes/add-page.sections/before-you-start.md +1 -1
  518. package/agent-docs/recipes/add-page.sections/build-the-shoalrun-docs-site.md +2 -2
  519. package/agent-docs/recipes/add-page.sections/check-agent-search-and-page-lookup.md +1 -1
  520. package/agent-docs/recipes/add-page.sections/check-the-built-page-artifacts.md +1 -1
  521. package/agent-docs/recipes/add-page.sections/check-the-outcome.md +1 -1
  522. package/agent-docs/recipes/add-page.sections/complete-the-guide-and-add-navigation.md +2 -2
  523. package/agent-docs/recipes/add-page.sections/install-the-site-dependencies.md +1 -1
  524. package/agent-docs/recipes/add-page.sections/regenerate-the-agent-documentation-bundle.md +2 -2
  525. package/agent-docs/recipes/add-page.sections/related-reading.md +1 -1
  526. package/agent-docs/recipes/add-page.sections/scaffold-a-new-guide.md +1 -1
  527. package/agent-docs/recipes/audit-docs.md +4 -4
  528. package/agent-docs/recipes/build-docs.md +2 -2
  529. package/agent-docs/recipes/preview-hybrid-search.md +5 -5
  530. package/agent-docs/recipes/preview-page.md +2 -2
  531. package/agent-docs/recipes/queue-email.md +2 -2
  532. package/agent-docs/recipes/refresh-agent-docs.md +4 -4
  533. package/agent-docs/recipes/send-welcome-email.md +13 -13
  534. package/agent-docs/reference/agent-skills.md +7 -7
  535. package/agent-docs/search-and-chat.md +4 -4
  536. package/agent-docs/search-index.json +1 -1
  537. package/agent-docs/start.md +5 -5
  538. package/agent-docs/start.sections/add-the-page-to-navigation.md +3 -3
  539. package/agent-docs/start.sections/build-and-check-both-outputs.md +3 -3
  540. package/agent-docs/start.sections/build-this-site.md +2 -2
  541. package/agent-docs/start.sections/check-writing-style.md +2 -2
  542. package/agent-docs/start.sections/create-a-page.md +2 -2
  543. package/agent-docs/start.sections/make-it-yours.md +2 -2
  544. package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
  545. package/agent-docs/start.sections/prerequisites.md +2 -2
  546. package/agent-docs/start.sections/related-reading.md +2 -2
  547. package/agent-docs/start.sections/start-your-own-project.md +3 -3
  548. package/agent-docs/status.md +14 -4
  549. package/agent-docs/styling/color-modes.md +2 -2
  550. package/agent-docs/styling/footer.md +2 -2
  551. package/agent-docs/styling/header.md +2 -2
  552. package/agent-docs/styling/layouts.md +3 -3
  553. package/agent-docs/styling/layouts.sections/build-a-landing-page.md +1 -1
  554. package/agent-docs/styling/layouts.sections/build-a-splash-page.md +1 -1
  555. package/agent-docs/styling/layouts.sections/control-navigation-tabs.md +2 -2
  556. package/agent-docs/styling/layouts.sections/customize-the-hero.md +1 -1
  557. package/agent-docs/styling/layouts.sections/hero.md +1 -1
  558. package/agent-docs/styling/layouts.sections/hide-the-table-of-contents-or-give-content-more-room.md +1 -1
  559. package/agent-docs/styling/layouts.sections/html-markdown-and-agents.md +2 -2
  560. package/agent-docs/styling/layouts.sections/related-reading.md +1 -1
  561. package/agent-docs/styling/palettes.md +3 -3
  562. package/agent-docs/styling/share-images.md +3 -3
  563. package/agent-docs/styling/themes.md +2 -2
  564. package/agent-docs/styling/try.md +2 -2
  565. package/agent-docs/what-is-shoalrun.md +7 -3
  566. package/assets/ask-widget.js +21 -7
  567. package/assets/navigation.js +5 -0
  568. package/dist/api-materialize.d.ts +2 -1
  569. package/dist/api-materialize.js +21 -9
  570. package/dist/api-publication-plan.d.ts +2 -0
  571. package/dist/api-publication-plan.js +23 -7
  572. package/dist/api-publication-review.js +4 -3
  573. package/dist/api-selection.d.ts +5 -2
  574. package/dist/api-selection.js +18 -11
  575. package/dist/artifact-bundle.js +9 -6
  576. package/dist/ask-function.js +5 -2
  577. package/dist/ask-runtime.d.ts +1 -0
  578. package/dist/ask-runtime.js +7 -2
  579. package/dist/authored-change.js +2 -1
  580. package/dist/authoring-project.js +1 -1
  581. package/dist/cards.js +2 -1
  582. package/dist/chat-config.d.ts +2 -0
  583. package/dist/chat-config.js +10 -2
  584. package/dist/cli-discovery.d.ts +2 -2
  585. package/dist/cli-discovery.js +9 -4
  586. package/dist/cli.js +50 -25
  587. package/dist/compiler-config.d.ts +17 -0
  588. package/dist/compiler-config.js +43 -2
  589. package/dist/compiler.d.ts +21 -0
  590. package/dist/compiler.js +16 -12
  591. package/dist/component-transform.d.ts +2 -4
  592. package/dist/component-transform.js +20 -7
  593. package/dist/config.d.ts +1 -0
  594. package/dist/config.js +2 -1
  595. package/dist/content-delivery-contract.d.ts +2 -1
  596. package/dist/content-delivery-validation.d.ts +2 -2
  597. package/dist/content-delivery-validation.js +6 -4
  598. package/dist/content-export-command.d.ts +1 -1
  599. package/dist/content-export-command.js +4 -4
  600. package/dist/content-export-comparison.js +6 -5
  601. package/dist/content-export-config.js +3 -1
  602. package/dist/content-export.js +9 -8
  603. package/dist/content-rest-client.js +4 -2
  604. package/dist/content-rest-contract.d.ts +2 -2
  605. package/dist/content-rest-server.js +11 -6
  606. package/dist/content-source.d.ts +13 -0
  607. package/dist/content-source.js +5 -2
  608. package/dist/content-workspace.d.ts +12 -0
  609. package/dist/content-workspace.js +2 -1
  610. package/dist/content.js +3 -2
  611. package/dist/cookbook-chooser.js +2 -1
  612. package/dist/deployment-profile.d.ts +2 -1
  613. package/dist/deployment-profile.js +38 -8
  614. package/dist/dev.d.ts +3 -1
  615. package/dist/dev.js +99 -12
  616. package/dist/docs-author.js +2 -1
  617. package/dist/docs-command.js +2 -2
  618. package/dist/docs-eval.d.ts +1 -0
  619. package/dist/docs-eval.js +2 -2
  620. package/dist/docs-mcp.d.ts +1 -0
  621. package/dist/docs-mcp.js +10 -5
  622. package/dist/docs-tool.d.ts +4 -10
  623. package/dist/document-sync.d.ts +1 -0
  624. package/dist/document-sync.js +2 -2
  625. package/dist/documentation-core.d.ts +29 -10
  626. package/dist/documentation-core.js +38 -4
  627. package/dist/freshness.js +2 -2
  628. package/dist/frontmatter.js +13 -7
  629. package/dist/function-runtime.d.ts +1 -0
  630. package/dist/index-build.d.ts +1 -0
  631. package/dist/index-build.js +2 -2
  632. package/dist/ingredient-draft.js +20 -10
  633. package/dist/mcp-analytics.d.ts +1 -0
  634. package/dist/mcp-artifacts.js +13 -4
  635. package/dist/mcp-config.d.ts +1 -0
  636. package/dist/mcp-config.js +3 -1
  637. package/dist/mcp-http.js +1 -1
  638. package/dist/page-materialization.d.ts +3 -4
  639. package/dist/page-materialization.js +15 -8
  640. package/dist/page-renderer.d.ts +6 -0
  641. package/dist/page-renderer.js +16 -5
  642. package/dist/project-navigation.js +2 -1
  643. package/dist/publication-identity.d.ts +12 -0
  644. package/dist/publication-identity.js +17 -0
  645. package/dist/publication-manifest.d.ts +24 -1
  646. package/dist/publication-manifest.js +14 -6
  647. package/dist/publication-plan.js +21 -9
  648. package/dist/publication-render.js +24 -8
  649. package/dist/recipe-draft.js +9 -6
  650. package/dist/scaffold.d.ts +7 -4
  651. package/dist/scaffold.js +16 -16
  652. package/dist/search-query.d.ts +4 -10
  653. package/dist/search-query.js +10 -9
  654. package/dist/server.d.ts +8 -0
  655. package/dist/server.js +14 -3
  656. package/dist/subject-deprecation.js +2 -1
  657. package/dist/turnstile-policy.d.ts +2 -0
  658. package/dist/turnstile-policy.js +23 -0
  659. package/dist/turnstile.d.ts +7 -0
  660. package/dist/turnstile.js +29 -2
  661. package/dist/vercel-function.js +2 -2
  662. package/example-configs/products/README.md +37 -0
  663. package/example-configs/products/content/operations.mdx +50 -0
  664. package/example-configs/products/content/payments-v2.mdx +30 -0
  665. package/example-configs/products/content/payments-v3.mdx +38 -0
  666. package/example-configs/products/content/priority-settlement.mdx +23 -0
  667. package/example-configs/products/content/reporting-v1.mdx +36 -0
  668. package/example-configs/products/content/scheduled-exports.mdx +23 -0
  669. package/example-configs/products/docs.config.yaml +56 -0
  670. package/example-configs/products/profiles/all-releases.yaml +9 -0
  671. package/example-configs/products/profiles/customer-a.yaml +13 -0
  672. package/example-configs/products/profiles/customer-b.yaml +13 -0
  673. package/example-configs/products/skus.yaml +11 -0
  674. package/examples/content-delivery/preview.mjs +1 -1
  675. package/package.json +1 -1
  676. package/schemas/content-export.schema.json +41 -3
  677. package/schemas/content-rest.openapi.json +184 -37
  678. package/skills/shoalrun-author/SKILL.md +6 -2
  679. package/skills/shoalrun-author/references/customer-editions.md +34 -4
  680. package/skills/shoalrun-author/references/publications.md +60 -0
  681. package/skills/shoalrun-brand/SKILL.md +52 -0
  682. package/skills/shoalrun-recipes/SKILL.md +2 -0
  683. package/skills/shoalrun-setup/SKILL.md +3 -1
  684. package/styles/header.css +3 -0
  685. package/styles/site.css +3 -0
  686. package/agent-docs/publish/content-export.sections/export-selected-pages.md +0 -116
@@ -114,14 +114,28 @@
114
114
  if (current?.item && (indent > current.indent || code && current.item.textContent.replace(/\[\d+\]/g, '').trim().endsWith(':'))) current.item.append(node);
115
115
  else { lists.length = 0; parent.append(node); }
116
116
  };
117
- for (const part of text.split(/((?:^[ \t]*)?```[\s\S]*?```)/m)) {
118
- if (!part.trim()) continue;
119
- if (part.trimStart().startsWith('```')) {
120
- const indent = indentOf(part);
121
- let code = part.replace(/^[ \t]*```[^\n]*\n?/, '').replace(/\n?[ \t]*```$/, '');
122
- if (indent) code = code.replace(new RegExp('^ {0,' + indent + '}', 'gm'), '');
117
+ // A shorter fence inside an example is literal code, not its closing fence.
118
+ const parts = [];
119
+ const openings = /^([ \t]*)(`{3,}|~{3,})[^\n]*\n/gm;
120
+ let cursor = 0, opening;
121
+ while ((opening = openings.exec(text))) {
122
+ const closing = new RegExp('^[ \\t]*' + opening[2][0] + '{' + opening[2].length + ',}[ \\t]*\\r?$', 'gm');
123
+ closing.lastIndex = openings.lastIndex;
124
+ const end = closing.exec(text);
125
+ parts.push({ text: text.slice(cursor, opening.index) });
126
+ parts.push({ code: text.slice(openings.lastIndex, end ? end.index : text.length).replace(/\r?\n$/, ''), indent: indentOf(opening[1]) });
127
+ cursor = end ? closing.lastIndex : text.length;
128
+ openings.lastIndex = cursor;
129
+ }
130
+ parts.push({ text: text.slice(cursor) });
131
+ for (const blockPart of parts) {
132
+ if (blockPart.code !== undefined) {
133
+ const { indent } = blockPart;
134
+ const code = indent ? blockPart.code.replace(new RegExp('^ {0,' + indent + '}', 'gm'), '') : blockPart.code;
123
135
  appendBlock(el('pre', {}, el('code', { text: code })), indent, true); continue;
124
136
  }
137
+ const part = blockPart.text;
138
+ if (!part.trim()) continue;
125
139
  for (const block of part.split(/\n{2,}/)) {
126
140
  const heading = /^(#{1,6})\s+(.+)$/.exec(block.trim());
127
141
  if (heading && !block.trim().includes('\n')) { const node = el(`h${Math.max(2, heading[1].length)}`); inline(node, heading[2], sources); appendBlock(node, indentOf(block)); continue; }
@@ -238,7 +252,7 @@
238
252
  });
239
253
  const checkVisitor = async () => {
240
254
  const turnstile = await loadTurnstile();
241
- if (widget === undefined) widget = turnstile.render(challengeBox, { sitekey: hosted.siteKey, appearance: 'interaction-only', execution: 'execute', callback: token => waiter?.resolve(token), 'error-callback': () => waiter?.reject(new Error('The check did not pass.')) });
255
+ if (widget === undefined) widget = turnstile.render(challengeBox, { sitekey: hosted.siteKey, ...(hosted.action ? { action: hosted.action } : {}), appearance: 'interaction-only', execution: 'execute', callback: token => waiter?.resolve(token), 'error-callback': () => waiter?.reject(new Error('The check did not pass.')) });
242
256
  else turnstile.reset(widget);
243
257
  return new Promise((resolve, reject) => {
244
258
  const timer = setTimeout(() => reject(new Error('The check timed out.')), 30000);
@@ -1,4 +1,9 @@
1
1
  const navigation = document.querySelector('.side');
2
+ for (const select of document.querySelectorAll('[data-publication-switcher]')) {
3
+ select.addEventListener('change', () => {
4
+ if (select.value) location.assign(select.value);
5
+ });
6
+ }
2
7
  const tree = navigation?.querySelector('.nav-tree');
3
8
  const search = navigation?.querySelector('.nav-search');
4
9
  const filter = navigation?.querySelector('#nav-filter');
@@ -1,4 +1,5 @@
1
- export type MaterializeOptions = {
1
+ import type { Variant } from './content.js';
2
+ export type MaterializeOptions = Partial<Variant> & {
2
3
  all?: boolean;
3
4
  operations?: string[];
4
5
  routes?: string[];
@@ -1,3 +1,5 @@
1
+ import { resolvePublication } from './compiler-config.js';
2
+ import { samePublication } from './publication-identity.js';
1
3
  import { mkdir, readFile, readdir, realpath, writeFile } from 'node:fs/promises';
2
4
  import path from 'node:path';
3
5
  import YAML from 'yaml';
@@ -30,7 +32,7 @@ function pageIdentity(source, file) {
30
32
  const data = YAML.parse(match[1]);
31
33
  if (!data || typeof data !== 'object')
32
34
  throw new Error(`${file}: invalid page frontmatter`);
33
- return { id: data.id, operation: Array.isArray(data.operations) && data.operations.length === 1 ? data.operations[0] : undefined, channel: data.channel, version: data.version, language: data.language, publications: data.publications };
35
+ return { id: data.id, operation: Array.isArray(data.operations) && data.operations.length === 1 ? data.operations[0] : undefined, product: data.product, channel: data.channel, version: data.version, language: data.language, publications: data.publications };
34
36
  }
35
37
  function select(candidates, options) {
36
38
  const ids = options.operations ?? [];
@@ -63,16 +65,14 @@ export async function materializeApiPages(configFile, apiId, options) {
63
65
  const config = loaded.value;
64
66
  const root = path.dirname(path.resolve(configFile));
65
67
  const contentDir = await canonical(path.resolve(root, config.site?.contentDir ?? 'content'));
66
- const directory = await canonical(options.output ? path.resolve(options.output) : path.join(contentDir, 'api', apiId));
68
+ const { candidates, publication } = await apiCandidates(configFile, apiId, options);
69
+ const defaultDirectory = publication.product ? path.join(contentDir, 'api', publication.product, publication.version, apiId) : path.join(contentDir, 'api', apiId);
70
+ const directory = await canonical(options.output ? path.resolve(options.output) : defaultDirectory);
67
71
  const relative = path.relative(contentDir, directory);
68
72
  if (relative.startsWith('..') || path.isAbsolute(relative))
69
73
  throw new Error(`MDX output must stay inside the content directory ${contentDir}`);
70
- const { candidates } = await apiCandidates(configFile, apiId);
71
74
  const selected = select(candidates, options);
72
- const defaults = config.publications?.defaults;
73
- if (!defaults?.channel || !defaults?.version)
74
- throw new Error('API page materialization needs publication defaults');
75
- const language = defaults.language ?? defaultLanguage(config);
75
+ const language = publication.language;
76
76
  const existing = new Map();
77
77
  for (const file of await pageFiles(contentDir)) {
78
78
  const identity = pageIdentity(await readFile(file, 'utf8'), file);
@@ -86,7 +86,19 @@ export async function materializeApiPages(configFile, apiId, options) {
86
86
  const skipped = [];
87
87
  const targets = new Set();
88
88
  for (const item of selected) {
89
- const matches = (existing.get(item.reference) ?? []).filter(page => (page.publications ? page.publications.some(publication => publication.channel === defaults.channel && publication.version === defaults.version) : (page.channel ?? defaults.channel) === defaults.channel && (page.version ?? defaults.version) === defaults.version) && (page.language ?? language) === language);
89
+ const matches = (existing.get(item.reference) ?? []).filter(page => {
90
+ const sourceLanguage = config.frontmatter?.enforced?.language ?? page.language ?? config.frontmatter?.defaults?.language ?? defaultLanguage(config);
91
+ if (page.publications)
92
+ return page.publications.some(member => member.product === publication.product && member.channel === publication.channel && member.version === publication.version) && sourceLanguage === language;
93
+ const product = config.publications.products ? config.frontmatter?.enforced?.product ?? page.product ?? config.frontmatter?.defaults?.product : undefined;
94
+ const coordinate = resolvePublication(config.publications, {
95
+ ...(product ? { product } : {}),
96
+ channel: config.frontmatter?.enforced?.channel ?? page.channel ?? config.frontmatter?.defaults?.channel ?? config.publications?.defaults?.channel,
97
+ version: config.frontmatter?.enforced?.version ?? page.version ?? (product ? undefined : config.frontmatter?.defaults?.version ?? config.publications?.defaults?.version),
98
+ language: sourceLanguage
99
+ }, defaultLanguage(config));
100
+ return samePublication(coordinate, publication);
101
+ });
90
102
  if (matches.length > 1)
91
103
  throw new Error(`Duplicate page ID ${item.reference} in the default publication: ${matches.map(page => page.file).join(', ')}`);
92
104
  const prior = matches[0];
@@ -108,7 +120,7 @@ export async function materializeApiPages(configFile, apiId, options) {
108
120
  if (atFile !== undefined)
109
121
  throw new Error(`${file}: target exists with another page ID; no files written`);
110
122
  const summary = item.method === 'WEBHOOK' ? `Webhook event: ${item.route}` : `${item.method} ${item.route}`;
111
- const header = YAML.stringify({ id: item.reference, title: item.title, summary, type: 'api-reference', slug: item.slug, channel: defaults.channel, version: defaults.version, language, operations: [item.id], access: { policy: 'draft' } });
123
+ const header = YAML.stringify({ id: item.reference, title: item.title, summary, type: 'api-reference', slug: item.slug, ...publication, operations: [item.id], access: { policy: 'draft' } });
112
124
  const body = 'This draft reference is based on its linked OpenAPI operation.\n\n[[TODO: Explain when to use this endpoint, its prerequisites, and any behavior the OpenAPI contract cannot express. Verify every claim before publishing.]]\n';
113
125
  pending.push({ item, file, content: `---\n${header}---\n\n${body}` });
114
126
  }
@@ -10,7 +10,9 @@ type ApiDefinition = {
10
10
  path: string;
11
11
  [key: string]: unknown;
12
12
  };
13
+ product?: string;
13
14
  publications?: Array<{
15
+ product?: string;
14
16
  channel: string;
15
17
  version: string;
16
18
  source: {
@@ -1,3 +1,4 @@
1
+ import { documentKey } from './publication-identity.js';
1
2
  import { matchesFeatures, validateFeatureClassification } from './deployment-profile.js';
2
3
  import { matchesContentFilter } from './content-filter.js';
3
4
  import path from 'node:path';
@@ -10,7 +11,7 @@ import { explain } from './config.js';
10
11
  import { isConfigMapping } from './compiler-config.js';
11
12
  const generatedReferenceBody = 'This reference is generated from the OpenAPI description. It shows the operation contract; follow any related guides below for task steps and context.\n';
12
13
  const generatedWebhookBody = 'This webhook reference is generated from the OpenAPI description. The provider sends this event to the receiver.\n';
13
- const keyFor = (id, variant) => `${id}|${variant.channel}|${variant.version}|${variant.language}`;
14
+ const keyFor = documentKey;
14
15
  function validatedApiDefinitions(value) {
15
16
  if (value === undefined)
16
17
  return {};
@@ -24,7 +25,7 @@ function validatedApiDefinitions(value) {
24
25
  if (source !== undefined && (!isConfigMapping(source) || typeof source.kind !== 'string' || typeof source.path !== 'string'))
25
26
  throw new Error(`apis.${id}.source needs kind and path`);
26
27
  const publications = raw.publications;
27
- if (publications !== undefined && (!Array.isArray(publications) || publications.some(item => !isConfigMapping(item) || typeof item.channel !== 'string' || typeof item.version !== 'string' || !isConfigMapping(item.source) || typeof item.source.kind !== 'string' || typeof item.source.path !== 'string' || (item.discovery !== undefined && (!isConfigMapping(item.discovery) || (item.discovery.endpoint !== undefined && typeof item.discovery.endpoint !== 'string'))))))
28
+ if (publications !== undefined && (!Array.isArray(publications) || publications.some(item => !isConfigMapping(item) || (item.product !== undefined && typeof item.product !== 'string') || typeof item.channel !== 'string' || typeof item.version !== 'string' || !isConfigMapping(item.source) || typeof item.source.kind !== 'string' || typeof item.source.path !== 'string' || (item.discovery !== undefined && (!isConfigMapping(item.discovery) || (item.discovery.endpoint !== undefined && typeof item.discovery.endpoint !== 'string'))))))
28
29
  throw new Error(`apis.${id}.publications needs entries with channel, version, and a local source`);
29
30
  const operations = raw.operations;
30
31
  if (operations !== undefined && (!Array.isArray(operations) || operations.some(item => !isConfigMapping(item) || typeof item.id !== 'string' || typeof item.reference !== 'string' || (item.sourceOperationId !== undefined && typeof item.sourceOperationId !== 'string'))))
@@ -39,6 +40,18 @@ function validatedApiDefinitions(value) {
39
40
  export async function materializeApiReferences({ config, loaded, variants, docs, knownDocumentIds, knownDocumentTypes, authoredOperationIds, routeOwners, basePath, readerFilters, contentFilter, allowRouteCollisions }) {
40
41
  const definitions = validatedApiDefinitions(config.apis);
41
42
  for (const [id, definition] of Object.entries(definitions)) {
43
+ if (config.publications.products && definition.product !== undefined && (typeof definition.product !== 'string' || !config.publications.products || !Object.hasOwn(config.publications.products, definition.product)))
44
+ throw new Error(`API ${id}: unknown product ${definition.product}`);
45
+ const seenPublications = new Set();
46
+ for (const publication of definition.publications ?? []) {
47
+ const catalog = publication.product === undefined ? config.publications.versions : config.publications.products?.[publication.product]?.versions;
48
+ if (!catalog || !Object.hasOwn(catalog, publication.version) || !Object.hasOwn(config.publications.channels, publication.channel))
49
+ throw new Error(`API ${id}: unknown product publication`);
50
+ const key = JSON.stringify([publication.product, publication.channel, publication.version]);
51
+ if (seenPublications.has(key))
52
+ throw new Error(`API ${id}: duplicate publication source`);
53
+ seenPublications.add(key);
54
+ }
42
55
  validateFeatureClassification(definition, loaded.deployment ? { ...loaded.deployment.context, requireClassification: false } : undefined, `API ${id}`);
43
56
  for (const operation of definition.operations ?? [])
44
57
  validateFeatureClassification(operation, loaded.deployment ? { ...loaded.deployment.context, requireClassification: false } : undefined, `Operation ${operation.id}`);
@@ -62,10 +75,13 @@ export async function materializeApiReferences({ config, loaded, variants, docs,
62
75
  }
63
76
  const sourceForVariant = (apiId, definition, variant) => {
64
77
  const defaults = config.publications.defaults;
65
- if (definition.source !== undefined && (!defaults?.channel || !defaults?.version))
78
+ if (definition.source !== undefined && (!defaults?.channel || (!defaults?.version && !((definition.product ?? defaults?.product) && config.publications.products?.[definition.product ?? defaults.product]?.defaultVersion))))
66
79
  throw new Error(`apis.${apiId}.source needs publications.defaults with channel and version to choose its publication`);
67
- const isDefault = variant.channel === defaults?.channel && variant.version === defaults?.version;
68
- const publicationIndex = definition.publications?.findIndex(item => item.channel === variant.channel && item.version === variant.version) ?? -1;
80
+ const product = config.publications.products ? definition.product ?? defaults?.product : undefined;
81
+ const scopedVersion = product && defaults?.product === product && defaults.version && Object.hasOwn(config.publications.products[product].versions, defaults.version) ? defaults.version : undefined;
82
+ const defaultVersion = product ? scopedVersion ?? config.publications.products?.[product]?.defaultVersion : defaults?.version;
83
+ const isDefault = variant.product === product && variant.channel === defaults?.channel && variant.version === defaultVersion;
84
+ const publicationIndex = definition.publications?.findIndex(item => item.product === variant.product && item.channel === variant.channel && item.version === variant.version) ?? -1;
69
85
  const source = publicationIndex >= 0 ? definition.publications?.[publicationIndex].source : (isDefault ? definition.source : undefined);
70
86
  if (!source)
71
87
  return undefined;
@@ -166,7 +182,7 @@ export async function materializeApiReferences({ config, loaded, variants, docs,
166
182
  const classification = requirements !== undefined || shared !== undefined ? { requires: requirements, shared } : definition;
167
183
  validateFeatureClassification(classification, loaded.deployment?.context, `${binding.file}: ${sourceOperationId} (generated reference)`);
168
184
  }
169
- if (!variants.some(item => item.channel === variant.channel && item.version === variant.version && item.language === variant.language))
185
+ if (!variants.some(item => item.product === variant.product && item.channel === variant.channel && item.version === variant.version && item.language === variant.language))
170
186
  continue;
171
187
  operationRequirements.set(keyFor(id, variant), requirements);
172
188
  const featureSelected = matchesFeatures(requirements, loaded.deployment?.context, `${binding.file}: ${sourceOperationId}`) && matchesFeatures(definition.requires, loaded.deployment?.context, `API ${apiId}`);
@@ -183,7 +199,7 @@ export async function materializeApiReferences({ config, loaded, variants, docs,
183
199
  knownDocumentTypes.set(reference, page.type);
184
200
  if (!matchesFeatures(page.requires, loaded.deployment?.context, `${binding.file}: ${reference}`))
185
201
  continue;
186
- if (page.access?.policy !== 'public' || page.channel !== variant.channel || page.version !== variant.version || page.language !== variant.language)
202
+ if (page.access?.policy !== 'public' || page.channel !== variant.channel || page.version !== variant.version || page.language !== variant.language || (config.publications.products && page.product !== variant.product))
187
203
  continue;
188
204
  const key = keyFor(reference, variant);
189
205
  const authored = docs.get(key);
@@ -1,9 +1,10 @@
1
+ import { documentKey, publicationKey } from './publication-identity.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { readFile } from 'node:fs/promises';
3
4
  import path from 'node:path';
4
5
  import { isConfigMapping } from './compiler-config.js';
5
6
  const digest = (value) => createHash('sha256').update(value).digest('hex');
6
- const keyFor = (id, variant) => `${id}|${variant.channel}|${variant.version}|${variant.language}`;
7
+ const keyFor = documentKey;
7
8
  export async function reviewApiPublication(configFile, apiPlan, rendered, apiEmbedUses, focusedContracts, apiSources, sourceForOperation, mode) {
8
9
  const { api, knownOperations, sourceForVariant } = apiPlan;
9
10
  // Pin the source bytes and the API selections exposed by public pages. Authored
@@ -19,7 +20,7 @@ export async function reviewApiPublication(configFile, apiPlan, rendered, apiEmb
19
20
  continue;
20
21
  const bindings = new Map();
21
22
  for (const { doc } of pages) {
22
- const key = `${doc.variant.channel}|${doc.variant.version}`;
23
+ const key = doc.variant.product ? publicationKey(doc.variant) : `${doc.variant.channel}|${doc.variant.version}`;
23
24
  if (!bindings.has(key))
24
25
  bindings.set(key, sourceForVariant(apiId, definition, doc.variant));
25
26
  }
@@ -35,7 +36,7 @@ export async function reviewApiPublication(configFile, apiPlan, rendered, apiEmb
35
36
  }
36
37
  const reviewedPages = pages.map(({ doc }) => ({ id: doc.frontmatter.id, url: doc.route, markdownUrl: doc.markdownRoute }));
37
38
  const references = pages.filter(({ doc }) => doc.frontmatter.type === 'api-reference').flatMap(({ doc }) => (doc.frontmatter.operations ?? []).filter(id => knownOperations.get(id)?.apiId === apiId).map(id => ({
38
- channel: doc.variant.channel, version: doc.variant.version, language: doc.variant.language,
39
+ ...(doc.variant.product ? { product: doc.variant.product } : {}), channel: doc.variant.channel, version: doc.variant.version, language: doc.variant.language,
39
40
  operation: sourceForOperation(id, doc.variant).sourceOperationId
40
41
  }))).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
41
42
  const embeds = apiEmbedUses.filter(use => use.api === apiId || (use.operation && knownOperations.get(use.operation)?.apiId === apiId))
@@ -1,3 +1,4 @@
1
+ import type { Variant } from './content.js';
1
2
  export type ApiCandidate = {
2
3
  operationId: string;
3
4
  method: string;
@@ -9,12 +10,14 @@ export type ApiCandidate = {
9
10
  slug: string;
10
11
  filename: string;
11
12
  };
12
- export declare function apiCandidates(configFile: string, apiId: string): Promise<{
13
+ export declare function apiCandidates(configFile: string, apiId: string, selection?: Partial<Variant>): Promise<{
13
14
  candidates: ApiCandidate[];
14
15
  selected: Set<string>;
15
16
  pathPrefix: string;
17
+ publication: Variant;
18
+ sourceFile: string;
16
19
  }>;
17
- export declare function selectApiReferences(configFile: string, apiId: string, outputFile: string): Promise<{
20
+ export declare function selectApiReferences(configFile: string, apiId: string, outputFile: string, publication?: Partial<Variant>): Promise<{
18
21
  selected: string[];
19
22
  total: number;
20
23
  file: string;
@@ -1,3 +1,6 @@
1
+ import { resolvePublication } from './compiler-config.js';
2
+ import { defaultLanguage } from './frontmatter.js';
3
+ import { samePublication } from './publication-identity.js';
1
4
  import { mkdir, writeFile } from 'node:fs/promises';
2
5
  import path from 'node:path';
3
6
  import { createInterface } from 'node:readline';
@@ -5,23 +8,27 @@ import YAML from 'yaml';
5
8
  import { ApiReader } from './api.js';
6
9
  import { generatedOperationIdentity } from './api-identity.js';
7
10
  import { explain, loadConfig } from './config.js';
8
- export async function apiCandidates(configFile, apiId) {
11
+ export async function apiCandidates(configFile, apiId, selection = {}) {
9
12
  const loaded = await loadConfig(configFile);
10
13
  const config = loaded.value;
11
14
  const definition = config.apis?.[apiId];
12
15
  if (!definition)
13
16
  throw new Error(`Unknown API ${apiId}`);
14
- const defaults = config.publications?.defaults;
15
- if (!defaults?.channel || !defaults?.version)
16
- throw new Error('API selection needs publication defaults');
17
- const publicationIndex = definition.publications?.findIndex((item) => item.channel === defaults.channel && item.version === defaults.version) ?? -1;
18
- const source = publicationIndex >= 0 ? definition.publications[publicationIndex].source : definition.source;
17
+ const defaults = config.publications?.defaults ?? {};
18
+ const product = config.publications.products ? selection.product ?? definition.product ?? defaults.product : undefined;
19
+ const publication = resolvePublication(config.publications, { ...defaults, ...selection, ...(product ? { product, version: selection.version } : {}) }, defaultLanguage(config));
20
+ if (!config.publications.enabled?.some((item) => samePublication(resolvePublication(config.publications, item, defaultLanguage(config)), publication)))
21
+ throw new Error('API selection publication is not enabled; select an explicit product and release');
22
+ const publicationIndex = definition.publications?.findIndex((item) => item.product === publication.product && item.channel === publication.channel && item.version === publication.version) ?? -1;
23
+ const sourceDefault = definition.source ? resolvePublication(config.publications, { ...defaults, ...(config.publications.products && definition.product ? { product: definition.product, version: undefined } : {}) }, defaultLanguage(config)) : undefined;
24
+ const source = publicationIndex >= 0 ? definition.publications[publicationIndex].source : sourceDefault && publication.product === sourceDefault.product && publication.channel === sourceDefault.channel && publication.version === sourceDefault.version ? definition.source : undefined;
19
25
  if (source?.kind !== 'file')
20
- throw new Error(`API ${apiId} needs a local file source in the default publication`);
26
+ throw new Error(`API ${apiId} needs a local file source in the selected publication`);
21
27
  const sourceKey = publicationIndex >= 0 ? `apis.${apiId}.publications.${publicationIndex}.source.path` : `apis.${apiId}.source.path`;
22
28
  const origin = explain(loaded, sourceKey).source.file;
23
29
  const reader = new ApiReader();
24
- const loadedSpec = await reader.load(path.resolve(path.dirname(origin), source.path));
30
+ const sourceFile = path.resolve(path.dirname(origin), source.path);
31
+ const loadedSpec = await reader.load(sourceFile);
25
32
  const spec = loadedSpec.value;
26
33
  const explicit = new Map((definition.operations ?? []).map((entry) => [entry.sourceOperationId, entry]));
27
34
  const generate = definition.generateReferences;
@@ -47,10 +54,10 @@ export async function apiCandidates(configFile, apiId) {
47
54
  }
48
55
  }
49
56
  const selected = new Set(generate && generate !== true && Array.isArray(generate.include) ? generate.include : generate && generate !== true && Array.isArray(generate.exclude) ? candidates.filter(item => !generate.exclude.includes(item.operationId)).map(item => item.operationId) : generate ? candidates.map(item => item.operationId) : []);
50
- return { candidates, selected, pathPrefix };
57
+ return { candidates, selected, pathPrefix, publication, sourceFile };
51
58
  }
52
- export async function selectApiReferences(configFile, apiId, outputFile) {
53
- const { candidates, selected: current, pathPrefix } = await apiCandidates(configFile, apiId);
59
+ export async function selectApiReferences(configFile, apiId, outputFile, publication = {}) {
60
+ const { candidates, selected: current, pathPrefix } = await apiCandidates(configFile, apiId, publication);
54
61
  const chosen = [];
55
62
  const reader = createInterface({ input: process.stdin, output: process.stdout });
56
63
  const answers = reader[Symbol.asyncIterator]();
@@ -16,6 +16,7 @@ import { defaultShareSvg, faviconSvg, fillShareTemplate, renderPng, touchIconSvg
16
16
  import { paletteCatalog, paletteCss, presetCatalog, resolvePalette } from './palettes.js';
17
17
  import { heading, link, list, paragraph, renderMarkdown, root, searchIndex, shareCardText, text } from './content.js';
18
18
  import { outputUrl } from './representation-tree.js';
19
+ const publicationLabel = (value) => [...(value.product === undefined ? [] : [value.product]), value.channel, value.version, value.language].join('/');
19
20
  export async function assembleArtifacts(input) {
20
21
  const { base, basePath, publicPath, canonical, siteOrigin, manifest, provenanceRecord, rendered, sitemaps, diagramAssets, heroImages, focusedContracts, styleFiles, themeStyleFile, generatedPaletteCss, generatedBadgeCss, search, synonyms, config, builtInSearchProvider, customReaderModule, analyticsModule, mcpAnalyticsModule, previewFiles, assetDirectory, themeSwitcher, themeDirectory, palette, colorMode, generatedFontsCss, fontFiles, fonts, shareImages, shareFor, themePreset, shareFontFiles, shareCache, faviconFile, faviconRoute, customStyleFile, scriptFiles, componentAssets, redirects, apiPublications, api, catalog, headers, documentRoutes, readerFilters, apiSources } = input;
21
22
  const artifacts = new Map();
@@ -198,7 +199,7 @@ export async function assembleArtifacts(input) {
198
199
  const discoveryEntry = ({ doc }, includeType = false) => ({ title: `${fictionalDocument(doc, llms) ? 'Fictional example: ' : ''}${doc.frontmatter.title}`, url: doc.markdownRoute, summary: `${includeType ? `${doc.frontmatter.type} — ` : ''}${fictionalDocument(doc, llms) ? 'Demonstration only; not a live API. ' : ''}${doc.frontmatter.summary}` });
199
200
  const tabs = manifest.navigationTabs ?? [];
200
201
  const tabLinks = tabs.length ? '\n\n## Navigation sections\n\n' + discoveryLinks(tabs.map(tab => ({
201
- title: `${tab.label} (${tab.variant.channel}/${tab.variant.version}/${tab.variant.language})`, url: tab.indexUrl,
202
+ title: `${tab.label} (${publicationLabel(tab.variant)})`, url: tab.indexUrl,
202
203
  summary: `Section ID: ${tab.id}. Scoped page index.`
203
204
  }))) : '';
204
205
  const groups = new Map();
@@ -237,7 +238,7 @@ export async function assembleArtifacts(input) {
237
238
  }))])).trimEnd();
238
239
  const discovery = [renderMarkdown(root([heading(1, String(config.site.title))])).trimEnd(), '', '> Documentation and API contracts published by this site.', ...(readerFilters ? ['', 'Reader views affect the interactive HTML only. This index lists every published page, and each Markdown page includes all reader-marked sections with readable labels. The document manifest records configured reader facets and each page’s marks.'] : []), ...(llms.fictionalPrefixes.length ? ['', 'Entries labeled Fictional example demonstrate documentation features. Their operations and API contracts do not describe a live service.'] : []), '', '## Discovery', '', discoveryLinks([{ title: 'Compact documentation index', url: publicPath('/llms.min.txt'), summary: 'Start here: full-page Markdown links and author-declared standalone section links with sizes and full-page fallbacks. No tools or JSON processing required.' }, ...(search.index ? [{ title: 'Compact heading index', url: publicPath('/search-index.min.json'), summary: 'Page summaries, headings, and smaller section Markdown URLs with sizes; no article text.' }] : []), { title: 'Resource response headers', url: publicPath('/resource-headers.json'), summary: 'Published hosting metadata: content types and representation Link headers for host adapters.' }, { title: 'Document sync snapshot', url: publicPath('/documents.sync.json'), summary: 'Save and compare compact page signatures between builds; build-info.json identifies the current build.' }, { title: 'Structured document manifest', url: publicPath('/documents.json'), summary: 'Stable page IDs, HTML and Markdown URLs, and content digests.' }, ...(sitemaps.size ? [{ title: 'XML sitemap', url: publicPath('/sitemap.xml'), summary: 'Canonical URLs for indexable pages.' }] : []), ...(search.index ? [{ title: 'Lexical search index', url: publicPath('/search-index.json'), summary: 'Downloadable page titles, summaries, headings, and bounded HTML article text. It is an index file, not a query endpoint.' }] : []), ...(catalog ? [{ title: 'API catalog', url: publicPath('/.well-known/api-catalog'), summary: '' }] : [])]), ...sections, ...(apiSources.some(item => llms.format === 'flat' || !fictionalApis.has(item.apiId)) ? ['', '## API contracts', '', discoveryLinks(apiSources.filter(item => llms.format === 'flat' || !fictionalApis.has(item.apiId)).map(item => ({ title: `${fictionalApis.has(item.apiId) ? 'Fictional example: ' : ''}${item.apiId} ${item.channel} ${item.version} OpenAPI`, url: item.sourceUrl, summary: `Pinned ${item.mediaType} source used for the reference.` })))] : []), ...(llms.format === 'grouped' && optional.length ? ['', '## Optional', '', optionalList] : [])].join('\n') + '\n';
239
240
  addPublicArtifact('/llms.txt', discovery + tabLinks + (tabLinks ? '\n' : ''));
240
- const publications = [...new Set(rendered.map(page => `${page.doc.variant.channel}/${page.doc.variant.version}/${page.doc.variant.language}`))].sort();
241
+ const publications = [...new Set(rendered.map(page => `${publicationLabel(page.doc.variant)}`))].sort();
241
242
  const pageSizes = new Map(manifest.documents.map(page => [page.markdownUrl, page]));
242
243
  const compactSummary = (page) => {
243
244
  const size = pageSizes.get(page.doc.markdownRoute);
@@ -245,21 +246,23 @@ export async function assembleArtifacts(input) {
245
246
  };
246
247
  const compactEntries = [...rendered].sort((a, b) => a.doc.route.localeCompare(b.doc.route)).map(page => {
247
248
  const entry = discoveryEntry(page);
248
- const publication = `${page.doc.variant.channel}/${page.doc.variant.version}/${page.doc.variant.language}`;
249
+ const publication = `${publicationLabel(page.doc.variant)}`;
249
250
  const approved = (page.sections ?? []).filter(section => section.standalone === true);
250
251
  return [paragraph(link(entry.url, `${page.doc.frontmatter.id} · ${entry.title}${publications.length > 1 ? ` (${publication})` : ''}`), text(`: ${compactSummary(page)}`)),
251
252
  ...(approved.length ? [list(approved.map(section => [paragraph(text('Standalone section: '), link(section.markdownUrl, section.title), text(` — ${section.markdownTokens} tokens (${section.markdownTokenEncoding}), ${section.markdownBytes} UTF-8 bytes. `), link(entry.url, 'Full page'), text('.'))]))] : [])];
252
253
  });
253
254
  const compactList = renderMarkdown(root([list(compactEntries)])).trimEnd();
255
+ const productGuidance = configField(config.publications, 'products') ? [paragraph(text('Products have independent versions. Discover published product/channel/version/language coordinates with MCP get_publications, or documents.json. Keep the exact publication returned by search when reading pages; cross-product links must name their target explicitly. This edition contains only its selected content.'))] : [];
254
256
  const compactIntro = renderMarkdown(root([
255
257
  heading(1, String(config.site.title)),
258
+ ...productGuidance,
256
259
  paragraph(text(`Full-page token counts use ${markdownTokenEncoding}. Fetch a matching full Markdown page by default. Use a listed standalone section only for its stated topic; for setup, broader questions, or missing context, follow Full page. Standalone is an author declaration, not proof of completeness.`)),
257
- paragraph(text(publications.length === 1 ? `Publication (channel/version/language): ${publications[0]}.` : 'Choose the matching channel/version/language shown on each page; keep that publication when following links.')),
260
+ paragraph(text(publications.length === 1 ? `Publication (${configField(config.publications, 'products') ? 'product/' : ''}channel/version/language): ${publications[0]}.` : `Choose the matching ${configField(config.publications, 'products') ? 'product/' : ''}channel/version/language shown on each page; keep that publication when following links.`)),
258
261
  paragraph(link(publicPath('/llms.txt'), 'Full documentation index'), text('. Full manifests and search indexes are optional. A missing match does not establish that a feature exists or does not exist.')),
259
262
  ])).trimEnd();
260
263
  const topicEntries = rendered.flatMap(page => {
261
264
  const entry = discoveryEntry(page);
262
- const publication = `${page.doc.variant.channel}/${page.doc.variant.version}/${page.doc.variant.language}`;
265
+ const publication = `${publicationLabel(page.doc.variant)}`;
263
266
  const area = Array.isArray(page.doc.frontmatter.area) ? page.doc.frontmatter.area[0] : page.doc.frontmatter.area;
264
267
  const topic = JSON.stringify([publication, area ?? page.doc.frontmatter.type]);
265
268
  const topicLabel = `${(area && manifest.taxonomy?.areas[area]?.label) || area || page.doc.frontmatter.type}${publications.length > 1 ? ` (${publication})` : ''}`;
@@ -283,7 +286,7 @@ export async function assembleArtifacts(input) {
283
286
  const members = manifest.documents.filter(doc => doc.navigationTab?.indexUrl === tab.indexUrl);
284
287
  const intro = renderMarkdown(root([
285
288
  heading(1, tab.label),
286
- paragraph(text(`Full-page token counts use ${markdownTokenEncoding}. Navigation section ID: ${tab.id}. Publication: ${tab.variant.channel}/${tab.variant.version}/${tab.variant.language}.`)),
289
+ paragraph(text(`Full-page token counts use ${markdownTokenEncoding}. Navigation section ID: ${tab.id}. Publication: ${publicationLabel(tab.variant)}.`)),
287
290
  paragraph(link(outputUrl(publicPath('/llms.min.txt'), '/', siteOrigin, 'markdown', documentRoutes, basePath), 'All sections and published pages'), text('. This index covers this section only; shared and unlisted pages remain reachable through the global index. Reader views do not remove pages from this index.')),
288
291
  ])).trimEnd();
289
292
  const memberUrls = new Set(members.flatMap(doc => [doc.markdownUrl, ...doc.sections.filter(section => section.standalone === true).map(section => section.markdownUrl)]));
@@ -14,6 +14,7 @@ import { createSession, turnstileVerifier } from './turnstile.js';
14
14
  import { envRedis } from './budget-store.js';
15
15
  import { pausedKey } from './chat-pause.js';
16
16
  import { deleteKvLogRecord, kvLogSink } from './ask-log-kv.js';
17
+ import { turnstileHostnames } from './turnstile-policy.js';
17
18
  // The answer function for a hosted site. The build writes a directory holding `runtime.json` (the chat and retrieval settings, with no
18
19
  // keys) and `site/ai` (the passages and vectors), and this module turns that directory into a Web `Request` to `Response` function. Keys come
19
20
  // only from the environment variables the settings name. It refuses to start without a shared budget store, because per-instance counters
@@ -39,8 +40,10 @@ export async function createAskFunction(directory, env = process.env, send) {
39
40
  if (chat.challenge) {
40
41
  const secret = env[chat.challenge.secretEnv];
41
42
  if (secret) {
42
- session = createSession({ secret });
43
- const verify = turnstileVerifier({ secret, ...(send ? { fetch: send } : {}) });
43
+ const allowedHostnames = turnstileHostnames(chat.challenge.hostnames ?? hosts.map(host => new URL(`https://${host}`).hostname), 'Turnstile allowedHostnames');
44
+ const context = JSON.stringify({ version: 1, hostnames: [...allowedHostnames].sort(), action: chat.challenge.action ?? null });
45
+ session = createSession({ secret, context });
46
+ const verify = turnstileVerifier({ secret, allowedHostnames, ...(chat.challenge.action ? { action: chat.challenge.action } : {}), ...(send ? { fetch: send } : {}) });
44
47
  challenge = ({ token, ip }) => verify({ token, ip });
45
48
  }
46
49
  else {
@@ -10,6 +10,7 @@ export type AskSetupInput = {
10
10
  settings?: Record<string, unknown>;
11
11
  model?: string;
12
12
  passages?: number;
13
+ product?: string;
13
14
  channel?: string;
14
15
  version?: string;
15
16
  language?: string;
@@ -1,3 +1,4 @@
1
+ import { parsePublicationKey } from './publication-identity.js';
1
2
  import { readFile } from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import { AnswerCache } from './answer-cache.js';
@@ -48,9 +49,13 @@ export async function prepareAskRuntime(input) {
48
49
  const embeddings = await readEmbeddings(input.siteDirectory);
49
50
  const retriever = new Retriever(chunks, embeddings);
50
51
  const variants = retriever.variants();
51
- const variant = input.channel && input.version && input.language ? `${input.channel}|${input.version}|${input.language}` : variants.length === 1 ? variants[0] : undefined;
52
+ const matchingVariants = variants.filter(key => {
53
+ const coordinate = parsePublicationKey(key);
54
+ return ['product', 'channel', 'version', 'language'].every(field => input[field] === undefined || coordinate[field] === input[field]);
55
+ });
56
+ const variant = matchingVariants.length === 1 ? matchingVariants[0] : undefined;
52
57
  if (!variant)
53
- throw new Error(`The site has several publications (${variants.join(', ')}); pass --channel, --version, and --language`);
58
+ throw new Error(`Select one publication from (${matchingVariants.join(', ')}); pass --product where applicable, --channel, --version, and --language`);
54
59
  let embedQuery;
55
60
  let embedTexts;
56
61
  let embedding;
@@ -1,3 +1,4 @@
1
+ import { documentKey } from './publication-identity.js';
1
2
  import { link, list, paragraph, root, text } from './semantic-markdown.js';
2
3
  export const changeKinds = ['editorial', 'procedure', 'behavior', 'breaking'];
3
4
  const labels = { editorial: 'Editorial correction', procedure: 'Procedure change', behavior: 'Behavior change', breaking: 'Breaking change' };
@@ -26,7 +27,7 @@ export function resolveAuthoredChange(doc, docs) {
26
27
  if (!value)
27
28
  return;
28
29
  const target = (id, field) => {
29
- const found = docs.get(`${id}|${doc.variant.channel}|${doc.variant.version}|${doc.variant.language}`);
30
+ const found = docs.get(documentKey(id, doc.variant));
30
31
  if (id === doc.frontmatter.id || !found || found.frontmatter.access?.policy !== 'public')
31
32
  throw new Error(`${doc.file}: change.${field} must name another public document in the same publication: ${id}`);
32
33
  return { id, title: found.frontmatter.title, url: found.route, markdownUrl: found.markdownRoute };
@@ -119,7 +119,7 @@ export async function inspectAuthoringProject(configFile, options = {}) {
119
119
  const doc = await readDocument(file, value.frontmatter, undefined, raw);
120
120
  const fm = doc.frontmatter;
121
121
  pages.push({ id: fm.id, file: relative(file), digest: digest(raw), title: fm.title, summary: fm.summary, type: fm.type, slug: fm.slug,
122
- publication: { channel: fm.channel ?? value.publications?.defaults?.channel, version: fm.version ?? value.publications?.defaults?.version, language: fm.language ?? defaultLanguage(value), ...(fm.publications ? { publications: fm.publications } : {}) },
122
+ publication: { ...(value.publications?.products && fm.product ? { product: fm.product } : {}), channel: fm.channel ?? value.publications?.defaults?.channel, version: value.publications?.products && fm.product && doc.sourceFrontmatter.version === undefined && value.frontmatter?.enforced?.version === undefined ? value.publications.products[fm.product]?.defaultVersion : fm.version ?? value.publications?.defaults?.version, language: fm.language ?? defaultLanguage(value), ...(fm.publications ? { publications: fm.publications } : {}) },
123
123
  access: fm.access ?? null, aliases: [] });
124
124
  bodies.set(relative(file), doc.body);
125
125
  findings.push(...authoringHints(doc.body, relative(file)).map(({ location, ...hint }) => hint));
package/dist/cards.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { samePublication } from './publication-identity.js';
1
2
  import { cardIcon, validateCardIcon } from './icons.js';
2
3
  import { surfaceText } from './surface-text.js';
3
4
  import { heading, link, list, paragraph, text } from './content.js';
@@ -7,7 +8,7 @@ const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
7
8
  const relationLabels = { prerequisite: 'Read first', 'next-step': 'Next steps', reference: 'Reference while working', advanced: 'Go deeper', 'see-also': 'Related topics', 'not-confused-with': 'Often confused with' };
8
9
  const relationTypes = new Set(Object.keys(relationLabels));
9
10
  const symmetric = (type) => type === 'see-also' || type === 'not-confused-with';
10
- const sameVariant = (a, b) => a.channel === b.channel && a.version === b.version && a.language === b.language;
11
+ const sameVariant = (a, b) => samePublication(a, b);
11
12
  export function validateCardMetadata(value, file) {
12
13
  if (value === undefined)
13
14
  return;
@@ -31,6 +31,8 @@ export type ChatChallenge = {
31
31
  provider: 'turnstile';
32
32
  siteKey: string;
33
33
  secretEnv: string;
34
+ hostnames?: string[];
35
+ action?: string;
34
36
  when: 'adaptive' | 'always';
35
37
  freeQuestions: number;
36
38
  busyShare: number;
@@ -1,5 +1,6 @@
1
1
  import { reservedBodyFields } from './chat.js';
2
2
  import { validateReaderSelection } from './reader-filters.js';
3
+ import { turnstileHostnames } from './turnstile-policy.js';
3
4
  export const escalateReasons = ['unsupported-claim', 'unsupported-code', 'uncited'];
4
5
  export const defaultLogNotice = 'Questions are recorded, with personal details removed, to improve these docs.';
5
6
  const mapping = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
@@ -305,9 +306,9 @@ export function validateChat(value, readerFilters) {
305
306
  if (!mapping(challenge))
306
307
  throw new Error('chat.challenge must be a mapping with provider, siteKey, and secretEnv');
307
308
  for (const key of Object.keys(challenge)) {
308
- if (['provider', 'siteKey', 'secretEnv', 'when', 'freeQuestions', 'busyShare'].includes(key))
309
+ if (['provider', 'siteKey', 'secretEnv', 'hostnames', 'action', 'when', 'freeQuestions', 'busyShare'].includes(key))
309
310
  continue;
310
- throw new Error(/key|secret|token|password/i.test(key) ? `chat.challenge.${key} is not a setting. The config never holds a secret; name the environment variable that does with secretEnv` : `chat.challenge has an unknown setting ${key}; it accepts provider, siteKey, secretEnv, when, freeQuestions, and busyShare`);
311
+ throw new Error(/key|secret|token|password/i.test(key) ? `chat.challenge.${key} is not a setting. The config never holds a secret; name the environment variable that does with secretEnv` : `chat.challenge has an unknown setting ${key}; it accepts provider, siteKey, secretEnv, hostnames, action, when, freeQuestions, and busyShare`);
311
312
  }
312
313
  if (challenge.provider !== 'turnstile')
313
314
  throw new Error('chat.challenge.provider must be turnstile');
@@ -322,6 +323,13 @@ export function validateChat(value, readerFilters) {
322
323
  if (challenge.busyShare !== undefined && (typeof challenge.busyShare !== 'number' || !(challenge.busyShare > 0 && challenge.busyShare <= 1)))
323
324
  throw new Error('chat.challenge.busyShare must be a number above 0 and at most 1');
324
325
  result.challenge = { provider: 'turnstile', siteKey, secretEnv, when: challenge.when ?? 'adaptive', freeQuestions: challenge.freeQuestions === undefined ? 3 : integer(challenge.freeQuestions, 'chat.challenge.freeQuestions', 0, 1000), busyShare: challenge.busyShare ?? 0.5 };
326
+ if (challenge.hostnames !== undefined)
327
+ result.challenge.hostnames = turnstileHostnames(challenge.hostnames, 'chat.challenge.hostnames');
328
+ if (challenge.action !== undefined) {
329
+ if (typeof challenge.action !== 'string' || !/^[A-Za-z0-9_-]{1,32}$/.test(challenge.action))
330
+ throw new Error('chat.challenge.action must contain 1 to 32 letters, numbers, underscores, or hyphens');
331
+ result.challenge.action = challenge.action;
332
+ }
325
333
  }
326
334
  if (value.budget !== undefined) {
327
335
  if (!mapping(value.budget))
@@ -1,4 +1,4 @@
1
- export declare const docsHelp = "Usage: shoalrun docs <command>\n\nRead bundled references (no project or provider key required):\n search <query> [--json]\n read <document-id> [--json]\n\nInspect a project:\n project [--config FILE] [--profile FILE] [--section pages|guidance|configuration|navigation|relationships|templates|findings]\n source FILE [--config FILE] [--profile FILE]\n context <document-id> [--config FILE]\n\nValidate and preview edits:\n baseline --out FILE [--config FILE] [--profile FILE]\n validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n validation-status REPORT\n review REPORT [--format json|markdown]\n preview REPORT [--port PORT]\n\nOther authoring tools: changes, plan, apply, mcp.\nDiscover packaged agent guidance with shoalrun skills list.\n";
1
+ export declare const docsHelp = "Usage: shoalrun docs <command>\n\nRead bundled references (no project or provider key required):\n search <query> [--json]\n read <document-id> [--json]\n outline <document-id> [--json]\n section <document-id> <section-id> [--json]\n\nSearch and reads accept --site DIRECTORY, --max-tokens N, and publication\nselectors --product P --channel C --version V --language L.\n\nInspect a project:\n project [--config FILE] [--profile FILE] [--section pages|guidance|configuration|navigation|relationships|templates|findings]\n source FILE [--config FILE] [--profile FILE]\n context <document-id> [--config FILE]\n\nValidate and preview edits:\n baseline --out FILE [--config FILE] [--profile FILE]\n validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n validation-status REPORT\n review REPORT [--format json|markdown]\n preview REPORT [--port PORT]\n\nOther authoring tools: changes, plan, apply, mcp.\nDiscover packaged agent guidance with shoalrun skills list.\n";
2
2
  export declare const skillsHelp = "Usage: shoalrun skills list [--json]\n shoalrun skills read <name> [--json]\n\nList the names, descriptions and local paths of packaged skills, or read a skill.\nThese commands do not install skills or require a project or provider key.\n";
3
- export declare const cliHelp = "Usage: shoalrun <command>\n\nStart and build:\n init [directory] [--starter minimal|api-docs|showcase]\n build [config] [output] [--profile FILE]\n export [config] --out DIRECTORY [--target NAME] [--profile FILE]\n dev [config] [output] [--port PORT]\n serve <site-directory> [--host HOST] [--port PORT]\n check [config] [--json]\n audit [config]\n scaffold <template> -n <target> [--config FILE]\n\nAgent guidance and offline documentation:\n skills list [--json]\n skills read <name> [--json]\n docs search <query> [--json]\n docs read <document-id> [--json]\n docs project [--config FILE] [--profile FILE]\n docs baseline --out FILE [--config FILE] [--profile FILE]\n docs validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n docs review REPORT [--format json|markdown]\n docs preview REPORT [--port PORT]\n\nOther commands: config, api, operation, ingredient, recipe, search, index,\nask, answers, ask-log, chat, eval, vercel.\nRun shoalrun docs --help or shoalrun skills --help for discovery commands.\n";
3
+ export declare const cliHelp = "Usage: shoalrun <command>\n\nStart and build:\n init [directory] [--starter minimal|api-docs|showcase]\n build [config] [output] [--profile FILE]\n export [config] --out DIRECTORY [--target NAME] [--profile FILE]\n dev [config] [output] [--profile FILE] [--port PORT]\n serve <site-directory> [--host HOST] [--port PORT]\n check [config] [--json]\n audit [config]\n scaffold <template> -n <target> [--config FILE] [--product P]\n\nAgent guidance and offline documentation:\n skills list [--json]\n skills read <name> [--json]\n docs search <query> [--site DIRECTORY] [--product P] [--json]\n docs read <document-id> [--site DIRECTORY] [--product P] [--json]\n docs project [--config FILE] [--profile FILE]\n docs baseline --out FILE [--config FILE] [--profile FILE]\n docs validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]\n docs review REPORT [--format json|markdown]\n docs preview REPORT [--port PORT]\n\nOther commands: config, api, operation, ingredient, recipe, search, index,\nask, answers, ask-log, chat, eval, vercel.\nRun shoalrun docs --help or shoalrun skills --help for discovery commands.\n";
4
4
  export declare function runSkillsCommand(args: string[]): Promise<string>;
@@ -7,6 +7,11 @@ export const docsHelp = `Usage: shoalrun docs <command>
7
7
  Read bundled references (no project or provider key required):
8
8
  search <query> [--json]
9
9
  read <document-id> [--json]
10
+ outline <document-id> [--json]
11
+ section <document-id> <section-id> [--json]
12
+
13
+ Search and reads accept --site DIRECTORY, --max-tokens N, and publication
14
+ selectors --product P --channel C --version V --language L.
10
15
 
11
16
  Inspect a project:
12
17
  project [--config FILE] [--profile FILE] [--section pages|guidance|configuration|navigation|relationships|templates|findings]
@@ -35,17 +40,17 @@ Start and build:
35
40
  init [directory] [--starter minimal|api-docs|showcase]
36
41
  build [config] [output] [--profile FILE]
37
42
  export [config] --out DIRECTORY [--target NAME] [--profile FILE]
38
- dev [config] [output] [--port PORT]
43
+ dev [config] [output] [--profile FILE] [--port PORT]
39
44
  serve <site-directory> [--host HOST] [--port PORT]
40
45
  check [config] [--json]
41
46
  audit [config]
42
- scaffold <template> -n <target> [--config FILE]
47
+ scaffold <template> -n <target> [--config FILE] [--product P]
43
48
 
44
49
  Agent guidance and offline documentation:
45
50
  skills list [--json]
46
51
  skills read <name> [--json]
47
- docs search <query> [--json]
48
- docs read <document-id> [--json]
52
+ docs search <query> [--site DIRECTORY] [--product P] [--json]
53
+ docs read <document-id> [--site DIRECTORY] [--product P] [--json]
49
54
  docs project [--config FILE] [--profile FILE]
50
55
  docs baseline --out FILE [--config FILE] [--profile FILE]
51
56
  docs validate (--baseline FILE | --file FILE | --id ID) [--config FILE] [--profile FILE]