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

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 (677) hide show
  1. package/AUTHORING.md +29 -0
  2. package/CHANGELOG.md +23 -0
  3. package/DEPLOYMENT-PROFILES.md +96 -5
  4. package/README.md +58 -2
  5. package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +21 -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/product-publications.md +60 -0
  254. package/agent-docs/changelog/working-tree-skill.md +1 -1
  255. package/agent-docs/changelog.md +17 -1
  256. package/agent-docs/chat/checks.md +11 -11
  257. package/agent-docs/chat/checks.sections/answer-ahead-of-time.md +1 -1
  258. package/agent-docs/chat/checks.sections/answer-for-one-audience.md +2 -2
  259. package/agent-docs/chat/checks.sections/answer-without-a-model.md +2 -2
  260. package/agent-docs/chat/checks.sections/follow-up-questions.md +2 -2
  261. package/agent-docs/chat/checks.sections/how-an-answer-is-checked.md +3 -3
  262. package/agent-docs/chat/checks.sections/questions-with-several-parts.md +3 -3
  263. package/agent-docs/chat/checks.sections/related-reading.md +1 -1
  264. package/agent-docs/chat/checks.sections/reuse-answers.md +4 -4
  265. package/agent-docs/chat/host.md +8 -8
  266. package/agent-docs/chat/host.sections/cap-the-daily-spend.md +2 -2
  267. package/agent-docs/chat/host.sections/keep-a-record-of-questions.md +3 -3
  268. package/agent-docs/chat/host.sections/related-reading.md +2 -2
  269. package/agent-docs/chat/passage-index.md +17 -17
  270. package/agent-docs/chat/passage-index.sections/build-the-index.md +2 -2
  271. package/agent-docs/chat/passage-index.sections/embed-passages.md +3 -3
  272. package/agent-docs/chat/passage-index.sections/how-the-default-chunker-splits-a-page.md +2 -2
  273. package/agent-docs/chat/passage-index.sections/limits.md +2 -2
  274. package/agent-docs/chat/passage-index.sections/passage-ids-and-links.md +3 -3
  275. package/agent-docs/chat/passage-index.sections/related-reading.md +2 -2
  276. package/agent-docs/chat/passage-index.sections/what-a-passage-contains.md +15 -15
  277. package/agent-docs/chat/prepared-answers.md +4 -4
  278. package/agent-docs/chat/settings.md +3 -3
  279. package/agent-docs/chat/settings.sections/choose-the-scorer.md +1 -1
  280. package/agent-docs/chat/settings.sections/configure-chat.md +1 -1
  281. package/agent-docs/chat/settings.sections/configure-retrieval.md +1 -1
  282. package/agent-docs/chat/settings.sections/related-reading.md +1 -1
  283. package/agent-docs/chat/settings.sections/send-extra-request-fields.md +2 -2
  284. package/agent-docs/chat/settings.sections/use-more-than-one-model.md +2 -2
  285. package/agent-docs/chat/settings.sections/when-the-scorer-is-down.md +1 -1
  286. package/agent-docs/chat/setup.md +2 -2
  287. package/agent-docs/chat.md +3 -3
  288. package/agent-docs/cli.md +73 -59
  289. package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +11 -7
  290. package/agent-docs/cli.sections/author-pages.md +16 -12
  291. package/agent-docs/cli.sections/build-and-serve.md +30 -18
  292. package/agent-docs/cli.sections/inspect-config-and-operations.md +13 -9
  293. package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +7 -3
  294. package/agent-docs/cli.sections/related-reading.md +6 -2
  295. package/agent-docs/cli.sections/search-and-chat.md +24 -18
  296. package/agent-docs/cli.sections/start-a-project.md +7 -3
  297. package/agent-docs/cli.sections/working-tree-authoring-tools.md +7 -3
  298. package/agent-docs/concepts.md +2 -2
  299. package/agent-docs/config/apis.md +2 -2
  300. package/agent-docs/config/content.md +3 -3
  301. package/agent-docs/config/content.sections/authoring.md +3 -3
  302. package/agent-docs/config/content.sections/badges.md +1 -1
  303. package/agent-docs/config/content.sections/callouts.md +1 -1
  304. package/agent-docs/config/content.sections/cookbooks.md +1 -1
  305. package/agent-docs/config/content.sections/frontmatter.md +1 -1
  306. package/agent-docs/config/content.sections/readerfilters.md +1 -1
  307. package/agent-docs/config/content.sections/related-reading.md +1 -1
  308. package/agent-docs/config/content.sections/relationships.md +1 -1
  309. package/agent-docs/config/content.sections/snippets.md +1 -1
  310. package/agent-docs/config/content.sections/templates.md +1 -1
  311. package/agent-docs/config/content.sections/variables.md +1 -1
  312. package/agent-docs/config/examples.md +4 -4
  313. package/agent-docs/config/examples.sections/feature-showcase.md +4 -4
  314. package/agent-docs/config/examples.sections/minimal-site.md +2 -2
  315. package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
  316. package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
  317. package/agent-docs/config/examples.sections/related-reading.md +2 -2
  318. package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
  319. package/agent-docs/config/integrations.md +4 -4
  320. package/agent-docs/config/outputs.md +22 -16
  321. package/agent-docs/config/outputs.sections/exports.md +19 -13
  322. package/agent-docs/config/outputs.sections/metadata.md +2 -2
  323. package/agent-docs/config/outputs.sections/related-reading.md +1 -1
  324. package/agent-docs/config/publishing.md +29 -19
  325. package/agent-docs/config/publishing.sections/navigation.md +2 -2
  326. package/agent-docs/config/publishing.sections/redirects.md +8 -8
  327. package/agent-docs/config/publishing.sections/related-reading.md +2 -2
  328. package/agent-docs/config/site.md +42 -18
  329. package/agent-docs/config/site.sections/related-reading.md +1 -1
  330. package/agent-docs/config/site.sections/theme.md +1 -1
  331. package/agent-docs/config.md +2 -2
  332. package/agent-docs/configuration.md +19 -19
  333. package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
  334. package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +5 -5
  335. package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
  336. package/agent-docs/configuration.sections/inspect-and-validate-changes.md +5 -5
  337. package/agent-docs/configuration.sections/related-reading.md +1 -1
  338. package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +5 -5
  339. package/agent-docs/configuration.sections/share-defaults-through-extends.md +3 -3
  340. package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
  341. package/agent-docs/configuration.sections/understand-the-three-stages.md +3 -3
  342. package/agent-docs/configuration.sections/understand-where-paths-point.md +2 -2
  343. package/agent-docs/connect/mcp.md +24 -15
  344. package/agent-docs/content-delivery/agents.md +6 -6
  345. package/agent-docs/content-delivery/api.md +29 -16
  346. package/agent-docs/content-delivery/client.md +14 -8
  347. package/agent-docs/content-delivery/http-api/operations/get-content-representation-fa1d2e3f.md +10 -2
  348. package/agent-docs/content-delivery/http-api/operations/get-content-representation-head-4052375c.md +10 -2
  349. package/agent-docs/content-delivery/http-api/operations/get-content-resource-849f1c49.md +537 -3
  350. package/agent-docs/content-delivery/http-api/operations/get-content-resource-head-0a352acd.md +10 -2
  351. package/agent-docs/content-delivery/http-api/operations/list-content-resources-8e977ec7.md +545 -3
  352. package/agent-docs/content-delivery/http-api/operations/list-content-resources-head-b67cbad9.md +10 -2
  353. package/agent-docs/content-delivery/http-api.md +21 -7
  354. package/agent-docs/content-delivery/manifest.md +30 -8
  355. package/agent-docs/content-delivery/publish.md +5 -5
  356. package/agent-docs/content-delivery/render.md +6 -6
  357. package/agent-docs/content-delivery/rest.md +16 -8
  358. package/agent-docs/content-delivery/sections.md +11 -11
  359. package/agent-docs/content-delivery/select.md +6 -6
  360. package/agent-docs/content-delivery.md +4 -4
  361. package/agent-docs/contribute/agent-skills.md +3 -3
  362. package/agent-docs/cookbooks/authoring.md +3 -3
  363. package/agent-docs/cookbooks/site-workflows.md +2 -2
  364. package/agent-docs/cookbooks/welcome-email.md +3 -3
  365. package/agent-docs/documents.json +2415 -1936
  366. package/agent-docs/example-api/cedar.md +4 -4
  367. package/agent-docs/features.md +49 -0
  368. package/agent-docs/glossary.md +22 -22
  369. package/agent-docs/index.md +5 -5
  370. package/agent-docs/ingredients/audit-site.md +2 -2
  371. package/agent-docs/ingredients/build-site.md +2 -2
  372. package/agent-docs/ingredients/complete-page.md +2 -2
  373. package/agent-docs/ingredients/refresh-agent-bundle.md +2 -2
  374. package/agent-docs/non-goals.md +4 -4
  375. package/agent-docs/provenance.json +10 -4
  376. package/agent-docs/publish/agent-discovery.md +8 -2
  377. package/agent-docs/publish/agent-friendliness.md +21 -21
  378. package/agent-docs/publish/agent-friendliness.sections/discover-a-page-with-a-small-context-budget.md +5 -5
  379. package/agent-docs/publish/agent-friendliness.sections/distinguish-examples-from-a-real-service.md +5 -5
  380. package/agent-docs/publish/agent-friendliness.sections/evidence-has-a-scope.md +5 -5
  381. package/agent-docs/publish/agent-friendliness.sections/keep-shared-instructions-complete.md +5 -5
  382. package/agent-docs/publish/agent-friendliness.sections/related-reading.md +3 -3
  383. package/agent-docs/publish/agent-friendliness.sections/secret-handshake.md +3 -3
  384. package/agent-docs/publish/agent-friendliness.sections/try-the-page-controls.md +3 -3
  385. package/agent-docs/publish/agent-friendliness.sections/use-the-transport-your-client-supports.md +4 -4
  386. package/agent-docs/publish/agent-friendliness.sections/verify-the-page-and-detect-changes.md +9 -9
  387. package/agent-docs/publish/agent-friendliness.sections/what-an-agent-reads.md +5 -5
  388. package/agent-docs/publish/agent-friendliness.sections/what-happens-to-an-unsupported-component.md +4 -4
  389. package/agent-docs/publish/api-references.md +5 -5
  390. package/agent-docs/publish/api-references.sections/author-the-reference-page.md +2 -2
  391. package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -3
  392. package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +2 -2
  393. package/agent-docs/publish/api-references.sections/next-steps.md +2 -2
  394. package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +2 -2
  395. package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +2 -2
  396. package/agent-docs/publish/api-references.sections/register-the-operation.md +2 -2
  397. package/agent-docs/publish/api-references.sections/related-reading.md +2 -2
  398. package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -3
  399. package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -3
  400. package/agent-docs/publish/audit.md +8 -8
  401. package/agent-docs/publish/audit.sections/add-project-tests.md +2 -2
  402. package/agent-docs/publish/audit.sections/check-agent-evaluation-reports.md +2 -2
  403. package/agent-docs/publish/audit.sections/check-before-pushing.md +3 -3
  404. package/agent-docs/publish/audit.sections/connect-a-documentation-test-suite.md +2 -2
  405. package/agent-docs/publish/audit.sections/read-the-report.md +3 -3
  406. package/agent-docs/publish/audit.sections/related-reading.md +1 -1
  407. package/agent-docs/publish/content-export.md +37 -15
  408. package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +4 -4
  409. package/agent-docs/publish/content-export.sections/check-the-result.md +2 -2
  410. package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +3 -3
  411. package/agent-docs/publish/content-export.sections/prerequisites.md +4 -4
  412. package/agent-docs/publish/content-export.sections/related-reading.md +2 -2
  413. package/agent-docs/publish/content-export.sections/review-exported-api-material.md +3 -3
  414. package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +2 -2
  415. package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +4 -4
  416. package/agent-docs/publish/content-negotiation.md +10 -10
  417. package/agent-docs/publish/content-negotiation.sections/hosting-contract.md +2 -2
  418. package/agent-docs/publish/content-negotiation.sections/missing-pages.md +3 -3
  419. package/agent-docs/publish/content-negotiation.sections/related-reading.md +1 -1
  420. package/agent-docs/publish/content-negotiation.sections/validators-and-manifest-links.md +2 -2
  421. package/agent-docs/publish/content-negotiation.sections/verify-the-deployed-url.md +2 -2
  422. package/agent-docs/publish/content-negotiation.sections/what-if-the-host-cannot-negotiate.md +3 -3
  423. package/agent-docs/publish/content-negotiation.sections/what-shoalrun-builds-and-what-the-host-does.md +2 -2
  424. package/agent-docs/publish/content-negotiation.sections/why-this-matters.md +2 -2
  425. package/agent-docs/publish/deployment-check.md +6 -6
  426. package/agent-docs/publish/deployment-profiles.md +60 -26
  427. package/agent-docs/publish/deployment-profiles.sections/before-you-begin.md +5 -5
  428. package/agent-docs/publish/deployment-profiles.sections/build-and-inspect-the-edition.md +9 -9
  429. package/agent-docs/publish/deployment-profiles.sections/check-the-result.md +7 -7
  430. package/agent-docs/publish/deployment-profiles.sections/choose-navigation-labels.md +6 -6
  431. package/agent-docs/publish/deployment-profiles.sections/current-limits.md +7 -7
  432. package/agent-docs/publish/deployment-profiles.sections/define-the-shared-sku-manifest.md +6 -6
  433. package/agent-docs/publish/deployment-profiles.sections/html-markdown-and-agents.md +7 -7
  434. package/agent-docs/publish/deployment-profiles.sections/mark-pages-and-shared-sections.md +13 -13
  435. package/agent-docs/publish/deployment-profiles.sections/preview-and-edit-a-customer-edition.md +55 -0
  436. package/agent-docs/publish/deployment-profiles.sections/related-reading.md +6 -6
  437. package/agent-docs/publish/deployment-profiles.sections/select-each-product-release.md +55 -0
  438. package/agent-docs/publish/deployment-profiles.sections/supply-the-profile-from-the-deployment.md +6 -6
  439. package/agent-docs/publish/evals.md +16 -16
  440. package/agent-docs/publish/evals.sections/add-the-audit-hook.md +5 -5
  441. package/agent-docs/publish/evals.sections/check-the-report.md +4 -4
  442. package/agent-docs/publish/evals.sections/define-a-task-file.md +5 -5
  443. package/agent-docs/publish/evals.sections/diagnose-a-different-build.md +5 -5
  444. package/agent-docs/publish/evals.sections/prepare-a-report-for-the-built-site.md +5 -5
  445. package/agent-docs/publish/evals.sections/related-reading.md +3 -3
  446. package/agent-docs/publish/evals.sections/run-and-review-the-tasks.md +4 -4
  447. package/agent-docs/publish/evals.sections/shoalrun-s-own-example.md +6 -6
  448. package/agent-docs/publish/host-adapters.md +6 -6
  449. package/agent-docs/publish/manni.md +16 -16
  450. package/agent-docs/publish/manni.sections/check-the-result.md +3 -3
  451. package/agent-docs/publish/manni.sections/how-this-site-uses-manni.md +6 -6
  452. package/agent-docs/publish/manni.sections/optional-custom-policies.md +4 -4
  453. package/agent-docs/publish/manni.sections/prerequisites.md +2 -2
  454. package/agent-docs/publish/mcp-analytics.md +12 -12
  455. package/agent-docs/publish/mcp-analytics.sections/adapter-exports.md +4 -4
  456. package/agent-docs/publish/mcp-analytics.sections/enable-analytics.md +4 -4
  457. package/agent-docs/publish/mcp-analytics.sections/event-fields-and-service-mappings.md +4 -4
  458. package/agent-docs/publish/mcp-analytics.sections/optionally-collect-intent-and-group-calls.md +4 -4
  459. package/agent-docs/publish/mcp-analytics.sections/optionally-identify-the-client-and-model.md +5 -5
  460. package/agent-docs/publish/mcp-analytics.sections/related-reading.md +3 -3
  461. package/agent-docs/publish/mcp-analytics.sections/safeguards-and-limits.md +5 -5
  462. package/agent-docs/publish/mcp.md +56 -29
  463. package/agent-docs/publish/mcp.sections/check-budgets-and-errors.md +8 -8
  464. package/agent-docs/publish/mcp.sections/choose-the-documentation-source.md +4 -4
  465. package/agent-docs/publish/mcp.sections/configure-the-client.md +4 -4
  466. package/agent-docs/publish/mcp.sections/discover-product-releases-before-searching.md +52 -0
  467. package/agent-docs/publish/mcp.sections/generate-a-vercel-endpoint.md +6 -6
  468. package/agent-docs/publish/mcp.sections/html-markdown-and-agents.md +38 -0
  469. package/agent-docs/publish/mcp.sections/related-reading.md +3 -3
  470. package/agent-docs/publish/mcp.sections/search-then-read.md +13 -12
  471. package/agent-docs/publish/mcp.sections/serve-a-public-endpoint-on-node.md +12 -8
  472. package/agent-docs/publish/mcp.sections/verify-the-connection.md +4 -4
  473. package/agent-docs/publish/mcp.sections/why-offer-mcp-for-public-docs.md +4 -4
  474. package/agent-docs/publish/openapi-extension-mappings.md +12 -12
  475. package/agent-docs/publish/output.md +20 -20
  476. package/agent-docs/publish/output.sections/api-contracts.md +1 -1
  477. package/agent-docs/publish/output.sections/code-highlighting.md +1 -1
  478. package/agent-docs/publish/output.sections/current-limits.md +1 -1
  479. package/agent-docs/publish/output.sections/incremental-sync.md +4 -4
  480. package/agent-docs/publish/output.sections/manifest-records-and-sections.md +3 -3
  481. package/agent-docs/publish/output.sections/navigation-section-indexes.md +1 -1
  482. package/agent-docs/publish/output.sections/page-formats.md +2 -2
  483. package/agent-docs/publish/output.sections/published-output-contract.md +5 -5
  484. package/agent-docs/publish/output.sections/reader-appearance-and-controls.md +1 -1
  485. package/agent-docs/publish/output.sections/related-reading.md +1 -1
  486. package/agent-docs/publish/output.sections/response-identity.md +1 -1
  487. package/agent-docs/publish/output.sections/site-files.md +6 -6
  488. package/agent-docs/publish/output.sections/validate-an-existing-build-locally.md +3 -3
  489. package/agent-docs/publish/output.sections/where-files-go.md +3 -3
  490. package/agent-docs/publish/publications.md +108 -19
  491. package/agent-docs/publish/publications.sections/add-a-language.md +60 -0
  492. package/agent-docs/publish/publications.sections/change-just-one-part-of-a-shared-page.md +63 -0
  493. package/agent-docs/publish/publications.sections/give-each-api-version-its-own-contract.md +34 -0
  494. package/agent-docs/publish/publications.sections/keep-an-unchanged-page-in-one-file.md +53 -0
  495. package/agent-docs/publish/publications.sections/publish-versions-without-a-product-catalog.md +49 -0
  496. package/agent-docs/publish/publications.sections/related-reading.md +42 -0
  497. package/agent-docs/publish/publications.sections/version-products-independently.md +115 -0
  498. package/agent-docs/publish/publications.sections/what-agents-receive.md +38 -0
  499. package/agent-docs/publish/revisions.md +4 -4
  500. package/agent-docs/publish/seo.md +10 -10
  501. package/agent-docs/publish/seo.sections/related-reading.md +2 -2
  502. package/agent-docs/publish/seo.sections/set-the-public-address.md +3 -3
  503. package/agent-docs/publish/seo.sections/what-agents-receive.md +3 -3
  504. package/agent-docs/publish/seo.sections/what-the-build-adds.md +2 -2
  505. package/agent-docs/publish/seo.sections/write-the-page-title-and-summary.md +2 -2
  506. package/agent-docs/publish/single-source-sites.md +5 -5
  507. package/agent-docs/publish/troubleshooting.md +10 -10
  508. package/agent-docs/publish/vercel.md +5 -5
  509. package/agent-docs/publish/vercel.sections/check-the-deployment.md +1 -1
  510. package/agent-docs/publish/vercel.sections/include-an-mcp-endpoint.md +2 -2
  511. package/agent-docs/publish/vercel.sections/prepare-your-project.md +2 -2
  512. package/agent-docs/publish/vercel.sections/related-reading.md +1 -1
  513. package/agent-docs/publish.md +2 -2
  514. package/agent-docs/recipes/add-page.md +5 -5
  515. package/agent-docs/recipes/add-page.sections/audit-the-shoalrun-docs-project.md +2 -2
  516. package/agent-docs/recipes/add-page.sections/before-you-start.md +1 -1
  517. package/agent-docs/recipes/add-page.sections/build-the-shoalrun-docs-site.md +2 -2
  518. package/agent-docs/recipes/add-page.sections/check-agent-search-and-page-lookup.md +1 -1
  519. package/agent-docs/recipes/add-page.sections/check-the-built-page-artifacts.md +1 -1
  520. package/agent-docs/recipes/add-page.sections/check-the-outcome.md +1 -1
  521. package/agent-docs/recipes/add-page.sections/complete-the-guide-and-add-navigation.md +2 -2
  522. package/agent-docs/recipes/add-page.sections/install-the-site-dependencies.md +1 -1
  523. package/agent-docs/recipes/add-page.sections/regenerate-the-agent-documentation-bundle.md +2 -2
  524. package/agent-docs/recipes/add-page.sections/related-reading.md +1 -1
  525. package/agent-docs/recipes/add-page.sections/scaffold-a-new-guide.md +1 -1
  526. package/agent-docs/recipes/audit-docs.md +4 -4
  527. package/agent-docs/recipes/build-docs.md +2 -2
  528. package/agent-docs/recipes/preview-hybrid-search.md +5 -5
  529. package/agent-docs/recipes/preview-page.md +2 -2
  530. package/agent-docs/recipes/queue-email.md +2 -2
  531. package/agent-docs/recipes/refresh-agent-docs.md +4 -4
  532. package/agent-docs/recipes/send-welcome-email.md +13 -13
  533. package/agent-docs/reference/agent-skills.md +7 -7
  534. package/agent-docs/search-and-chat.md +4 -4
  535. package/agent-docs/search-index.json +1 -1
  536. package/agent-docs/start.md +5 -5
  537. package/agent-docs/start.sections/add-the-page-to-navigation.md +3 -3
  538. package/agent-docs/start.sections/build-and-check-both-outputs.md +3 -3
  539. package/agent-docs/start.sections/build-this-site.md +2 -2
  540. package/agent-docs/start.sections/check-writing-style.md +2 -2
  541. package/agent-docs/start.sections/create-a-page.md +2 -2
  542. package/agent-docs/start.sections/make-it-yours.md +2 -2
  543. package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
  544. package/agent-docs/start.sections/prerequisites.md +2 -2
  545. package/agent-docs/start.sections/related-reading.md +2 -2
  546. package/agent-docs/start.sections/start-your-own-project.md +3 -3
  547. package/agent-docs/status.md +14 -4
  548. package/agent-docs/styling/color-modes.md +2 -2
  549. package/agent-docs/styling/footer.md +2 -2
  550. package/agent-docs/styling/header.md +2 -2
  551. package/agent-docs/styling/layouts.md +3 -3
  552. package/agent-docs/styling/layouts.sections/build-a-landing-page.md +1 -1
  553. package/agent-docs/styling/layouts.sections/build-a-splash-page.md +1 -1
  554. package/agent-docs/styling/layouts.sections/control-navigation-tabs.md +2 -2
  555. package/agent-docs/styling/layouts.sections/customize-the-hero.md +1 -1
  556. package/agent-docs/styling/layouts.sections/hero.md +1 -1
  557. package/agent-docs/styling/layouts.sections/hide-the-table-of-contents-or-give-content-more-room.md +1 -1
  558. package/agent-docs/styling/layouts.sections/html-markdown-and-agents.md +2 -2
  559. package/agent-docs/styling/layouts.sections/related-reading.md +1 -1
  560. package/agent-docs/styling/palettes.md +3 -3
  561. package/agent-docs/styling/share-images.md +3 -3
  562. package/agent-docs/styling/themes.md +2 -2
  563. package/agent-docs/styling/try.md +2 -2
  564. package/agent-docs/what-is-shoalrun.md +7 -3
  565. package/assets/ask-widget.js +20 -6
  566. package/assets/navigation.js +5 -0
  567. package/dist/api-materialize.d.ts +2 -1
  568. package/dist/api-materialize.js +21 -9
  569. package/dist/api-publication-plan.d.ts +2 -0
  570. package/dist/api-publication-plan.js +23 -7
  571. package/dist/api-publication-review.js +4 -3
  572. package/dist/api-selection.d.ts +5 -2
  573. package/dist/api-selection.js +18 -11
  574. package/dist/artifact-bundle.js +9 -6
  575. package/dist/ask-runtime.d.ts +1 -0
  576. package/dist/ask-runtime.js +7 -2
  577. package/dist/authored-change.js +2 -1
  578. package/dist/authoring-project.js +1 -1
  579. package/dist/cards.js +2 -1
  580. package/dist/cli-discovery.d.ts +2 -2
  581. package/dist/cli-discovery.js +9 -4
  582. package/dist/cli.js +48 -23
  583. package/dist/compiler-config.d.ts +17 -0
  584. package/dist/compiler-config.js +43 -2
  585. package/dist/compiler.d.ts +21 -0
  586. package/dist/compiler.js +16 -12
  587. package/dist/component-transform.d.ts +2 -4
  588. package/dist/component-transform.js +20 -7
  589. package/dist/config.d.ts +1 -0
  590. package/dist/config.js +2 -1
  591. package/dist/content-delivery-contract.d.ts +2 -1
  592. package/dist/content-delivery-validation.d.ts +2 -2
  593. package/dist/content-delivery-validation.js +6 -4
  594. package/dist/content-export-command.d.ts +1 -1
  595. package/dist/content-export-command.js +4 -4
  596. package/dist/content-export-comparison.js +6 -5
  597. package/dist/content-export-config.js +3 -1
  598. package/dist/content-export.js +9 -8
  599. package/dist/content-rest-client.js +4 -2
  600. package/dist/content-rest-contract.d.ts +2 -2
  601. package/dist/content-rest-server.js +11 -6
  602. package/dist/content-source.d.ts +13 -0
  603. package/dist/content-source.js +5 -2
  604. package/dist/content-workspace.d.ts +12 -0
  605. package/dist/content-workspace.js +2 -1
  606. package/dist/content.js +3 -2
  607. package/dist/cookbook-chooser.js +2 -1
  608. package/dist/deployment-profile.d.ts +2 -1
  609. package/dist/deployment-profile.js +38 -8
  610. package/dist/dev.d.ts +3 -1
  611. package/dist/dev.js +99 -12
  612. package/dist/docs-author.js +2 -1
  613. package/dist/docs-command.js +2 -2
  614. package/dist/docs-eval.d.ts +1 -0
  615. package/dist/docs-eval.js +2 -2
  616. package/dist/docs-mcp.d.ts +1 -0
  617. package/dist/docs-mcp.js +10 -5
  618. package/dist/docs-tool.d.ts +4 -10
  619. package/dist/document-sync.d.ts +1 -0
  620. package/dist/document-sync.js +2 -2
  621. package/dist/documentation-core.d.ts +29 -10
  622. package/dist/documentation-core.js +38 -4
  623. package/dist/freshness.js +2 -2
  624. package/dist/frontmatter.js +13 -7
  625. package/dist/function-runtime.d.ts +1 -0
  626. package/dist/index-build.d.ts +1 -0
  627. package/dist/index-build.js +2 -2
  628. package/dist/ingredient-draft.js +20 -10
  629. package/dist/mcp-analytics.d.ts +1 -0
  630. package/dist/mcp-artifacts.js +13 -4
  631. package/dist/mcp-config.d.ts +1 -0
  632. package/dist/mcp-config.js +3 -1
  633. package/dist/mcp-http.js +1 -1
  634. package/dist/page-materialization.d.ts +3 -4
  635. package/dist/page-materialization.js +15 -8
  636. package/dist/page-renderer.d.ts +6 -0
  637. package/dist/page-renderer.js +16 -5
  638. package/dist/project-navigation.js +2 -1
  639. package/dist/publication-identity.d.ts +12 -0
  640. package/dist/publication-identity.js +17 -0
  641. package/dist/publication-manifest.d.ts +24 -1
  642. package/dist/publication-manifest.js +14 -6
  643. package/dist/publication-plan.js +21 -9
  644. package/dist/publication-render.js +24 -8
  645. package/dist/recipe-draft.js +9 -6
  646. package/dist/scaffold.d.ts +7 -4
  647. package/dist/scaffold.js +16 -16
  648. package/dist/search-query.d.ts +4 -10
  649. package/dist/search-query.js +10 -9
  650. package/dist/server.d.ts +8 -0
  651. package/dist/server.js +14 -3
  652. package/dist/subject-deprecation.js +2 -1
  653. package/dist/vercel-function.js +1 -1
  654. package/example-configs/products/README.md +37 -0
  655. package/example-configs/products/content/operations.mdx +50 -0
  656. package/example-configs/products/content/payments-v2.mdx +30 -0
  657. package/example-configs/products/content/payments-v3.mdx +38 -0
  658. package/example-configs/products/content/priority-settlement.mdx +23 -0
  659. package/example-configs/products/content/reporting-v1.mdx +36 -0
  660. package/example-configs/products/content/scheduled-exports.mdx +23 -0
  661. package/example-configs/products/docs.config.yaml +56 -0
  662. package/example-configs/products/profiles/all-releases.yaml +9 -0
  663. package/example-configs/products/profiles/customer-a.yaml +13 -0
  664. package/example-configs/products/profiles/customer-b.yaml +13 -0
  665. package/example-configs/products/skus.yaml +11 -0
  666. package/examples/content-delivery/preview.mjs +1 -1
  667. package/package.json +1 -1
  668. package/schemas/content-export.schema.json +41 -3
  669. package/schemas/content-rest.openapi.json +184 -37
  670. package/skills/shoalrun-author/SKILL.md +6 -2
  671. package/skills/shoalrun-author/references/customer-editions.md +34 -4
  672. package/skills/shoalrun-author/references/publications.md +60 -0
  673. package/skills/shoalrun-recipes/SKILL.md +2 -0
  674. package/skills/shoalrun-setup/SKILL.md +3 -1
  675. package/styles/header.css +3 -0
  676. package/styles/site.css +3 -0
  677. package/agent-docs/publish/content-export.sections/export-selected-pages.md +0 -116
@@ -3,7 +3,7 @@ import { validateSubjectDeprecation } from './subject-deprecation.js';
3
3
  import { validateCardMetadata } from './cards.js';
4
4
  import { resolveTaxonomy, validateTaxonomy, taxonomySchema } from './taxonomy.js';
5
5
  import { validateStandaloneSectionDeclarations } from './section-identity.js';
6
- export const nativePublicFields = new Set(['id', 'title', 'type', 'summary', 'description', 'language', 'locale', 'date', 'updated', 'verified', 'releaseVersion', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'audiences', 'readerFilters', 'tags', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle']);
6
+ export const nativePublicFields = new Set(['id', 'title', 'type', 'summary', 'description', 'language', 'locale', 'date', 'updated', 'verified', 'releaseVersion', 'availability', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'audiences', 'readerFilters', 'tags', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle']);
7
7
  export const protectedMetadataRoots = new Set(['shared', 'requires', 'standaloneSections', 'access', 'seo', 'markdownMetadata', 'variables', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image', 'private', 'internal', 'card', 'displayText', 'publications']);
8
8
  const fieldTypes = new Set(['string', 'number', 'integer', 'boolean', 'object', 'array']);
9
9
  const safePath = (value) => /^[A-Za-z_][A-Za-z0-9_-]*(?:\.[A-Za-z_][A-Za-z0-9_-]*)*$/.test(value);
@@ -33,7 +33,7 @@ export function frontmatterLayers(config = {}) {
33
33
  const layer = config[name] === undefined ? {} : config[name];
34
34
  if (!object(layer))
35
35
  throw new Error(`frontmatter.${name} must be a mapping`);
36
- for (const field of ['id', 'slug', 'shared', 'publications', 'standaloneSections', 'subjectDeprecation', 'change'])
36
+ for (const field of ['id', 'slug', 'shared', 'publications', 'standaloneSections', 'subjectDeprecation', 'change', 'availability'])
37
37
  if (Object.hasOwn(layer, field))
38
38
  throw new Error(`frontmatter.${name}.${field} must stay page-specific`);
39
39
  layers[name] = mergeMetadata({}, layer);
@@ -126,6 +126,11 @@ export function validateFrontmatter(frontmatter, config, file, source) {
126
126
  if (frontmatter.type === 'changelog-entry' &&
127
127
  (mode === 'date' && frontmatter.date === undefined || mode === 'version' && frontmatter.releaseVersion === undefined || mode === 'either' && frontmatter.date === undefined && frontmatter.releaseVersion === undefined))
128
128
  throw new Error(`${file}: changelog-entry pages need ${mode === 'either' ? 'date or releaseVersion' : mode === 'version' ? 'releaseVersion' : 'date'}`);
129
+ if (frontmatter.availability !== undefined) {
130
+ const value = frontmatter.availability;
131
+ if (!object(value) || !Object.keys(value).length || Object.keys(value).some(key => !['since', 'through'].includes(key)) || Object.values(value).some(label => typeof label !== 'string' || !label.trim()))
132
+ throw new Error(`${file}: availability must contain nonempty since and/or through version labels`);
133
+ }
129
134
  if (frontmatter.releaseVersion !== undefined && (typeof frontmatter.releaseVersion !== 'string' || !frontmatter.releaseVersion.trim()))
130
135
  throw new Error(`${file}: releaseVersion must be nonempty text`);
131
136
  for (const field of ['date', 'verified'])
@@ -151,10 +156,10 @@ export function validateFrontmatter(frontmatter, config, file, source) {
151
156
  }
152
157
  if (frontmatter.publications !== undefined) {
153
158
  const publications = frontmatter.publications;
154
- if (!Array.isArray(publications) || !publications.length || publications.some(item => !object(item) || Object.keys(item).some(key => !['channel', 'version'].includes(key)) || typeof item.channel !== 'string' || !item.channel.trim() || typeof item.version !== 'string' || !item.version.trim())) {
159
+ if (!Array.isArray(publications) || !publications.length || publications.some(item => !object(item) || Object.keys(item).some(key => !['product', 'channel', 'version'].includes(key)) || (item.product !== undefined && (typeof item.product !== 'string' || !item.product.trim())) || typeof item.channel !== 'string' || !item.channel.trim() || typeof item.version !== 'string' || !item.version.trim())) {
155
160
  throw new Error(`${file}: publications must list channel and version pairs`);
156
161
  }
157
- const keys = publications.map(item => `${item.channel}|${item.version}`);
162
+ const keys = publications.map(item => `${item.product ?? ''}|${item.channel}|${item.version}`);
158
163
  if (new Set(keys).size !== keys.length)
159
164
  throw new Error(`${file}: publications has duplicate channel/version pairs`);
160
165
  }
@@ -230,14 +235,15 @@ export function frontmatterSchema(config) {
230
235
  date: { type: 'string', format: 'date', description: 'Publication date in YYYY-MM-DD format; optional for release notes and one possible changelog identifier.' },
231
236
  updated: { type: 'string', description: 'Date of the last meaningful page update: YYYY-MM-DD or a timezone-qualified ISO timestamp. Used as sitemap lastmod.' },
232
237
  verified: { type: 'string', format: 'date', description: 'Date someone verified the technical claims; independent of content revision and never assigned by the build.' },
238
+ availability: { type: 'object', minProperties: 1, additionalProperties: false, properties: { since: { type: 'string', minLength: 1, pattern: '\\S' }, through: { type: 'string', minLength: 1, pattern: '\\S' } }, description: 'Inclusive feature availability labels shown beside page dates and retained in Markdown and the document manifest. Does not select or hide publications; labels are not compared or inferred.' },
233
239
  releaseVersion: { type: 'string', minLength: 1, description: 'Release label for a note or changelog entry; separate from the documentation publication version.' },
234
240
  slug: { type: 'string', description: 'Page URL path before channel, version, and language prefixes.' },
235
241
  channel: { type: 'string', description: 'Publication environment, such as sandbox or production; selects an enabled publication and API source.' },
236
242
  version: { type: 'string', description: 'API or documentation edition, such as v1; selects an enabled publication and API source.' },
237
- publications: { type: 'array', minItems: 1, items: { type: 'object', properties: { channel: { type: 'string' }, version: { type: 'string' } }, required: ['channel', 'version'], additionalProperties: false }, description: 'Publish this one page file in each listed channel/version pair. Use instead of page-level channel and version; language stays the same.' },
243
+ publications: { type: 'array', minItems: 1, items: { type: 'object', properties: { product: { type: 'string', minLength: 1 }, channel: { type: 'string' }, version: { type: 'string' } }, required: ['channel', 'version'], additionalProperties: false }, description: 'Publish this one page file in each listed product/channel/version coordinate. Use instead of page-level channel and version; language stays the same.' },
238
244
  language: { type: 'string', description: 'Content language; uses frontmatter defaults/enforced values, then publications.defaults.language, then en.' },
239
245
  locale: { type: 'string', description: 'Formatting conventions used in the content; can inherit a project locale for the page language and can be overridden per page.' },
240
- product: { type: 'string', minLength: 1, description: 'Optional product category. Also selects the product reader facet when that facet is configured.' },
246
+ product: { type: 'string', minLength: 1, description: 'Product publication ID when publications.products is configured; otherwise an optional category and reader facet.' },
241
247
  area: { type: 'string', minLength: 1, description: 'Optional area category. Also selects the area reader facet when that facet is configured.' },
242
248
  subarea: { type: 'string', minLength: 1, description: 'Optional finer category. Also selects the subarea reader facet when that facet is configured.' },
243
249
  operations: { type: 'array', items: { type: 'string' }, description: 'Stable API operation IDs that connect this page to endpoint references and related documents.' },
@@ -326,7 +332,7 @@ export function frontmatterReference(config, sectionsOnly = false) {
326
332
  'Language is the content language and selects a publication. Locale describes formatting conventions in the content and does not select a publication. `frontmatter.locales` can set a project locale for each language; pages may override it.', '',
327
333
  '## Categorize, connect, and present the page', '',
328
334
  'By default, `product`, `area`, and `subarea` are optional, nonempty string categories. They can come from project defaults and appear in the document manifest and search index. A matching configured reader facet makes each category a page filter; without that facet it remains taxonomy only. `operations` links a guide or reference to stable API operation IDs. On a guide or how-to page, `relatedApiReferences` names API reference page IDs to add cross links in both directions within the same publication. Tags help document collections find the page. Card settings change its preview when another page links to it; they do not change the destination. `subjectLifecycle` displays the status of the documented API or feature; `lifecycle` is available for the document\'s editorial state. `tocDepth` limits the HTML page table of contents; use 0 to hide it. `layout` picks the HTML page layout: `docs`, `wide`, `landing`, or `splash`. `showNavigationTabs` overrides the navigation tab bar for this page; landing and splash pages hide it by default. `image` replaces the generated link-preview image. `date` and `releaseVersion` can identify a changelog entry under the project\'s `frontmatter.changelogIdentifier` rule.', '',
329
- ...table, ...nativeRows(['product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'tags', 'date', 'releaseVersion', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle', 'card', 'standaloneSections', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image']), '',
335
+ ...table, ...nativeRows(['availability', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'tags', 'date', 'releaseVersion', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle', 'card', 'standaloneSections', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image']), '',
330
336
  'Projects can opt into built-in category enforcement with `frontmatter.taxonomy`. It declares areas and their allowed subareas, optional required fields, and optional explicit-field requirements for authored pages. Its `multiple` list permits arrays for selected category fields; otherwise each field allows one value. Defaults and enforced values still apply; generated API references use resolved categories. Definitions appear in the document manifest and constrain the generated frontmatter schema. Omit taxonomy or set it to false to preserve optional category behavior.', '',
331
337
  'With `profiles.requireClassification: true`, every public source page in the shared enabled publications needs an explicit `shared: true` or `requires` declaration before customer selection. Defaults do not count. Shared pages may contain feature-specific sections wrapped in `<ForFeature>`; unwrapped text remains shared.', '',
332
338
  '## Control output details', '',
@@ -3,6 +3,7 @@ export type FunctionRuntime = {
3
3
  schemaVersion: 1;
4
4
  settings: Record<string, unknown>;
5
5
  variant?: {
6
+ product?: string;
6
7
  channel: string;
7
8
  version: string;
8
9
  language: string;
@@ -36,6 +36,7 @@ type ManifestDocument = {
36
36
  digest: string;
37
37
  readerFilters?: Record<string, string[]>;
38
38
  variant: {
39
+ product?: string;
39
40
  channel: string;
40
41
  version: string;
41
42
  language: string;
@@ -1,3 +1,4 @@
1
+ import { publicationKey } from './publication-identity.js';
1
2
  import { aiDirectory } from './ai-directory.js';
2
3
  export { aiDirectory } from './ai-directory.js';
3
4
  import { createHash } from 'node:crypto';
@@ -210,8 +211,7 @@ export async function buildChunkIndex(directory, options = {}) {
210
211
  if (!inside(await realpath(file)))
211
212
  throw new Error(`Markdown path for ${document.id} leaves the site directory`);
212
213
  const markdown = await readFile(file, 'utf8');
213
- const { channel, version, language } = document.variant;
214
- chunks.push(...chunkMarkdown(markdown, { ...document, variant: `${channel}|${version}|${language}` }, anchors.get(document.url), options));
214
+ chunks.push(...chunkMarkdown(markdown, { ...document, variant: publicationKey(document.variant) }, anchors.get(document.url), options));
215
215
  }
216
216
  // Generation identity includes publication membership, routes, reader marks,
217
217
  // and prepared search evidence. Embedding digests remain content-only.
@@ -1,3 +1,5 @@
1
+ import { samePublication } from './publication-identity.js';
2
+ import { resolvePublication } from './compiler-config.js';
1
3
  import { createHash } from 'node:crypto';
2
4
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
5
  import path from 'node:path';
@@ -10,13 +12,15 @@ const object = (value) => !!value && typeof value === 'object' && !Array.isArray
10
12
  const digest = (value) => createHash('sha256').update(value).digest('hex');
11
13
  function parseSpec(value) {
12
14
  const fields = ['schemaVersion', 'id', 'title', 'summary', 'slug', 'operation', 'requestExample'];
13
- if (!object(value) || value.schemaVersion !== 1 || Object.keys(value).some(key => ![...fields, 'workflow'].includes(key)))
15
+ if (!object(value) || value.schemaVersion !== 1 || Object.keys(value).some(key => ![...fields, 'workflow', 'publication'].includes(key)))
14
16
  throw new Error('Ingredient spec needs schemaVersion: 1 and only supported fields');
15
17
  for (const field of fields.slice(1))
16
18
  if (typeof value[field] !== 'string' || !value[field].trim())
17
19
  throw new Error(`Ingredient spec needs ${field}`);
18
20
  if (!/^\/[a-z0-9/-]+$/.test(value.slug) || value.slug.includes('//') || value.slug.split('/').includes('..'))
19
21
  throw new Error('Ingredient slug must be a lowercase absolute path');
22
+ if (value.publication !== undefined && (!object(value.publication) || Object.keys(value.publication).some(key => !['product', 'channel', 'version', 'language'].includes(key)) || Object.values(value.publication).some(item => typeof item !== 'string' || !item)))
23
+ throw new Error('Ingredient publication must declare product/channel/version/language strings');
20
24
  const workflow = ingredientWorkflow(value.workflow, 'Ingredient workflow');
21
25
  return { ...value, ...(workflow ? { workflow } : {}) };
22
26
  }
@@ -39,10 +43,20 @@ export async function renderIngredientDraft(configFile, specFile) {
39
43
  if (matching.length !== 1)
40
44
  throw new Error(`Ingredient operation ${spec.operation} must name one explicitly configured API operation`);
41
45
  const { apiId, api, operation } = matching[0];
42
- if (api.source?.kind !== 'file' || typeof api.source.path !== 'string')
43
- throw new Error(`Ingredient operation ${spec.operation} needs a local OpenAPI source in the default publication`);
44
- const origin = explain(loaded, `apis.${apiId}.source.path`).source.file;
45
- const source = path.resolve(path.dirname(origin), api.source.path);
46
+ const defaults = config.publications?.defaults ?? {};
47
+ const product = config.publications.products ? spec.publication?.product ?? api.product ?? defaults.product : undefined;
48
+ const publication = resolvePublication(config.publications, { ...defaults, ...spec.publication, ...(product ? { product, version: spec.publication?.version } : {}) }, defaultLanguage(config));
49
+ const publicationIndex = api.publications?.findIndex((item) => item.product === publication.product && item.channel === publication.channel && item.version === publication.version) ?? -1;
50
+ const defaultSourcePublication = api.source ? resolvePublication(config.publications, { ...defaults, ...(config.publications.products && api.product ? { product: api.product, version: undefined } : {}) }, defaultLanguage(config)) : undefined;
51
+ const binding = publicationIndex >= 0 ? api.publications[publicationIndex].source : defaultSourcePublication && publication.product === defaultSourcePublication.product && publication.channel === defaultSourcePublication.channel && publication.version === defaultSourcePublication.version ? api.source : undefined;
52
+ if (!config.publications.enabled?.some((item) => samePublication(resolvePublication(config.publications, item, defaultLanguage(config)), publication)))
53
+ throw new Error('Ingredient publication is not enabled');
54
+ if (publicationIndex < 0 && config.publications.products && publication.product !== (api.product ?? defaults.product))
55
+ throw new Error('Ingredient needs an OpenAPI source for its selected product');
56
+ if (binding?.kind !== 'file' || typeof binding.path !== 'string')
57
+ throw new Error(`Ingredient operation ${spec.operation} needs a local OpenAPI source in the selected publication`);
58
+ const origin = explain(loaded, publicationIndex >= 0 ? `apis.${apiId}.publications.${publicationIndex}.source.path` : `apis.${apiId}.source.path`).source.file;
59
+ const source = path.resolve(path.dirname(origin), binding.path);
46
60
  const reader = new ApiReader(root);
47
61
  const details = await reader.operation(source, operation.sourceOperationId, spec.operation);
48
62
  const sourceDigest = digest((await Promise.all([...reader.dependencies].sort().map(async (file) => `${path.relative(root, file)}\n${await readFile(file, 'utf8')}`))).join('\n'));
@@ -52,13 +66,9 @@ export async function renderIngredientDraft(configFile, specFile) {
52
66
  if (requests.length !== 1 || !requests[0].curl)
53
67
  throw new Error(`Request example ${spec.requestExample} needs one inline example with a generated cURL command`);
54
68
  const response = details.examples.find(example => example.location === 'response' && /^2\d\d$/.test(example.status ?? '') && example.value !== undefined);
55
- const defaults = config.publications?.defaults ?? {};
56
- if (!defaults.channel || !defaults.version)
57
- throw new Error('Ingredient draft needs a default channel and version');
58
- const language = defaults.language ?? defaultLanguage(config);
59
69
  const header = {
60
70
  id: spec.id, title: spec.title, summary: spec.summary, type: 'ingredient', slug: spec.slug,
61
- channel: defaults.channel, version: defaults.version, language,
71
+ ...publication,
62
72
  operations: [spec.operation], access: { policy: 'draft' }, ...(spec.workflow ? { workflow: spec.workflow } : {})
63
73
  };
64
74
  const reference = operation.reference ? `[${details.method.toUpperCase()} ${details.route}](doc:${operation.reference})` : `\`${details.method.toUpperCase()} ${details.route}\``;
@@ -10,6 +10,7 @@ export type McpAnalyticsEvent = McpClientMetadata & {
10
10
  sectionId?: string;
11
11
  buildId: string;
12
12
  publication: {
13
+ product?: string;
13
14
  channel: string;
14
15
  version: string;
15
16
  language: string;
@@ -1,3 +1,4 @@
1
+ import { publicationKey, samePublication } from './publication-identity.js';
1
2
  import { mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises';
2
3
  import os from 'node:os';
3
4
  import path from 'node:path';
@@ -10,8 +11,8 @@ export async function addMcpArtifacts(artifacts, config, manifest, rendered, hea
10
11
  if (!mcp)
11
12
  return;
12
13
  const endpoint = `${manifest.basePath}${mcp.path}`;
13
- const variant = ['channel', 'version', 'language'].map(key => mcp.publication[key]).join('|');
14
- const selected = rendered.filter(page => ['channel', 'version', 'language'].every(key => page.doc.variant[key] === mcp.publication[key]));
14
+ const variant = publicationKey(mcp.publication);
15
+ const selected = rendered.filter(page => samePublication(page.doc.variant, mcp.publication));
15
16
  if (!selected.length || selected.some(page => page.doc.frontmatter.access?.policy !== 'public'))
16
17
  throw new Error('mcp.publication must select nonempty, normally published public documentation');
17
18
  for (const artifact of artifacts.keys()) {
@@ -24,7 +25,7 @@ export async function addMcpArtifacts(artifacts, config, manifest, rendered, hea
24
25
  }
25
26
  if (manifest.redirects.some((r) => r.from === endpoint || r.markdownFrom === endpoint))
26
27
  throw new Error('MCP endpoint conflicts with a redirect');
27
- const docs = manifest.documents.filter((doc) => ['channel', 'version', 'language'].every(key => doc.variant[key] === mcp.publication[key]));
28
+ const docs = manifest.documents.filter((doc) => samePublication(doc.variant, mcp.publication));
28
29
  const inventory = {};
29
30
  const put = (file, value) => {
30
31
  artifacts.set(`${mcpDataPath}/${file}`, value);
@@ -38,7 +39,15 @@ export async function addMcpArtifacts(artifacts, config, manifest, rendered, hea
38
39
  }) };
39
40
  if (search.documents.some(doc => doc.variant !== variant))
40
41
  throw new Error('MCP search publication mismatch');
41
- put('documents.json', JSON.stringify({ schemaVersion: 1, documents: docs }));
42
+ const catalog = mcp.publication.product === undefined ? undefined : manifest.publications?.products?.[mcp.publication.product];
43
+ const scopedProducts = catalog && mcp.publication.product ? { [mcp.publication.product]: {
44
+ ...(typeof catalog.label === 'string' ? { label: catalog.label } : {}),
45
+ ...(catalog.defaultVersion === mcp.publication.version ? { defaultVersion: catalog.defaultVersion } : {}),
46
+ versions: [mcp.publication.version],
47
+ } } : undefined;
48
+ put('documents.json', JSON.stringify({ schemaVersion: 1, documents: docs,
49
+ ...(manifest.publications ? { publications: { enabled: [{ ...mcp.publication }], ...(scopedProducts ? { products: scopedProducts } : {}) } } : {}),
50
+ }));
42
51
  put('search-index.json', JSON.stringify(search));
43
52
  for (const doc of docs)
44
53
  for (const resource of [doc, ...doc.sections]) {
@@ -3,6 +3,7 @@ export type McpConfig = {
3
3
  access: 'public';
4
4
  path: string;
5
5
  publication: {
6
+ product?: string;
6
7
  channel: string;
7
8
  version: string;
8
9
  language: string;
@@ -15,8 +15,10 @@ export function resolveMcp(value) {
15
15
  if (typeof route !== 'string' || !/^\/[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/.test(route) || route.startsWith('/__shoalrun'))
16
16
  throw new Error('mcp.path must be a non-reserved absolute path without a trailing slash');
17
17
  const publication = configMappingAt(config.publication, 'mcp.publication');
18
- if (Object.keys(publication).some(key => !['channel', 'version', 'language'].includes(key)) || ['channel', 'version', 'language'].some(key => typeof publication[key] !== 'string' || !/^[a-zA-Z0-9._-]{1,128}$/.test(publication[key])))
18
+ if (Object.keys(publication).some(key => !['product', 'channel', 'version', 'language'].includes(key)) || ['channel', 'version', 'language'].some(key => typeof publication[key] !== 'string' || !/^[a-zA-Z0-9._-]{1,128}$/.test(publication[key])))
19
19
  throw new Error('mcp.publication needs channel, version, and language');
20
+ if (publication.product !== undefined && (typeof publication.product !== 'string' || !/^[a-zA-Z0-9._-]{1,128}$/.test(publication.product)))
21
+ throw new Error('mcp.publication.product must be a product ID');
20
22
  const strings = (key) => {
21
23
  const values = config[key] ?? [];
22
24
  if (!Array.isArray(values) || values.length > 32 || values.some(v => typeof v !== 'string' || !v || v.length > 253))
package/dist/mcp-http.js CHANGED
@@ -18,7 +18,7 @@ export async function loadMcpRuntime(directory) {
18
18
  throw error;
19
19
  }
20
20
  const runtime = JSON.parse(raw);
21
- if (runtime.schemaVersion !== 1 || runtime.access !== 'public' || runtime.enabled !== true || runtime.dataDirectory !== mcpDataPath.slice(1) || !hex(runtime.buildId) || !hex(runtime.corpusDigest) || !runtime.inventory || Array.isArray(runtime.inventory) || fingerprint(JSON.stringify(runtime.inventory)) !== runtime.corpusDigest || !runtime.publication || ['channel', 'version', 'language'].some(key => typeof runtime.publication[key] !== 'string') || !Array.isArray(runtime.allowedHosts) || !Array.isArray(runtime.allowedOrigins) || typeof runtime.path !== 'string' || !/^\/[a-zA-Z0-9_/-]+$/.test(runtime.path))
21
+ if (runtime.schemaVersion !== 1 || runtime.access !== 'public' || runtime.enabled !== true || runtime.dataDirectory !== mcpDataPath.slice(1) || !hex(runtime.buildId) || !hex(runtime.corpusDigest) || !runtime.inventory || Array.isArray(runtime.inventory) || fingerprint(JSON.stringify(runtime.inventory)) !== runtime.corpusDigest || !runtime.publication || (runtime.publication.product !== undefined && (typeof runtime.publication.product !== 'string' || !runtime.publication.product)) || ['channel', 'version', 'language'].some(key => typeof runtime.publication[key] !== 'string') || !Array.isArray(runtime.allowedHosts) || !Array.isArray(runtime.allowedOrigins) || typeof runtime.path !== 'string' || !/^\/[a-zA-Z0-9_/-]+$/.test(runtime.path))
22
22
  throw new Error('Invalid MCP runtime metadata; rebuild the public site');
23
23
  if (runtime.analytics?.consent)
24
24
  resolveMcp({ enabled: true, access: 'public', publication: runtime.publication, analytics: { ...runtime.analytics, module: './adapter.mjs' } });
@@ -9,6 +9,7 @@ import type { SnippetDefinition, SnippetUse } from './snippets.js';
9
9
  import type { ReaderFiltersConfig } from './reader-filters.js';
10
10
  import type { resolveCalloutTypes } from './callouts.js';
11
11
  import type { resolveBadgeVariants } from './badges.js';
12
+ import type { CompilerPublicationsConfig } from './compiler-config.js';
12
13
  type ApiPlan = Awaited<ReturnType<typeof materializeApiReferences>>;
13
14
  type SourceBinding = NonNullable<ReturnType<ApiPlan['sourceForVariant']>>;
14
15
  export type MaterializedPage = {
@@ -25,10 +26,7 @@ export type MaterializedPage = {
25
26
  export declare function materializePages({ variables, frontmatterConfig, publications, docs, linkDocuments, apiPlan, sourceForOperation, snippets, calloutTypes, badgeVariants, componentPlugins, readerFilters, base, publicPath, relatedApiTargets, guidesByApi }: {
26
27
  variables: Record<string, unknown>;
27
28
  frontmatterConfig: unknown;
28
- publications: {
29
- channels: Record<string, unknown>;
30
- versions: Record<string, unknown>;
31
- };
29
+ publications: CompilerPublicationsConfig;
32
30
  docs: Map<string, Document>;
33
31
  linkDocuments?: Map<string, Document>;
34
32
  apiPlan: ApiPlan;
@@ -67,6 +65,7 @@ export declare function materializePages({ variables, frontmatterConfig, publica
67
65
  operations: Record<string, {
68
66
  id: string;
69
67
  type: string;
68
+ product?: string;
70
69
  channel: string;
71
70
  version: string;
72
71
  language: string;
@@ -1,3 +1,4 @@
1
+ import { documentKey, publicationKey } from './publication-identity.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import path from 'node:path';
3
4
  import { resolveApiEmbedTree } from './api-embeds.js';
@@ -7,7 +8,7 @@ import { isConfigMapping } from './compiler-config.js';
7
8
  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';
8
9
  const generatedWebhookBody = 'This webhook reference is generated from the OpenAPI description. The provider sends this event to the receiver.\n';
9
10
  const digest = (value) => createHash('sha256').update(value).digest('hex');
10
- const keyFor = (id, variant) => `${id}|${variant.channel}|${variant.version}|${variant.language}`;
11
+ const keyFor = documentKey;
11
12
  export async function materializePages({ variables, frontmatterConfig, publications, docs, linkDocuments = docs, apiPlan, sourceForOperation, snippets, calloutTypes, badgeVariants, componentPlugins, readerFilters, base, publicPath, relatedApiTargets, guidesByApi }) {
12
13
  const { api, queryRules, lifecycleMappings, extensionValue, sourceForVariant, knownOperations } = apiPlan;
13
14
  const apiPublications = new Map();
@@ -28,7 +29,7 @@ export async function materializePages({ variables, frontmatterConfig, publicati
28
29
  if (keyFor(other.frontmatter.id, doc.variant) === keyFor(other.frontmatter.id, other.variant))
29
30
  local.set(other.frontmatter.id, other);
30
31
  const parsed = parse.parse(doc.body);
31
- const tree = await resolveApiEmbedTree(transformMdx(parsed, doc, local, snippets, variables, snippetUses, calloutTypes, base, readerFilters, frontmatterConfig, publications, badgeVariants, componentPlugins), api, operationId => sourceForOperation(operationId, doc.variant), apiId => {
32
+ const tree = await resolveApiEmbedTree(transformMdx(parsed, doc, local, snippets, variables, snippetUses, calloutTypes, base, readerFilters, frontmatterConfig, publications, badgeVariants, componentPlugins, linkDocuments), api, operationId => sourceForOperation(operationId, doc.variant), apiId => {
32
33
  if (doc.featureContext?.grants)
33
34
  throw new Error('Standalone API schema embeds require an explicitly scoped source and are not supported in profiled builds; select an operation instead');
34
35
  const definition = apiPlan.apiDefinitions[apiId];
@@ -63,7 +64,7 @@ export async function materializePages({ variables, frontmatterConfig, publicati
63
64
  const mapped = mapping && (typeof rawLifecycle === 'string' || typeof rawLifecycle === 'number' || typeof rawLifecycle === 'boolean') && Object.hasOwn(mapping.values, String(rawLifecycle)) ? mapping.values[String(rawLifecycle)] : undefined;
64
65
  if (mapped && !generated.deprecated && !doc.frontmatter.subjectLifecycle)
65
66
  doc.frontmatter.subjectLifecycle = mapped;
66
- const navVariant = `${doc.variant.channel}|${doc.variant.version}|${doc.variant.language}`;
67
+ const navVariant = publicationKey(doc.variant);
67
68
  const entries = navigationEntries.get(navVariant) ?? [];
68
69
  entries.push({ id: operationId, apiId: binding.apiId, documentId: doc.frontmatter.id, title: doc.frontmatter.title, tag: generated.tags[0] ?? (generated.webhook ? 'Webhooks' : 'Other'), search: `${generated.webhook ? 'webhook' : generated.method.toUpperCase()} ${generated.route} ${binding.sourceOperationId} ${operationId}` });
69
70
  navigationEntries.set(navVariant, entries);
@@ -84,7 +85,7 @@ export async function materializePages({ variables, frontmatterConfig, publicati
84
85
  pageCurl = generated.curl;
85
86
  pageSamples = generated.samples;
86
87
  if (source.focused === true || source.publish === true) {
87
- const coordinates = [doc.variant.channel, doc.variant.version, doc.variant.language];
88
+ const coordinates = [...(doc.variant.product ? [doc.variant.product] : []), doc.variant.channel, doc.variant.version, doc.variant.language];
88
89
  if (coordinates.some(value => !/^[A-Za-z0-9._-]+$/.test(value)))
89
90
  throw new Error(`${doc.file}: unsafe publication coordinate for focused contract`);
90
91
  const name = operationId.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 70) || 'operation';
@@ -105,11 +106,17 @@ export async function materializePages({ variables, frontmatterConfig, publicati
105
106
  const extension = path.extname(sourceFile).toLowerCase();
106
107
  if (!['.yaml', '.yml', '.json'].includes(extension))
107
108
  throw new Error(`Published API source needs YAML or JSON extension: ${sourceFile}`);
108
- const sourceUrl = publicPath(`/api/${id}/${doc.variant.channel}/${doc.variant.version}/${path.basename(sourceFile)}`);
109
+ const sourceUrl = publicPath(`/api/${id}/${doc.variant.product ? `${doc.variant.product}/` : ''}${doc.variant.channel}/${doc.variant.version}/${path.basename(sourceFile)}`);
109
110
  const endpoint = (publicationIndex >= 0 ? binding.definition.publications?.[publicationIndex].discovery?.endpoint : undefined) ?? binding.definition.discovery?.endpoint;
110
- const recordKey = `${id}|${doc.variant.channel}|${doc.variant.version}`;
111
- if (!apiPublications.has(recordKey))
112
- apiPublications.set(recordKey, { apiId: id, variant: doc.variant, sourceFile, endpoint, referenceUrl: doc.route, sourceUrl, mediaType: extension === '.json' ? 'application/json' : 'application/yaml' });
111
+ // Source contracts are shared across documentation languages. Keep the
112
+ // legacy productless identity and publish each source URL only once.
113
+ const recordKey = `${id}|${doc.variant.channel}|${doc.variant.version}${doc.variant.product ? `|${doc.variant.product}` : ''}`;
114
+ const mediaType = extension === '.json' ? 'application/json' : 'application/yaml';
115
+ const previous = apiPublications.get(recordKey);
116
+ if (previous && (previous.sourceFile !== sourceFile || previous.sourceUrl !== sourceUrl || previous.endpoint !== endpoint || previous.mediaType !== mediaType))
117
+ throw new Error(`Conflicting published OpenAPI source for ${recordKey}`);
118
+ if (!previous)
119
+ apiPublications.set(recordKey, { apiId: id, variant: doc.variant, sourceFile, endpoint, referenceUrl: doc.route, sourceUrl, mediaType });
113
120
  }
114
121
  }
115
122
  for (const operationId of doc.frontmatter.operations ?? []) {
@@ -52,6 +52,12 @@ export type PageShell = {
52
52
  header?: HeaderConfig;
53
53
  footer?: FooterConfig;
54
54
  search?: boolean;
55
+ publicationChoices?: Array<{
56
+ label: string;
57
+ group: string;
58
+ url: string;
59
+ current: boolean;
60
+ }>;
55
61
  publicationAlternates?: Array<{
56
62
  label: string;
57
63
  url: string;
@@ -1,3 +1,4 @@
1
+ import { publicationKey } from './publication-identity.js';
1
2
  import { resolveAgentDiscovery } from './agent-discovery.js';
2
3
  import { navigationCounts, navigationHeading } from './compiler-config.js';
3
4
  import { navigationTab } from './project-navigation.js';
@@ -6,7 +7,14 @@ import { readerFilterAttribute } from './reader-filters.js';
6
7
  import { surfaceText } from './surface-text.js';
7
8
  import { normalizeBasePath, sitePath } from './site-path.js';
8
9
  import { renderHtmlWithHeadings } from './html-renderer.js';
9
- const variantKey = (variant) => `${variant.channel}|${variant.version}|${variant.language}`;
10
+ const variantKey = publicationKey;
11
+ function publicationPicker(shell, esc) {
12
+ const choices = shell.publicationChoices ?? [];
13
+ if (!choices.length)
14
+ return '';
15
+ const groups = [...new Set(choices.map(item => item.group))];
16
+ return `<select class="publication-picker" data-publication-switcher aria-label="Publication">${groups.map(group => `<optgroup label="${esc(group)}">${choices.filter(item => item.group === group).map(item => `<option value="${esc(item.url)}"${item.current ? ' selected' : ''}>${esc(item.label)}</option>`).join('')}</optgroup>`).join('')}</select><noscript><nav aria-label="Publications">${choices.map(item => `<a href="${esc(item.url)}">${esc(item.label)}</a>`).join(' ')}</nav></noscript>`;
17
+ }
10
18
  // Header search is revealed by search.js; without scripts the sidebar filter still works.
11
19
  function readerFilterSlot(control, esc) {
12
20
  return `<div class="reader-filter-slot" data-reader-filter="${esc(JSON.stringify(control))}"></div>`;
@@ -14,7 +22,7 @@ function readerFilterSlot(control, esc) {
14
22
  function headerTools(shell, variant, esc, readerConfig) {
15
23
  const header = shell.header ?? { links: [] };
16
24
  const alternates = shell.publicationAlternates ?? [];
17
- const switcher = alternates.length > 1 ? `<nav class="publication-switcher" aria-label="Switch documentation version"><details><summary><span>Version</span><strong>${esc(alternates.find(item => item.current)?.label ?? '')}</strong></summary><ul>${alternates.map(item => `<li><a href="${esc(item.url)}"${item.current ? ' aria-current="page"' : ''}>${esc(item.label)}</a></li>`).join('')}</ul></details></nav>` : '';
25
+ const switcher = !shell.publicationChoices?.length && alternates.length > 1 ? `<nav class="publication-switcher" aria-label="Switch documentation version"><details><summary><span>Version</span><strong>${esc(alternates.find(item => item.current)?.label ?? '')}</strong></summary><ul>${alternates.map(item => `<li><a href="${esc(item.url)}"${item.current ? ' aria-current="page"' : ''}>${esc(item.label)}</a></li>`).join('')}</ul></details></nav>` : '';
18
26
  const search = shell.search ? `<div class="site-search" data-variant="${esc(variantKey(variant))}" hidden><label class="site-search-label" for="site-search-input">Search documentation</label><input id="site-search-input" type="search" role="combobox" autocomplete="off" spellcheck="false" aria-autocomplete="list" aria-expanded="false" aria-controls="site-search-results"><kbd class="site-search-key" aria-hidden="true">/</kbd><ul id="site-search-results" class="site-search-results" role="listbox" aria-label="Search results" hidden></ul><p class="site-search-status" role="status"></p></div>` : '';
19
27
  const links = header.links.length ? `<nav class="header-actions" aria-label="Site links">${header.links.map(link => `<a class="header-${link.style}" href="${esc(link.href)}"${/^https?:/.test(link.href) ? ' rel="noopener"' : ''}>${esc(link.label)}</a>`).join('')}</nav>` : '';
20
28
  const toggle = shell.toggle ? `<button type="button" class="mode-toggle" aria-pressed="false" hidden><span class="mode-toggle-label">Dark mode</span><svg class="mode-icon-light" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg><svg class="mode-icon-dark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg></button>` : '';
@@ -85,10 +93,13 @@ export function buildHtmlPage(doc, tree, markdownUrl, siteTitle, navigation, exa
85
93
  const updated = doc.frontmatter.updated && !(changelogEntry && doc.frontmatter.date) ? `<span class="page-date">Updated <time datetime="${esc(doc.frontmatter.updated)}">${esc(doc.frontmatter.updated.slice(0, 10))}</time></span>` : '';
86
94
  const verified = doc.frontmatter.verified && doc.frontmatter.showVerified !== false ? `<span class="page-date">Verified <time datetime="${esc(doc.frontmatter.verified)}">${esc(doc.frontmatter.verified)}</time></span>` : '';
87
95
  const releaseVersion = doc.frontmatter.releaseVersion ? `<span class="page-version">Version ${esc(doc.frontmatter.releaseVersion)}</span>` : '';
88
- const pageDates = changelogEntry ? `<div class="page-meta">${date}${updated}${verified}${releaseVersion}</div>` : `${date}${updated}${verified}${releaseVersion}`;
96
+ const availability = doc.frontmatter.availability;
97
+ const availabilityLabels = availability ? `${availability.since ? `<span class="page-version" data-availability="since">Since ${esc(availability.since)}</span>` : ''}${availability.through ? `<span class="page-version" data-availability="through">Through ${esc(availability.through)}</span>` : ''}` : '';
98
+ const metadata = `${date}${updated}${verified}${releaseVersion}${availabilityLabels}`;
99
+ const pageDates = metadata ? `<div class="page-meta">${metadata}</div>` : '';
89
100
  const containsCurrent = (item) => item.route === doc.route || !!item.items?.some(containsCurrent);
90
101
  const activeTab = navigationTab(navigation, doc.route);
91
- const analyticsBootstrap = config.analytics ? `<script type="application/json" id="analytics-config">${JSON.stringify({ pageId: doc.frontmatter.id, pageUrl: doc.route, documentType: doc.frontmatter.type, channel: doc.variant.channel, version: doc.variant.version, language: doc.variant.language, ...(activeTab ? { navigationSectionId: activeTab.id } : {}) }).replaceAll('<', '\\u003c')}</script><script type="module" src="/assets/analytics.js"></script>` : '';
102
+ const analyticsBootstrap = config.analytics ? `<script type="application/json" id="analytics-config">${JSON.stringify({ pageId: doc.frontmatter.id, pageUrl: doc.route, documentType: doc.frontmatter.type, ...doc.variant, ...(activeTab ? { navigationSectionId: activeTab.id } : {}) }).replaceAll('<', '\\u003c')}</script><script type="module" src="/assets/analytics.js"></script>` : '';
92
103
  const pageLayout = doc.frontmatter.layout ?? 'docs';
93
104
  const showNavigationTabs = doc.frontmatter.showNavigationTabs ?? (pageLayout === 'docs' || pageLayout === 'wide');
94
105
  const sectionLinks = navigation.filter(node => node.tab).map(node => `<a href="${esc(node.route)}"${node === activeTab ? ' aria-current="true"' : ''}>${esc(node.label)}</a>`).join('');
@@ -176,6 +187,6 @@ export function buildHtmlPage(doc, tree, markdownUrl, siteTitle, navigation, exa
176
187
  const menu = side || sectionNavigation ? `<a class="mobile-menu" href="#${side ? 'docs-navigation' : 'docs-sections'}">Menu</a>` : '';
177
188
  const rail = toc || panel ? `<aside class="page-rail">${doc.endpoint ? `${panel}${toc}` : `${toc}${panel}`}</aside>` : '';
178
189
  const breadcrumbs = (shell.breadcrumbs?.length ?? 0) > 1 && !hero ? `<nav class="doc-breadcrumbs" aria-label="Breadcrumb"><ol>${shell.breadcrumbs.map((item, index) => `<li>${index === shell.breadcrumbs.length - 1 ? `<span aria-current="page">${esc(item.label)}</span>` : item.url ? `<a href="${esc(item.url)}">${esc(item.label)}</a>` : `<span>${esc(item.label)}</span>`}</li>`).join('')}</ol></nav>` : '';
179
- const markup = `<!doctype html><html lang="${esc(doc.variant.language)}"${shell.themeCss || shell.paletteCss ? ` data-theme="${esc(shell.preset ?? 'shoal')}" data-palette="${esc(shell.palette ?? '')}"` : ''}${shell.masthead ? ` data-masthead="${esc(shell.masthead)}"` : ''}${layout === 'docs' ? '' : ` data-layout="${layout}"`}><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="${shell.mode === 'system' ? 'light dark' : shell.mode ?? 'light'}">${shell.indexing === false || doc.frontmatter.seo?.noindex === true ? '<meta name="robots" content="noindex">' : ''}${shell.origin ? `<link rel="canonical" href="${esc(absolute(doc.route))}">` : ''}${shell.toggle ? '<script src="/assets/mode.js"></script>' : ''}<title>${esc(String(title))}</title>${description ? `<meta name="description" content="${esc(String(description))}">` : ''}${socialDescription ? `<meta property="og:description" content="${esc(socialDescription)}">` : ''}${social}<link rel="alternate" type="text/markdown" href="${esc(markdownUrl)}"><link rel="describedby" href="/llms.min.txt" title="Documentation index">${icons}${shell.preloadFont ? `<link rel="preload" href="/assets/fonts/${esc(shell.preloadFont)}" as="font" type="font/woff2" crossorigin>` : ''}<link rel="stylesheet" href="/assets/site.css">${article.includes('data-theme-preview') ? '<link rel="stylesheet" href="/assets/theme-preview.css">' : ''}${shell.themeCss ? '<link rel="stylesheet" href="/assets/theme.css" data-theme-link="theme">' : ''}${shell.paletteCss ? '<link rel="stylesheet" href="/assets/palette.css" data-theme-link="palette">' : ''}${shell.badgesCss ? '<link rel="stylesheet" href="/assets/badges.css">' : ''}${shell.themeSwitcher ? `<script src="/assets/theme-switcher.js" data-themes="${esc(shell.themeSwitcher)}"></script>` : ''}${shell.fontsCss ? '<link rel="stylesheet" href="/assets/fonts.css">' : ''}${customCss ? '<link rel="stylesheet" href="/assets/project.css">' : ''}</head><body><a class="skip" href="#main">Skip to content</a>${agent.mode === 'disclosure' ? '' : agentBlock}<header class="mast"><div class="mast-inner">${shell.home ? `<a class="${brandClass}" href="/">${brand}</a>` : `<span class="${brandClass}">${brand}</span>`}${editionLabel && (shell.publicationAlternates?.length ?? 0) < 2 ? `<span class="edition">${esc(editionLabel)}</span>` : ''}${menu}${headerTools(shell, doc.variant, esc, readerConfig)}${agent.mode === 'disclosure' ? agentBlock : ''}</div></header>${sectionNavigation}${shortcuts}<div class="layout${layout === 'docs' ? '' : ` layout-${layout}`}${rail ? ' has-rail' : ''}${panel ? ' has-examples' : ''}${doc.endpoint ? ' api-reference' : ''}"><main id="main" class="content" tabindex="-1" data-document-type="${esc(doc.frontmatter.type)}"${readerConfig ? ` data-reader-page="${esc(readerFilterAttribute(doc.readerFilters ?? {}))}"` : ''}>${breadcrumbs}${hero ? '' : `<header class="page-head"><span class="eyebrow">${esc(typeLabel(doc.frontmatter.type))}</span>${doc.endpoint ? '' : badge(doc.frontmatter.subjectLifecycle)}<h1>${esc(doc.frontmatter.title)}${doc.endpoint ? badge(doc.frontmatter.subjectLifecycle) : ''}</h1>${pageHeader && !routeSummary ? `<p class="summary">${esc(pageHeader)}</p>` : ''}${pageDates}${endpoint}${audienceBadges}</header>`}${hero ? '' : `<div class="page-formats"><a class="formats" href="${esc(markdownUrl)}">Read as Markdown</a><button type="button" class="formats" data-copy-markdown hidden>Copy as Markdown</button><span role="status" data-copy-markdown-status></span></div>`}${toc ? '<div class="mobile-outline-slot"></div>' : ''}${jumps}${readerBanner}<article>${article}</article></main>${rail}${side}</div>${footer}${analyticsBootstrap}${readerBootstrap}<script type="module" src="/assets/copy-markdown.js"></script><script type="module" src="/assets/navigation.js"></script><script type="module" src="/assets/reader.js"></script><script type="module" src="/assets/tabs.js"></script>${shell.search ? '<script type="module" src="/assets/search.js"></script>' : ''}${article.includes('data-tooltip') ? '<script type="module" src="/assets/tooltips.js"></script>' : ''}${article.includes('data-component-module') ? '<script type="module" src="/assets/components.js"></script>' : ''}${article.includes('data-file-tree') ? '<script type="module" src="/assets/file-tree.js"></script>' : ''}${article.includes('data-image-expand') ? '<script type="module" src="/assets/image-viewer.js"></script>' : ''}${article.includes('data-table-filter') || article.includes('data-definition-filter') ? '<script type="module" src="/assets/table-filter.js"></script>' : ''}${article.includes('data-walkthrough') ? '<script type="module" src="/assets/walkthrough.js"></script>' : ''}${article.includes('data-cookbook-chooser') ? '<script type="module" src="/assets/cookbook-chooser.js"></script>' : ''}${article.includes('data-theme-preview') ? '<script type="module" src="/assets/theme-preview.js"></script>' : ''}${panel ? '<script type="module" src="/assets/example-panel.js"></script>' : ''}${panel.includes('data-code-samples') ? '<script type="module" src="/assets/code-samples.js"></script>' : ''}</body></html>`;
190
+ const markup = `<!doctype html><html lang="${esc(doc.variant.language)}"${shell.themeCss || shell.paletteCss ? ` data-theme="${esc(shell.preset ?? 'shoal')}" data-palette="${esc(shell.palette ?? '')}"` : ''}${shell.masthead ? ` data-masthead="${esc(shell.masthead)}"` : ''}${layout === 'docs' ? '' : ` data-layout="${layout}"`}><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="${shell.mode === 'system' ? 'light dark' : shell.mode ?? 'light'}">${shell.indexing === false || doc.frontmatter.seo?.noindex === true ? '<meta name="robots" content="noindex">' : ''}${shell.origin ? `<link rel="canonical" href="${esc(absolute(doc.route))}">` : ''}${shell.toggle ? '<script src="/assets/mode.js"></script>' : ''}<title>${esc(String(title))}</title>${description ? `<meta name="description" content="${esc(String(description))}">` : ''}${socialDescription ? `<meta property="og:description" content="${esc(socialDescription)}">` : ''}${social}<link rel="alternate" type="text/markdown" href="${esc(markdownUrl)}"><link rel="describedby" href="/llms.min.txt" title="Documentation index">${icons}${shell.preloadFont ? `<link rel="preload" href="/assets/fonts/${esc(shell.preloadFont)}" as="font" type="font/woff2" crossorigin>` : ''}<link rel="stylesheet" href="/assets/site.css">${article.includes('data-theme-preview') ? '<link rel="stylesheet" href="/assets/theme-preview.css">' : ''}${shell.themeCss ? '<link rel="stylesheet" href="/assets/theme.css" data-theme-link="theme">' : ''}${shell.paletteCss ? '<link rel="stylesheet" href="/assets/palette.css" data-theme-link="palette">' : ''}${shell.badgesCss ? '<link rel="stylesheet" href="/assets/badges.css">' : ''}${shell.themeSwitcher ? `<script src="/assets/theme-switcher.js" data-themes="${esc(shell.themeSwitcher)}"></script>` : ''}${shell.fontsCss ? '<link rel="stylesheet" href="/assets/fonts.css">' : ''}${customCss ? '<link rel="stylesheet" href="/assets/project.css">' : ''}</head><body><a class="skip" href="#main">Skip to content</a>${agent.mode === 'disclosure' ? '' : agentBlock}<header class="mast"><div class="mast-inner">${shell.home ? `<a class="${brandClass}" href="/">${brand}</a>` : `<span class="${brandClass}">${brand}</span>`}${publicationPicker(shell, esc)}${editionLabel && !shell.publicationChoices?.length && (shell.publicationAlternates?.length ?? 0) < 2 ? `<span class="edition">${esc(editionLabel)}</span>` : ''}${menu}${headerTools(shell, doc.variant, esc, readerConfig)}${agent.mode === 'disclosure' ? agentBlock : ''}</div></header>${sectionNavigation}${shortcuts}<div class="layout${layout === 'docs' ? '' : ` layout-${layout}`}${rail ? ' has-rail' : ''}${panel ? ' has-examples' : ''}${doc.endpoint ? ' api-reference' : ''}"><main id="main" class="content" tabindex="-1" data-document-type="${esc(doc.frontmatter.type)}"${readerConfig ? ` data-reader-page="${esc(readerFilterAttribute(doc.readerFilters ?? {}))}"` : ''}>${breadcrumbs}${hero ? '' : `<header class="page-head"><span class="eyebrow">${esc(typeLabel(doc.frontmatter.type))}</span>${doc.endpoint ? '' : badge(doc.frontmatter.subjectLifecycle)}<h1>${esc(doc.frontmatter.title)}${doc.endpoint ? badge(doc.frontmatter.subjectLifecycle) : ''}</h1>${pageHeader && !routeSummary ? `<p class="summary">${esc(pageHeader)}</p>` : ''}${pageDates}${endpoint}${audienceBadges}</header>`}${hero ? '' : `<div class="page-formats"><a class="formats" href="${esc(markdownUrl)}">Read as Markdown</a><button type="button" class="formats" data-copy-markdown hidden>Copy as Markdown</button><span role="status" data-copy-markdown-status></span></div>`}${toc ? '<div class="mobile-outline-slot"></div>' : ''}${jumps}${readerBanner}<article>${article}</article></main>${rail}${side}</div>${footer}${analyticsBootstrap}${readerBootstrap}<script type="module" src="/assets/copy-markdown.js"></script><script type="module" src="/assets/navigation.js"></script><script type="module" src="/assets/reader.js"></script><script type="module" src="/assets/tabs.js"></script>${shell.search ? '<script type="module" src="/assets/search.js"></script>' : ''}${article.includes('data-tooltip') ? '<script type="module" src="/assets/tooltips.js"></script>' : ''}${article.includes('data-component-module') ? '<script type="module" src="/assets/components.js"></script>' : ''}${article.includes('data-file-tree') ? '<script type="module" src="/assets/file-tree.js"></script>' : ''}${article.includes('data-image-expand') ? '<script type="module" src="/assets/image-viewer.js"></script>' : ''}${article.includes('data-table-filter') || article.includes('data-definition-filter') ? '<script type="module" src="/assets/table-filter.js"></script>' : ''}${article.includes('data-walkthrough') ? '<script type="module" src="/assets/walkthrough.js"></script>' : ''}${article.includes('data-cookbook-chooser') ? '<script type="module" src="/assets/cookbook-chooser.js"></script>' : ''}${article.includes('data-theme-preview') ? '<script type="module" src="/assets/theme-preview.js"></script>' : ''}${panel ? '<script type="module" src="/assets/example-panel.js"></script>' : ''}${panel.includes('data-code-samples') ? '<script type="module" src="/assets/code-samples.js"></script>' : ''}</body></html>`;
180
191
  return basePath ? markup.replace(/((?:href|src)=")\/(assets\/|llms(?:\.min)?\.txt|apple-touch-icon\.png)/g, `$1${basePath}/$2`).replace('href="/"', `href="${basePath}/"`) : markup;
181
192
  }
@@ -1,6 +1,7 @@
1
+ import { publicationKey } from './publication-identity.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { markdownRoute } from './content-source.js';
3
- const variantKey = (variant) => `${variant.channel}|${variant.version}|${variant.language}`;
4
+ const variantKey = publicationKey;
4
5
  const docKey = (id, variant) => `${id}|${variantKey(variant)}`;
5
6
  const tagId = (placeholder, tag) => `${placeholder}-tag-${createHash('sha256').update(tag).digest('hex').slice(0, 8)}`;
6
7
  export function validateProjectNavigation(layout, docs, operations, apiIds) {
@@ -0,0 +1,12 @@
1
+ /** Publication identity shared by compiler, retrieval and delivery runtimes. */
2
+ export type PublicationCoordinate = {
3
+ product?: string;
4
+ channel: string;
5
+ version: string;
6
+ language: string;
7
+ };
8
+ /** Productless keys deliberately retain the original serialized identity. */
9
+ export declare function publicationKey(value: PublicationCoordinate): string;
10
+ export declare function documentKey(id: string, value: PublicationCoordinate): string;
11
+ export declare function samePublication(left: PublicationCoordinate, right: PublicationCoordinate): boolean;
12
+ export declare function parsePublicationKey(value: string): PublicationCoordinate;
@@ -0,0 +1,17 @@
1
+ /** Productless keys deliberately retain the original serialized identity. */
2
+ export function publicationKey(value) {
3
+ return [value.channel, value.version, value.language, ...(value.product === undefined ? [] : [value.product])].join('|');
4
+ }
5
+ export function documentKey(id, value) {
6
+ return `${id}|${publicationKey(value)}`;
7
+ }
8
+ export function samePublication(left, right) {
9
+ return left.product === right.product && left.channel === right.channel && left.version === right.version && left.language === right.language;
10
+ }
11
+ export function parsePublicationKey(value) {
12
+ const parts = value.split('|');
13
+ if ((parts.length !== 3 && parts.length !== 4) || parts.some(part => !part))
14
+ throw new Error(`Invalid publication identity ${value}`);
15
+ const [channel, version, language, product] = parts;
16
+ return { channel, version, language, ...(product === undefined ? {} : { product }) };
17
+ }
@@ -1,3 +1,4 @@
1
+ import type { CompilerPublicationsConfig } from './compiler-config.js';
1
2
  import type { ApiEmbedUse } from './api-embeds.js';
2
3
  import type { CardUse, validateRelationships } from './cards.js';
3
4
  import type { Document, Variant } from './content.js';
@@ -7,7 +8,8 @@ import { type resolveProjectNavigation } from './project-navigation.js';
7
8
  import type { ReaderFiltersConfig } from './reader-filters.js';
8
9
  import type { Taxonomy } from './taxonomy.js';
9
10
  import type { SnippetUse } from './snippets.js';
10
- export declare function buildPublicationManifest({ fictionalDocuments, configDigest, synonyms, basePath, publicPath, readerFilters, taxonomy, dependencies, rendered, resolvedNavigation, cardUses, snippetUses, apiEmbedUses, focusedContracts, operations, publishedRelationships, redirects, apiSources, siteOrigin, siteIndexing, siteUpdated, diagramAssets, heroImages, faviconRoute, catalog }: {
11
+ export declare function buildPublicationManifest({ configPublications, fictionalDocuments, configDigest, synonyms, basePath, publicPath, readerFilters, taxonomy, dependencies, rendered, resolvedNavigation, cardUses, snippetUses, apiEmbedUses, focusedContracts, operations, publishedRelationships, redirects, apiSources, siteOrigin, siteIndexing, siteUpdated, diagramAssets, heroImages, faviconRoute, catalog }: {
12
+ configPublications: CompilerPublicationsConfig;
11
13
  fictionalDocuments: Set<Document>;
12
14
  configDigest: string;
13
15
  synonyms: unknown[];
@@ -38,6 +40,7 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
38
40
  }>;
39
41
  apiSources: Array<{
40
42
  apiId: string;
43
+ product?: string;
41
44
  channel: string;
42
45
  version: string;
43
46
  endpoint: string | null;
@@ -98,6 +101,10 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
98
101
  url?: string;
99
102
  }[];
100
103
  verified?: string | undefined;
104
+ availability?: {
105
+ since?: string;
106
+ through?: string;
107
+ } | undefined;
101
108
  updated?: string | undefined;
102
109
  indexable: boolean;
103
110
  navigationTab: {
@@ -163,6 +170,10 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
163
170
  url?: string;
164
171
  }[];
165
172
  verified?: string | undefined;
173
+ availability?: {
174
+ since?: string;
175
+ through?: string;
176
+ } | undefined;
166
177
  updated?: string | undefined;
167
178
  indexable: boolean;
168
179
  navigationTab?: undefined;
@@ -181,6 +192,7 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
181
192
  operations: Record<string, {
182
193
  id: string;
183
194
  type: string;
195
+ product?: string;
184
196
  channel: string;
185
197
  version: string;
186
198
  language: string;
@@ -200,6 +212,7 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
200
212
  }[];
201
213
  apiSources: {
202
214
  apiId: string;
215
+ product?: string;
203
216
  channel: string;
204
217
  version: string;
205
218
  endpoint: string | null;
@@ -221,6 +234,16 @@ export declare function buildPublicationManifest({ fictionalDocuments, configDig
221
234
  sitemap?: string | undefined;
222
235
  basePath: string;
223
236
  searchSynonyms?: unknown[] | undefined;
237
+ publications?: {
238
+ enabled: Variant[];
239
+ products: {
240
+ [k: string]: {
241
+ versions: string[];
242
+ defaultVersion?: string | undefined;
243
+ label?: string | undefined;
244
+ };
245
+ };
246
+ } | undefined;
224
247
  schemaVersion: number;
225
248
  configDigest: string;
226
249
  };