@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.
- package/AUTHORING.md +29 -0
- package/CHANGELOG.md +23 -0
- package/DEPLOYMENT-PROFILES.md +96 -5
- package/README.md +58 -2
- package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +21 -17
- package/agent-docs/SNAPSHOT.json +5 -5
- package/agent-docs/api-docs/focused-contracts.md +4 -4
- package/agent-docs/api-docs/generate.md +11 -11
- package/agent-docs/api-docs/generate.sections/add-useful-examples.md +3 -3
- package/agent-docs/api-docs/generate.sections/choose-generated-references-or-mdx.md +4 -4
- package/agent-docs/api-docs/generate.sections/describe-filters-that-do-not-use-their-openapi-parameter-name.md +1 -1
- package/agent-docs/api-docs/generate.sections/generate-many-pages-selectively.md +2 -2
- package/agent-docs/api-docs/generate.sections/link-guides-to-api-references.md +1 -1
- package/agent-docs/api-docs/generate.sections/map-extension-values-to-shoalrun-status.md +1 -1
- package/agent-docs/api-docs/generate.sections/override-generated-reference-order-in-navigation.md +4 -4
- package/agent-docs/api-docs/generate.sections/related-reading.md +1 -1
- package/agent-docs/api-docs/generate.sections/use-a-template-for-editorial-context.md +2 -2
- package/agent-docs/api-docs/support.md +7 -7
- package/agent-docs/author/add-page.md +3 -3
- package/agent-docs/author/agent-overview.md +3 -3
- package/agent-docs/author/agent-workflow.md +7 -7
- package/agent-docs/author/analytics.md +27 -27
- package/agent-docs/author/analytics.sections/adapter-exports-and-consent.md +3 -3
- package/agent-docs/author/analytics.sections/built-in-events.md +15 -15
- package/agent-docs/author/analytics.sections/configure-an-adapter.md +1 -1
- package/agent-docs/author/analytics.sections/custom-interactions.md +2 -2
- package/agent-docs/author/analytics.sections/event-format.md +2 -2
- package/agent-docs/author/analytics.sections/html-markdown-and-agents.md +4 -4
- package/agent-docs/author/analytics.sections/inspect-events-locally.md +2 -2
- package/agent-docs/author/analytics.sections/map-events-to-your-service.md +3 -3
- package/agent-docs/author/analytics.sections/posthog-example.md +3 -3
- package/agent-docs/author/analytics.sections/related-reading.md +1 -1
- package/agent-docs/author/authoring-agent.md +3 -3
- package/agent-docs/author/coding-agent.md +4 -4
- package/agent-docs/author/components/api-embeds.md +6 -6
- package/agent-docs/author/components/api-embeds.sections/apiexample.md +3 -3
- package/agent-docs/author/components/api-embeds.sections/html-markdown-and-agents.md +1 -1
- package/agent-docs/author/components/api-embeds.sections/related-reading.md +1 -1
- package/agent-docs/author/components/badge.md +2 -2
- package/agent-docs/author/components/callout.md +2 -2
- package/agent-docs/author/components/cards.md +16 -16
- package/agent-docs/author/components/cards.sections/add-a-lucide-icon.md +4 -4
- package/agent-docs/author/components/cards.sections/build-a-collection.md +7 -7
- package/agent-docs/author/components/cards.sections/curate-a-reading-list.md +9 -9
- package/agent-docs/author/components/cards.sections/html-markdown-and-agents.md +3 -3
- package/agent-docs/author/components/cards.sections/link-to-one-document.md +3 -3
- package/agent-docs/author/components/cards.sections/override-card-text.md +5 -5
- package/agent-docs/author/components/cards.sections/related-reading.md +3 -3
- package/agent-docs/author/components/code-blocks.md +2 -2
- package/agent-docs/author/components/collapsible.md +3 -3
- package/agent-docs/author/components/cookbook-chooser.md +5 -5
- package/agent-docs/author/components/custom/react.md +8 -8
- package/agent-docs/author/components/custom/react.sections/html-markdown-and-agents.md +3 -3
- package/agent-docs/author/components/custom/react.sections/interactive-react-example.md +2 -2
- package/agent-docs/author/components/custom/react.sections/registration.md +1 -1
- package/agent-docs/author/components/custom/react.sections/related-reading.md +1 -1
- package/agent-docs/author/components/custom/react.sections/share-the-model-with-the-browser.md +3 -3
- package/agent-docs/author/components/custom/react.sections/where-the-content-lives.md +3 -3
- package/agent-docs/author/components/custom.md +7 -7
- package/agent-docs/author/components/definition-list.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/basic-shapes.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/flows-and-structures.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/html-markdown-and-agents.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/layout-engines.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/related-reading.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/sequences-and-grids.md +2 -2
- package/agent-docs/author/components/diagrams/d2-gallery.sections/styles-and-code.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.md +3 -3
- package/agent-docs/author/components/diagrams/pele-gallery.sections/charts-and-planning.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.sections/flowchart-shapes.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.sections/flows-and-behavior.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.sections/html-markdown-and-agents.md +3 -3
- package/agent-docs/author/components/diagrams/pele-gallery.sections/related-reading.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.sections/specialized-diagrams.md +2 -2
- package/agent-docs/author/components/diagrams/pele-gallery.sections/systems-and-structures.md +2 -2
- package/agent-docs/author/components/diagrams.md +8 -8
- package/agent-docs/author/components/doc-link.md +3 -3
- package/agent-docs/author/components/fields.md +18 -18
- package/agent-docs/author/components/file-tree.md +2 -2
- package/agent-docs/author/components/images.md +5 -5
- package/agent-docs/author/components/info-hint.md +3 -3
- package/agent-docs/author/components/kbd.md +2 -2
- package/agent-docs/author/components/math.md +2 -2
- package/agent-docs/author/components/only.md +3 -3
- package/agent-docs/author/components/progress.md +3 -3
- package/agent-docs/author/components/steps.md +2 -2
- package/agent-docs/author/components/tables.md +2 -2
- package/agent-docs/author/components/tabs.md +5 -5
- package/agent-docs/author/components/timeline.md +2 -2
- package/agent-docs/author/components/tooltips.md +2 -2
- package/agent-docs/author/components/walkthroughs.md +2 -2
- package/agent-docs/author/components/walkthroughs.sections/attributes.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/build-up-code.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/choose-a-layout.md +2 -2
- package/agent-docs/author/components/walkthroughs.sections/explain-one-file.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/html-markdown-and-agents.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/related-reading.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/syntax.md +1 -1
- package/agent-docs/author/components/walkthroughs.sections/take-code-from-a-file.md +1 -1
- package/agent-docs/author/components.md +2 -2
- package/agent-docs/author/content.md +3 -3
- package/agent-docs/author/cookbooks.md +9 -9
- package/agent-docs/author/css.md +4 -4
- package/agent-docs/author/css.sections/borders-fields-and-navigation-tokens.md +3 -3
- package/agent-docs/author/css.sections/core-color-tokens.md +3 -3
- package/agent-docs/author/css.sections/html-markdown-and-agents.md +4 -4
- package/agent-docs/author/css.sections/page-attributes.md +3 -3
- package/agent-docs/author/css.sections/page-transitions.md +3 -3
- package/agent-docs/author/css.sections/responsive-behavior.md +3 -3
- package/agent-docs/author/css.sections/status-code-and-callout-tokens.md +3 -3
- package/agent-docs/author/css.sections/typography-shape-and-width-tokens.md +3 -3
- package/agent-docs/author/custom-metadata.md +13 -13
- package/agent-docs/author/custom-metadata.sections/add-a-custom-page-field.md +4 -4
- package/agent-docs/author/custom-metadata.sections/choose-text-for-each-surface.md +3 -3
- package/agent-docs/author/custom-metadata.sections/preview-changes-to-metadata-providers.md +2 -2
- package/agent-docs/author/custom-metadata.sections/read-metadata-from-a-project-module.md +3 -3
- package/agent-docs/author/custom-metadata.sections/related-reading.md +1 -1
- package/agent-docs/author/design-templates.md +3 -3
- package/agent-docs/author/design-writing-guides.md +3 -3
- package/agent-docs/author/frontmatter-reference.md +45 -6
- package/agent-docs/author/frontmatter-reference.sections/categorize-connect-and-present-the-page.md +64 -0
- package/agent-docs/author/frontmatter-reference.sections/choose-a-publication-and-visibility.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/control-output-details.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/feature-availability.md +59 -0
- package/agent-docs/author/frontmatter-reference.sections/global-defaults-and-enforced-values.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/html-markdown-and-agents.md +3 -3
- package/agent-docs/author/frontmatter-reference.sections/identify-and-route-a-page.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/point-agents-to-it.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/product-publication-fields.md +37 -0
- package/agent-docs/author/frontmatter-reference.sections/project-defined-fields.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/related-reading.md +2 -2
- package/agent-docs/author/frontmatter-reference.sections/use-the-local-files-while-authoring.md +4 -4
- package/agent-docs/author/frontmatter-reference.sections/when-the-files-update.md +2 -2
- package/agent-docs/author/frontmatter.md +13 -13
- package/agent-docs/author/frontmatter.sections/audience-badges.md +3 -3
- package/agent-docs/author/frontmatter.sections/give-deprecation-guidance.md +4 -4
- package/agent-docs/author/frontmatter.sections/global-defaults-and-enforced-values.md +1 -1
- package/agent-docs/author/frontmatter.sections/optional-native-fields.md +4 -4
- package/agent-docs/author/frontmatter.sections/publication-fields.md +2 -2
- package/agent-docs/author/frontmatter.sections/publishing-policy.md +1 -1
- package/agent-docs/author/frontmatter.sections/related-metadata-tasks.md +1 -1
- package/agent-docs/author/frontmatter.sections/related-reading.md +1 -1
- package/agent-docs/author/frontmatter.sections/required-after-inheritance.md +1 -1
- package/agent-docs/author/frontmatter.sections/seo-fields.md +2 -2
- package/agent-docs/author/frontmatter.sections/validation-rules.md +3 -3
- package/agent-docs/author/markdown-metadata.md +20 -20
- package/agent-docs/author/navigation.md +12 -12
- package/agent-docs/author/navigation.sections/arrange-authored-pages.md +4 -4
- package/agent-docs/author/navigation.sections/fill-an-api-tag-group.md +2 -2
- package/agent-docs/author/navigation.sections/hide-group-page-counts.md +4 -4
- package/agent-docs/author/navigation.sections/html-markdown-and-agents.md +4 -4
- package/agent-docs/author/navigation.sections/local-api-preview.md +2 -2
- package/agent-docs/author/navigation.sections/mix-guides-and-api-references.md +3 -3
- package/agent-docs/author/navigation.sections/optionally-split-a-large-menu-into-files.md +2 -2
- package/agent-docs/author/navigation.sections/reach-navigation-while-reading.md +2 -2
- package/agent-docs/author/navigation.sections/related-reading.md +2 -2
- package/agent-docs/author/navigation.sections/split-navigation-into-tabs.md +4 -4
- package/agent-docs/author/navigation.sections/subject-lifecycle-labels.md +3 -3
- package/agent-docs/author/reader-views.md +9 -9
- package/agent-docs/author/reader-views.sections/configure-the-choices.md +2 -2
- package/agent-docs/author/reader-views.sections/connect-your-own-control.md +1 -1
- package/agent-docs/author/reader-views.sections/how-it-works-for-agents.md +3 -3
- package/agent-docs/author/reader-views.sections/mark-pages.md +3 -3
- package/agent-docs/author/reader-views.sections/mark-sections-and-add-an-entry-choice.md +2 -2
- package/agent-docs/author/reader-views.sections/place-filter-controls.md +2 -2
- package/agent-docs/author/reader-views.sections/try-the-controls-here.md +2 -2
- package/agent-docs/author/recipe-drafts.md +5 -5
- package/agent-docs/author/recipe-drafts.sections/1-write-one-reusable-step.md +2 -2
- package/agent-docs/author/recipe-drafts.sections/2-list-the-steps-for-one-complete-goal.md +2 -2
- package/agent-docs/author/recipe-drafts.sections/3-generate-a-draft-and-review-it.md +1 -1
- package/agent-docs/author/recipe-drafts.sections/4-maintain-shoalrun-s-published-recipe-snapshots.md +2 -2
- package/agent-docs/author/recipe-drafts.sections/related-reading.md +1 -1
- package/agent-docs/author/recipe-drafts.sections/start-an-ingredient-from-an-api-example.md +2 -2
- package/agent-docs/author/recipes.md +7 -7
- package/agent-docs/author/recipes.sections/how-agents-use-this.md +2 -2
- package/agent-docs/author/recipes.sections/one-example-from-shoalrun.md +2 -2
- package/agent-docs/author/recipes.sections/related-reading.md +1 -1
- package/agent-docs/author/recipes.sections/try-a-complete-workflow.md +1 -1
- package/agent-docs/author/recipes.sections/use-recipes-for-task-oriented-how-tos.md +3 -3
- package/agent-docs/author/recipes.sections/what-changing-an-ingredient-updates.md +2 -2
- package/agent-docs/author/recipes.sections/what-each-file-does.md +1 -1
- package/agent-docs/author/recipes.sections/what-happens-and-when.md +2 -2
- package/agent-docs/author/related-reading.md +11 -11
- package/agent-docs/author/related-reading.sections/automatic-footers.md +3 -3
- package/agent-docs/author/related-reading.sections/declare-relationships.md +3 -3
- package/agent-docs/author/related-reading.sections/display-related-documents.md +3 -3
- package/agent-docs/author/related-reading.sections/html-markdown-and-agents.md +1 -1
- package/agent-docs/author/related-reading.sections/inspect-output-and-changes.md +2 -2
- package/agent-docs/author/related-reading.sections/reading-paths-in-section-markdown.md +3 -3
- package/agent-docs/author/related-reading.sections/related-reading.md +1 -1
- package/agent-docs/author/related-reading.sections/where-relationship-explanations-come-from.md +2 -2
- package/agent-docs/author/release-notes.md +8 -8
- package/agent-docs/author/search.md +43 -39
- package/agent-docs/author/search.sections/agent-and-mcp-search-scope.md +12 -8
- package/agent-docs/author/search.sections/choose-a-provider.md +8 -8
- package/agent-docs/author/search.sections/cli-and-mcp-ranking-details.md +4 -4
- package/agent-docs/author/search.sections/enable-included-semantic-search.md +5 -5
- package/agent-docs/author/search.sections/hosted-semantic-search-limits.md +3 -3
- package/agent-docs/author/search.sections/html-markdown-and-agents.md +3 -3
- package/agent-docs/author/search.sections/lexical-search.md +6 -6
- package/agent-docs/author/search.sections/local-semantic-preview.md +3 -3
- package/agent-docs/author/search.sections/read-a-search-result-with-an-agent.md +2 -2
- package/agent-docs/author/search.sections/related-reading.md +2 -2
- package/agent-docs/author/search.sections/reuse-the-lexical-index.md +5 -5
- package/agent-docs/author/search.sections/turn-search-off.md +3 -3
- package/agent-docs/author/search.sections/use-the-search-box.md +2 -2
- package/agent-docs/author/search.sections/write-a-custom-provider.md +11 -11
- package/agent-docs/author/snippets.md +3 -3
- package/agent-docs/author/taxonomy.md +3 -3
- package/agent-docs/author/templates.md +16 -14
- package/agent-docs/author/templates.sections/built-in-feature-templates.md +2 -2
- package/agent-docs/author/templates.sections/built-in-templates.md +2 -2
- package/agent-docs/author/templates.sections/choose-formatting-enforcement-for-your-project.md +7 -7
- package/agent-docs/author/templates.sections/create-or-edit-a-project-template.md +8 -6
- package/agent-docs/author/templates.sections/keep-the-four-shapes-distinct.md +2 -2
- package/agent-docs/author/templates.sections/project-added-templates.md +3 -3
- package/agent-docs/author/templates.sections/related-reading.md +2 -2
- package/agent-docs/author/templates.sections/scaffold-a-page.md +2 -2
- package/agent-docs/author/templates.sections/short-cli-and-derived-values.md +3 -3
- package/agent-docs/author/templates.sections/what-every-template-gives-you.md +3 -3
- package/agent-docs/author/workspace/commands.md +4 -4
- package/agent-docs/author/workspace.md +7 -7
- package/agent-docs/author/writing-style.md +33 -18
- package/agent-docs/author/writing-style.sections/adapt-this-example.md +2 -2
- package/agent-docs/author/writing-style.sections/choose-components-by-reader-need.md +3 -3
- package/agent-docs/author/writing-style.sections/evidence-and-uncertainty.md +4 -4
- package/agent-docs/author/writing-style.sections/example-audience-and-scope.md +2 -2
- package/agent-docs/author/writing-style.sections/feature-availability.md +20 -7
- package/agent-docs/author/writing-style.sections/ingredients-recipes-and-cookbooks.md +5 -5
- package/agent-docs/author/writing-style.sections/page-purpose-and-structure.md +4 -4
- package/agent-docs/author/writing-style.sections/procedures-and-examples.md +4 -4
- package/agent-docs/author/writing-style.sections/related-reading.md +2 -2
- package/agent-docs/author/writing-style.sections/review-a-draft.md +3 -3
- package/agent-docs/author/writing-style.sections/reviewed-writing-examples.md +2 -2
- package/agent-docs/author/writing-style.sections/voice-and-explanations.md +4 -2
- package/agent-docs/changelog/2026-10-14-agent-readiness.md +2 -2
- package/agent-docs/changelog/2026-10-15-evaluation-builds.md +9 -9
- package/agent-docs/changelog/2026-10-16-navigation-layouts.md +4 -4
- package/agent-docs/changelog/2026-10-17-mcp-hosting.md +2 -2
- package/agent-docs/changelog/2026-10-18-search-and-tooltips.md +3 -3
- package/agent-docs/changelog/2026-10-19-visual-navigation.md +3 -3
- package/agent-docs/changelog/2026-10-25.md +2 -2
- package/agent-docs/changelog/2026-10-26.md +4 -4
- package/agent-docs/changelog/2026-10-27.md +1 -1
- package/agent-docs/changelog/2026-10-28.md +3 -3
- package/agent-docs/changelog/2026-10-30.md +1 -1
- package/agent-docs/changelog/2026-11-03.md +5 -5
- package/agent-docs/changelog/2026-11-04-runtime-packaging.md +46 -0
- package/agent-docs/changelog/authoring-preview.md +3 -3
- package/agent-docs/changelog/authoring-search.md +1 -1
- package/agent-docs/changelog/authoring-tools.md +2 -2
- package/agent-docs/changelog/product-publications.md +60 -0
- package/agent-docs/changelog/working-tree-skill.md +1 -1
- package/agent-docs/changelog.md +17 -1
- package/agent-docs/chat/checks.md +11 -11
- package/agent-docs/chat/checks.sections/answer-ahead-of-time.md +1 -1
- package/agent-docs/chat/checks.sections/answer-for-one-audience.md +2 -2
- package/agent-docs/chat/checks.sections/answer-without-a-model.md +2 -2
- package/agent-docs/chat/checks.sections/follow-up-questions.md +2 -2
- package/agent-docs/chat/checks.sections/how-an-answer-is-checked.md +3 -3
- package/agent-docs/chat/checks.sections/questions-with-several-parts.md +3 -3
- package/agent-docs/chat/checks.sections/related-reading.md +1 -1
- package/agent-docs/chat/checks.sections/reuse-answers.md +4 -4
- package/agent-docs/chat/host.md +8 -8
- package/agent-docs/chat/host.sections/cap-the-daily-spend.md +2 -2
- package/agent-docs/chat/host.sections/keep-a-record-of-questions.md +3 -3
- package/agent-docs/chat/host.sections/related-reading.md +2 -2
- package/agent-docs/chat/passage-index.md +17 -17
- package/agent-docs/chat/passage-index.sections/build-the-index.md +2 -2
- package/agent-docs/chat/passage-index.sections/embed-passages.md +3 -3
- package/agent-docs/chat/passage-index.sections/how-the-default-chunker-splits-a-page.md +2 -2
- package/agent-docs/chat/passage-index.sections/limits.md +2 -2
- package/agent-docs/chat/passage-index.sections/passage-ids-and-links.md +3 -3
- package/agent-docs/chat/passage-index.sections/related-reading.md +2 -2
- package/agent-docs/chat/passage-index.sections/what-a-passage-contains.md +15 -15
- package/agent-docs/chat/prepared-answers.md +4 -4
- package/agent-docs/chat/settings.md +3 -3
- package/agent-docs/chat/settings.sections/choose-the-scorer.md +1 -1
- package/agent-docs/chat/settings.sections/configure-chat.md +1 -1
- package/agent-docs/chat/settings.sections/configure-retrieval.md +1 -1
- package/agent-docs/chat/settings.sections/related-reading.md +1 -1
- package/agent-docs/chat/settings.sections/send-extra-request-fields.md +2 -2
- package/agent-docs/chat/settings.sections/use-more-than-one-model.md +2 -2
- package/agent-docs/chat/settings.sections/when-the-scorer-is-down.md +1 -1
- package/agent-docs/chat/setup.md +2 -2
- package/agent-docs/chat.md +3 -3
- package/agent-docs/cli.md +73 -59
- package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +11 -7
- package/agent-docs/cli.sections/author-pages.md +16 -12
- package/agent-docs/cli.sections/build-and-serve.md +30 -18
- package/agent-docs/cli.sections/inspect-config-and-operations.md +13 -9
- package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +7 -3
- package/agent-docs/cli.sections/related-reading.md +6 -2
- package/agent-docs/cli.sections/search-and-chat.md +24 -18
- package/agent-docs/cli.sections/start-a-project.md +7 -3
- package/agent-docs/cli.sections/working-tree-authoring-tools.md +7 -3
- package/agent-docs/concepts.md +2 -2
- package/agent-docs/config/apis.md +2 -2
- package/agent-docs/config/content.md +3 -3
- package/agent-docs/config/content.sections/authoring.md +3 -3
- package/agent-docs/config/content.sections/badges.md +1 -1
- package/agent-docs/config/content.sections/callouts.md +1 -1
- package/agent-docs/config/content.sections/cookbooks.md +1 -1
- package/agent-docs/config/content.sections/frontmatter.md +1 -1
- package/agent-docs/config/content.sections/readerfilters.md +1 -1
- package/agent-docs/config/content.sections/related-reading.md +1 -1
- package/agent-docs/config/content.sections/relationships.md +1 -1
- package/agent-docs/config/content.sections/snippets.md +1 -1
- package/agent-docs/config/content.sections/templates.md +1 -1
- package/agent-docs/config/content.sections/variables.md +1 -1
- package/agent-docs/config/examples.md +4 -4
- package/agent-docs/config/examples.sections/feature-showcase.md +4 -4
- package/agent-docs/config/examples.sections/minimal-site.md +2 -2
- package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
- package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
- package/agent-docs/config/examples.sections/related-reading.md +2 -2
- package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
- package/agent-docs/config/integrations.md +4 -4
- package/agent-docs/config/outputs.md +22 -16
- package/agent-docs/config/outputs.sections/exports.md +19 -13
- package/agent-docs/config/outputs.sections/metadata.md +2 -2
- package/agent-docs/config/outputs.sections/related-reading.md +1 -1
- package/agent-docs/config/publishing.md +29 -19
- package/agent-docs/config/publishing.sections/navigation.md +2 -2
- package/agent-docs/config/publishing.sections/redirects.md +8 -8
- package/agent-docs/config/publishing.sections/related-reading.md +2 -2
- package/agent-docs/config/site.md +42 -18
- package/agent-docs/config/site.sections/related-reading.md +1 -1
- package/agent-docs/config/site.sections/theme.md +1 -1
- package/agent-docs/config.md +2 -2
- package/agent-docs/configuration.md +19 -19
- package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
- package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +5 -5
- package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
- package/agent-docs/configuration.sections/inspect-and-validate-changes.md +5 -5
- package/agent-docs/configuration.sections/related-reading.md +1 -1
- package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +5 -5
- package/agent-docs/configuration.sections/share-defaults-through-extends.md +3 -3
- package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
- package/agent-docs/configuration.sections/understand-the-three-stages.md +3 -3
- package/agent-docs/configuration.sections/understand-where-paths-point.md +2 -2
- package/agent-docs/connect/mcp.md +24 -15
- package/agent-docs/content-delivery/agents.md +6 -6
- package/agent-docs/content-delivery/api.md +29 -16
- package/agent-docs/content-delivery/client.md +14 -8
- package/agent-docs/content-delivery/http-api/operations/get-content-representation-fa1d2e3f.md +10 -2
- package/agent-docs/content-delivery/http-api/operations/get-content-representation-head-4052375c.md +10 -2
- package/agent-docs/content-delivery/http-api/operations/get-content-resource-849f1c49.md +537 -3
- package/agent-docs/content-delivery/http-api/operations/get-content-resource-head-0a352acd.md +10 -2
- package/agent-docs/content-delivery/http-api/operations/list-content-resources-8e977ec7.md +545 -3
- package/agent-docs/content-delivery/http-api/operations/list-content-resources-head-b67cbad9.md +10 -2
- package/agent-docs/content-delivery/http-api.md +21 -7
- package/agent-docs/content-delivery/manifest.md +30 -8
- package/agent-docs/content-delivery/publish.md +5 -5
- package/agent-docs/content-delivery/render.md +6 -6
- package/agent-docs/content-delivery/rest.md +16 -8
- package/agent-docs/content-delivery/sections.md +11 -11
- package/agent-docs/content-delivery/select.md +6 -6
- package/agent-docs/content-delivery.md +4 -4
- package/agent-docs/contribute/agent-skills.md +3 -3
- package/agent-docs/cookbooks/authoring.md +3 -3
- package/agent-docs/cookbooks/site-workflows.md +2 -2
- package/agent-docs/cookbooks/welcome-email.md +3 -3
- package/agent-docs/documents.json +2415 -1936
- package/agent-docs/example-api/cedar.md +4 -4
- package/agent-docs/features.md +49 -0
- package/agent-docs/glossary.md +22 -22
- package/agent-docs/index.md +5 -5
- package/agent-docs/ingredients/audit-site.md +2 -2
- package/agent-docs/ingredients/build-site.md +2 -2
- package/agent-docs/ingredients/complete-page.md +2 -2
- package/agent-docs/ingredients/refresh-agent-bundle.md +2 -2
- package/agent-docs/non-goals.md +4 -4
- package/agent-docs/provenance.json +10 -4
- package/agent-docs/publish/agent-discovery.md +8 -2
- package/agent-docs/publish/agent-friendliness.md +21 -21
- package/agent-docs/publish/agent-friendliness.sections/discover-a-page-with-a-small-context-budget.md +5 -5
- package/agent-docs/publish/agent-friendliness.sections/distinguish-examples-from-a-real-service.md +5 -5
- package/agent-docs/publish/agent-friendliness.sections/evidence-has-a-scope.md +5 -5
- package/agent-docs/publish/agent-friendliness.sections/keep-shared-instructions-complete.md +5 -5
- package/agent-docs/publish/agent-friendliness.sections/related-reading.md +3 -3
- package/agent-docs/publish/agent-friendliness.sections/secret-handshake.md +3 -3
- package/agent-docs/publish/agent-friendliness.sections/try-the-page-controls.md +3 -3
- package/agent-docs/publish/agent-friendliness.sections/use-the-transport-your-client-supports.md +4 -4
- package/agent-docs/publish/agent-friendliness.sections/verify-the-page-and-detect-changes.md +9 -9
- package/agent-docs/publish/agent-friendliness.sections/what-an-agent-reads.md +5 -5
- package/agent-docs/publish/agent-friendliness.sections/what-happens-to-an-unsupported-component.md +4 -4
- package/agent-docs/publish/api-references.md +5 -5
- package/agent-docs/publish/api-references.sections/author-the-reference-page.md +2 -2
- package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -3
- package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +2 -2
- package/agent-docs/publish/api-references.sections/next-steps.md +2 -2
- package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +2 -2
- package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +2 -2
- package/agent-docs/publish/api-references.sections/register-the-operation.md +2 -2
- package/agent-docs/publish/api-references.sections/related-reading.md +2 -2
- package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -3
- package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -3
- package/agent-docs/publish/audit.md +8 -8
- package/agent-docs/publish/audit.sections/add-project-tests.md +2 -2
- package/agent-docs/publish/audit.sections/check-agent-evaluation-reports.md +2 -2
- package/agent-docs/publish/audit.sections/check-before-pushing.md +3 -3
- package/agent-docs/publish/audit.sections/connect-a-documentation-test-suite.md +2 -2
- package/agent-docs/publish/audit.sections/read-the-report.md +3 -3
- package/agent-docs/publish/audit.sections/related-reading.md +1 -1
- package/agent-docs/publish/content-export.md +37 -15
- package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +4 -4
- package/agent-docs/publish/content-export.sections/check-the-result.md +2 -2
- package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +3 -3
- package/agent-docs/publish/content-export.sections/prerequisites.md +4 -4
- package/agent-docs/publish/content-export.sections/related-reading.md +2 -2
- package/agent-docs/publish/content-export.sections/review-exported-api-material.md +3 -3
- package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +2 -2
- package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +4 -4
- package/agent-docs/publish/content-negotiation.md +10 -10
- package/agent-docs/publish/content-negotiation.sections/hosting-contract.md +2 -2
- package/agent-docs/publish/content-negotiation.sections/missing-pages.md +3 -3
- package/agent-docs/publish/content-negotiation.sections/related-reading.md +1 -1
- package/agent-docs/publish/content-negotiation.sections/validators-and-manifest-links.md +2 -2
- package/agent-docs/publish/content-negotiation.sections/verify-the-deployed-url.md +2 -2
- package/agent-docs/publish/content-negotiation.sections/what-if-the-host-cannot-negotiate.md +3 -3
- package/agent-docs/publish/content-negotiation.sections/what-shoalrun-builds-and-what-the-host-does.md +2 -2
- package/agent-docs/publish/content-negotiation.sections/why-this-matters.md +2 -2
- package/agent-docs/publish/deployment-check.md +6 -6
- package/agent-docs/publish/deployment-profiles.md +60 -26
- package/agent-docs/publish/deployment-profiles.sections/before-you-begin.md +5 -5
- package/agent-docs/publish/deployment-profiles.sections/build-and-inspect-the-edition.md +9 -9
- package/agent-docs/publish/deployment-profiles.sections/check-the-result.md +7 -7
- package/agent-docs/publish/deployment-profiles.sections/choose-navigation-labels.md +6 -6
- package/agent-docs/publish/deployment-profiles.sections/current-limits.md +7 -7
- package/agent-docs/publish/deployment-profiles.sections/define-the-shared-sku-manifest.md +6 -6
- package/agent-docs/publish/deployment-profiles.sections/html-markdown-and-agents.md +7 -7
- package/agent-docs/publish/deployment-profiles.sections/mark-pages-and-shared-sections.md +13 -13
- package/agent-docs/publish/deployment-profiles.sections/preview-and-edit-a-customer-edition.md +55 -0
- package/agent-docs/publish/deployment-profiles.sections/related-reading.md +6 -6
- package/agent-docs/publish/deployment-profiles.sections/select-each-product-release.md +55 -0
- package/agent-docs/publish/deployment-profiles.sections/supply-the-profile-from-the-deployment.md +6 -6
- package/agent-docs/publish/evals.md +16 -16
- package/agent-docs/publish/evals.sections/add-the-audit-hook.md +5 -5
- package/agent-docs/publish/evals.sections/check-the-report.md +4 -4
- package/agent-docs/publish/evals.sections/define-a-task-file.md +5 -5
- package/agent-docs/publish/evals.sections/diagnose-a-different-build.md +5 -5
- package/agent-docs/publish/evals.sections/prepare-a-report-for-the-built-site.md +5 -5
- package/agent-docs/publish/evals.sections/related-reading.md +3 -3
- package/agent-docs/publish/evals.sections/run-and-review-the-tasks.md +4 -4
- package/agent-docs/publish/evals.sections/shoalrun-s-own-example.md +6 -6
- package/agent-docs/publish/host-adapters.md +6 -6
- package/agent-docs/publish/manni.md +16 -16
- package/agent-docs/publish/manni.sections/check-the-result.md +3 -3
- package/agent-docs/publish/manni.sections/how-this-site-uses-manni.md +6 -6
- package/agent-docs/publish/manni.sections/optional-custom-policies.md +4 -4
- package/agent-docs/publish/manni.sections/prerequisites.md +2 -2
- package/agent-docs/publish/mcp-analytics.md +12 -12
- package/agent-docs/publish/mcp-analytics.sections/adapter-exports.md +4 -4
- package/agent-docs/publish/mcp-analytics.sections/enable-analytics.md +4 -4
- package/agent-docs/publish/mcp-analytics.sections/event-fields-and-service-mappings.md +4 -4
- package/agent-docs/publish/mcp-analytics.sections/optionally-collect-intent-and-group-calls.md +4 -4
- package/agent-docs/publish/mcp-analytics.sections/optionally-identify-the-client-and-model.md +5 -5
- package/agent-docs/publish/mcp-analytics.sections/related-reading.md +3 -3
- package/agent-docs/publish/mcp-analytics.sections/safeguards-and-limits.md +5 -5
- package/agent-docs/publish/mcp.md +56 -29
- package/agent-docs/publish/mcp.sections/check-budgets-and-errors.md +8 -8
- package/agent-docs/publish/mcp.sections/choose-the-documentation-source.md +4 -4
- package/agent-docs/publish/mcp.sections/configure-the-client.md +4 -4
- package/agent-docs/publish/mcp.sections/discover-product-releases-before-searching.md +52 -0
- package/agent-docs/publish/mcp.sections/generate-a-vercel-endpoint.md +6 -6
- package/agent-docs/publish/mcp.sections/html-markdown-and-agents.md +38 -0
- package/agent-docs/publish/mcp.sections/related-reading.md +3 -3
- package/agent-docs/publish/mcp.sections/search-then-read.md +13 -12
- package/agent-docs/publish/mcp.sections/serve-a-public-endpoint-on-node.md +12 -8
- package/agent-docs/publish/mcp.sections/verify-the-connection.md +4 -4
- package/agent-docs/publish/mcp.sections/why-offer-mcp-for-public-docs.md +4 -4
- package/agent-docs/publish/openapi-extension-mappings.md +12 -12
- package/agent-docs/publish/output.md +20 -20
- package/agent-docs/publish/output.sections/api-contracts.md +1 -1
- package/agent-docs/publish/output.sections/code-highlighting.md +1 -1
- package/agent-docs/publish/output.sections/current-limits.md +1 -1
- package/agent-docs/publish/output.sections/incremental-sync.md +4 -4
- package/agent-docs/publish/output.sections/manifest-records-and-sections.md +3 -3
- package/agent-docs/publish/output.sections/navigation-section-indexes.md +1 -1
- package/agent-docs/publish/output.sections/page-formats.md +2 -2
- package/agent-docs/publish/output.sections/published-output-contract.md +5 -5
- package/agent-docs/publish/output.sections/reader-appearance-and-controls.md +1 -1
- package/agent-docs/publish/output.sections/related-reading.md +1 -1
- package/agent-docs/publish/output.sections/response-identity.md +1 -1
- package/agent-docs/publish/output.sections/site-files.md +6 -6
- package/agent-docs/publish/output.sections/validate-an-existing-build-locally.md +3 -3
- package/agent-docs/publish/output.sections/where-files-go.md +3 -3
- package/agent-docs/publish/publications.md +108 -19
- package/agent-docs/publish/publications.sections/add-a-language.md +60 -0
- package/agent-docs/publish/publications.sections/change-just-one-part-of-a-shared-page.md +63 -0
- package/agent-docs/publish/publications.sections/give-each-api-version-its-own-contract.md +34 -0
- package/agent-docs/publish/publications.sections/keep-an-unchanged-page-in-one-file.md +53 -0
- package/agent-docs/publish/publications.sections/publish-versions-without-a-product-catalog.md +49 -0
- package/agent-docs/publish/publications.sections/related-reading.md +42 -0
- package/agent-docs/publish/publications.sections/version-products-independently.md +115 -0
- package/agent-docs/publish/publications.sections/what-agents-receive.md +38 -0
- package/agent-docs/publish/revisions.md +4 -4
- package/agent-docs/publish/seo.md +10 -10
- package/agent-docs/publish/seo.sections/related-reading.md +2 -2
- package/agent-docs/publish/seo.sections/set-the-public-address.md +3 -3
- package/agent-docs/publish/seo.sections/what-agents-receive.md +3 -3
- package/agent-docs/publish/seo.sections/what-the-build-adds.md +2 -2
- package/agent-docs/publish/seo.sections/write-the-page-title-and-summary.md +2 -2
- package/agent-docs/publish/single-source-sites.md +5 -5
- package/agent-docs/publish/troubleshooting.md +10 -10
- package/agent-docs/publish/vercel.md +5 -5
- package/agent-docs/publish/vercel.sections/check-the-deployment.md +1 -1
- package/agent-docs/publish/vercel.sections/include-an-mcp-endpoint.md +2 -2
- package/agent-docs/publish/vercel.sections/prepare-your-project.md +2 -2
- package/agent-docs/publish/vercel.sections/related-reading.md +1 -1
- package/agent-docs/publish.md +2 -2
- package/agent-docs/recipes/add-page.md +5 -5
- package/agent-docs/recipes/add-page.sections/audit-the-shoalrun-docs-project.md +2 -2
- package/agent-docs/recipes/add-page.sections/before-you-start.md +1 -1
- package/agent-docs/recipes/add-page.sections/build-the-shoalrun-docs-site.md +2 -2
- package/agent-docs/recipes/add-page.sections/check-agent-search-and-page-lookup.md +1 -1
- package/agent-docs/recipes/add-page.sections/check-the-built-page-artifacts.md +1 -1
- package/agent-docs/recipes/add-page.sections/check-the-outcome.md +1 -1
- package/agent-docs/recipes/add-page.sections/complete-the-guide-and-add-navigation.md +2 -2
- package/agent-docs/recipes/add-page.sections/install-the-site-dependencies.md +1 -1
- package/agent-docs/recipes/add-page.sections/regenerate-the-agent-documentation-bundle.md +2 -2
- package/agent-docs/recipes/add-page.sections/related-reading.md +1 -1
- package/agent-docs/recipes/add-page.sections/scaffold-a-new-guide.md +1 -1
- package/agent-docs/recipes/audit-docs.md +4 -4
- package/agent-docs/recipes/build-docs.md +2 -2
- package/agent-docs/recipes/preview-hybrid-search.md +5 -5
- package/agent-docs/recipes/preview-page.md +2 -2
- package/agent-docs/recipes/queue-email.md +2 -2
- package/agent-docs/recipes/refresh-agent-docs.md +4 -4
- package/agent-docs/recipes/send-welcome-email.md +13 -13
- package/agent-docs/reference/agent-skills.md +7 -7
- package/agent-docs/search-and-chat.md +4 -4
- package/agent-docs/search-index.json +1 -1
- package/agent-docs/start.md +5 -5
- package/agent-docs/start.sections/add-the-page-to-navigation.md +3 -3
- package/agent-docs/start.sections/build-and-check-both-outputs.md +3 -3
- package/agent-docs/start.sections/build-this-site.md +2 -2
- package/agent-docs/start.sections/check-writing-style.md +2 -2
- package/agent-docs/start.sections/create-a-page.md +2 -2
- package/agent-docs/start.sections/make-it-yours.md +2 -2
- package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
- package/agent-docs/start.sections/prerequisites.md +2 -2
- package/agent-docs/start.sections/related-reading.md +2 -2
- package/agent-docs/start.sections/start-your-own-project.md +3 -3
- package/agent-docs/status.md +14 -4
- package/agent-docs/styling/color-modes.md +2 -2
- package/agent-docs/styling/footer.md +2 -2
- package/agent-docs/styling/header.md +2 -2
- package/agent-docs/styling/layouts.md +3 -3
- package/agent-docs/styling/layouts.sections/build-a-landing-page.md +1 -1
- package/agent-docs/styling/layouts.sections/build-a-splash-page.md +1 -1
- package/agent-docs/styling/layouts.sections/control-navigation-tabs.md +2 -2
- package/agent-docs/styling/layouts.sections/customize-the-hero.md +1 -1
- package/agent-docs/styling/layouts.sections/hero.md +1 -1
- package/agent-docs/styling/layouts.sections/hide-the-table-of-contents-or-give-content-more-room.md +1 -1
- package/agent-docs/styling/layouts.sections/html-markdown-and-agents.md +2 -2
- package/agent-docs/styling/layouts.sections/related-reading.md +1 -1
- package/agent-docs/styling/palettes.md +3 -3
- package/agent-docs/styling/share-images.md +3 -3
- package/agent-docs/styling/themes.md +2 -2
- package/agent-docs/styling/try.md +2 -2
- package/agent-docs/what-is-shoalrun.md +7 -3
- package/assets/ask-widget.js +20 -6
- package/assets/navigation.js +5 -0
- package/dist/api-materialize.d.ts +2 -1
- package/dist/api-materialize.js +21 -9
- package/dist/api-publication-plan.d.ts +2 -0
- package/dist/api-publication-plan.js +23 -7
- package/dist/api-publication-review.js +4 -3
- package/dist/api-selection.d.ts +5 -2
- package/dist/api-selection.js +18 -11
- package/dist/artifact-bundle.js +9 -6
- package/dist/ask-runtime.d.ts +1 -0
- package/dist/ask-runtime.js +7 -2
- package/dist/authored-change.js +2 -1
- package/dist/authoring-project.js +1 -1
- package/dist/cards.js +2 -1
- package/dist/cli-discovery.d.ts +2 -2
- package/dist/cli-discovery.js +9 -4
- package/dist/cli.js +48 -23
- package/dist/compiler-config.d.ts +17 -0
- package/dist/compiler-config.js +43 -2
- package/dist/compiler.d.ts +21 -0
- package/dist/compiler.js +16 -12
- package/dist/component-transform.d.ts +2 -4
- package/dist/component-transform.js +20 -7
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -1
- package/dist/content-delivery-contract.d.ts +2 -1
- package/dist/content-delivery-validation.d.ts +2 -2
- package/dist/content-delivery-validation.js +6 -4
- package/dist/content-export-command.d.ts +1 -1
- package/dist/content-export-command.js +4 -4
- package/dist/content-export-comparison.js +6 -5
- package/dist/content-export-config.js +3 -1
- package/dist/content-export.js +9 -8
- package/dist/content-rest-client.js +4 -2
- package/dist/content-rest-contract.d.ts +2 -2
- package/dist/content-rest-server.js +11 -6
- package/dist/content-source.d.ts +13 -0
- package/dist/content-source.js +5 -2
- package/dist/content-workspace.d.ts +12 -0
- package/dist/content-workspace.js +2 -1
- package/dist/content.js +3 -2
- package/dist/cookbook-chooser.js +2 -1
- package/dist/deployment-profile.d.ts +2 -1
- package/dist/deployment-profile.js +38 -8
- package/dist/dev.d.ts +3 -1
- package/dist/dev.js +99 -12
- package/dist/docs-author.js +2 -1
- package/dist/docs-command.js +2 -2
- package/dist/docs-eval.d.ts +1 -0
- package/dist/docs-eval.js +2 -2
- package/dist/docs-mcp.d.ts +1 -0
- package/dist/docs-mcp.js +10 -5
- package/dist/docs-tool.d.ts +4 -10
- package/dist/document-sync.d.ts +1 -0
- package/dist/document-sync.js +2 -2
- package/dist/documentation-core.d.ts +29 -10
- package/dist/documentation-core.js +38 -4
- package/dist/freshness.js +2 -2
- package/dist/frontmatter.js +13 -7
- package/dist/function-runtime.d.ts +1 -0
- package/dist/index-build.d.ts +1 -0
- package/dist/index-build.js +2 -2
- package/dist/ingredient-draft.js +20 -10
- package/dist/mcp-analytics.d.ts +1 -0
- package/dist/mcp-artifacts.js +13 -4
- package/dist/mcp-config.d.ts +1 -0
- package/dist/mcp-config.js +3 -1
- package/dist/mcp-http.js +1 -1
- package/dist/page-materialization.d.ts +3 -4
- package/dist/page-materialization.js +15 -8
- package/dist/page-renderer.d.ts +6 -0
- package/dist/page-renderer.js +16 -5
- package/dist/project-navigation.js +2 -1
- package/dist/publication-identity.d.ts +12 -0
- package/dist/publication-identity.js +17 -0
- package/dist/publication-manifest.d.ts +24 -1
- package/dist/publication-manifest.js +14 -6
- package/dist/publication-plan.js +21 -9
- package/dist/publication-render.js +24 -8
- package/dist/recipe-draft.js +9 -6
- package/dist/scaffold.d.ts +7 -4
- package/dist/scaffold.js +16 -16
- package/dist/search-query.d.ts +4 -10
- package/dist/search-query.js +10 -9
- package/dist/server.d.ts +8 -0
- package/dist/server.js +14 -3
- package/dist/subject-deprecation.js +2 -1
- package/dist/vercel-function.js +1 -1
- package/example-configs/products/README.md +37 -0
- package/example-configs/products/content/operations.mdx +50 -0
- package/example-configs/products/content/payments-v2.mdx +30 -0
- package/example-configs/products/content/payments-v3.mdx +38 -0
- package/example-configs/products/content/priority-settlement.mdx +23 -0
- package/example-configs/products/content/reporting-v1.mdx +36 -0
- package/example-configs/products/content/scheduled-exports.mdx +23 -0
- package/example-configs/products/docs.config.yaml +56 -0
- package/example-configs/products/profiles/all-releases.yaml +9 -0
- package/example-configs/products/profiles/customer-a.yaml +13 -0
- package/example-configs/products/profiles/customer-b.yaml +13 -0
- package/example-configs/products/skus.yaml +11 -0
- package/examples/content-delivery/preview.mjs +1 -1
- package/package.json +1 -1
- package/schemas/content-export.schema.json +41 -3
- package/schemas/content-rest.openapi.json +184 -37
- package/skills/shoalrun-author/SKILL.md +6 -2
- package/skills/shoalrun-author/references/customer-editions.md +34 -4
- package/skills/shoalrun-author/references/publications.md +60 -0
- package/skills/shoalrun-recipes/SKILL.md +2 -0
- package/skills/shoalrun-setup/SKILL.md +3 -1
- package/styles/header.css +3 -0
- package/styles/site.css +3 -0
- package/agent-docs/publish/content-export.sections/export-selected-pages.md +0 -116
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { samePublication } from './publication-identity.js';
|
|
1
2
|
import { ContentDeliveryError, contentRefKey } from './content-delivery-contract.js';
|
|
2
3
|
const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
3
4
|
const keys = (value, allowed) => object(value) && Object.keys(value).every(key => allowed.includes(key));
|
|
@@ -6,8 +7,7 @@ const digestPattern = /^[a-f0-9]{64}$/;
|
|
|
6
7
|
const pathPattern = /^(?:NOTICES\.txt|(?:content|assets)\/[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*)$/;
|
|
7
8
|
export const safeContentPath = (value) => typeof value === 'string' && pathPattern.test(value) && value.split('/').every(part => part !== '.' && part !== '..');
|
|
8
9
|
const invalid = (message) => { throw new ContentDeliveryError('invalid_manifest', message); };
|
|
9
|
-
export const validContentPublication = (value) =>
|
|
10
|
-
const samePublication = (left, right) => ['channel', 'version', 'language'].every(key => left[key] === right[key]);
|
|
10
|
+
export const validContentPublication = (value) => keys(value, ['channel', 'version', 'language', 'product']) && ['channel', 'version', 'language'].every(key => nonempty(value[key])) && (value.product === undefined ? !Object.hasOwn(value, 'product') : nonempty(value.product));
|
|
11
11
|
export function validContentRef(value) {
|
|
12
12
|
if (!object(value))
|
|
13
13
|
return false;
|
|
@@ -27,11 +27,11 @@ function safeExternal(value, image = false) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
export function validateContentManifest(value, maxResources = 10_000, maxResourceBytes = 8_000_000) {
|
|
30
|
-
if (!keys(value, ['schemaVersion', 'kind', 'digest', 'publicBase', 'publication', 'review', 'resources', 'assets', 'files', 'diagnostics']) || value.schemaVersion
|
|
30
|
+
if (!keys(value, ['schemaVersion', 'kind', 'digest', 'publicBase', 'publication', 'review', 'resources', 'assets', 'files', 'diagnostics']) || ![1, 2].includes(value.schemaVersion) || value.kind !== 'shoalrun-content-export' || !digestPattern.test(value.digest ?? ''))
|
|
31
31
|
invalid('Unsupported content manifest.');
|
|
32
32
|
if (typeof value.publicBase !== 'string' || !/^\/(?:[A-Za-z0-9_~.-]+\/)*$/.test(value.publicBase) || value.publicBase.split('/').some((part) => part === '.' || part === '..'))
|
|
33
33
|
invalid('Invalid content mount.');
|
|
34
|
-
if (!validContentPublication(value.publication))
|
|
34
|
+
if (!validContentPublication(value.publication) || value.schemaVersion !== (value.publication.product === undefined ? 1 : 2))
|
|
35
35
|
invalid('Invalid publication.');
|
|
36
36
|
if (!keys(value.review, ['status', 'apis']) || value.review.status !== 'ok' || !Array.isArray(value.review.apis) || value.review.apis.some((api) => !keys(api, ['apiId', 'digest']) || !nonempty(api.apiId) || !digestPattern.test(api.digest ?? '')))
|
|
37
37
|
invalid('Content must have approved API review metadata.');
|
|
@@ -57,6 +57,8 @@ export function validateContentManifest(value, maxResources = 10_000, maxResourc
|
|
|
57
57
|
}
|
|
58
58
|
/** Shared metadata validation; transport supplies its file/asset inventory policy. */
|
|
59
59
|
export function validateContentResources(resources, expectedPublication, assets, checkRepresentation, publicBase = '/') {
|
|
60
|
+
if (!validContentPublication(expectedPublication))
|
|
61
|
+
invalid('Invalid expected publication.');
|
|
60
62
|
const refs = new Set();
|
|
61
63
|
const links = [];
|
|
62
64
|
for (const resource of resources) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const exportHelp = "Usage: shoalrun export [config] --out DIRECTORY [--target NAME]\n [--format markdown|html|both] [--document ID]...\n [--channel C --version V --language L] [--public-base /help/] [--review]\n [--profile FILE] [--previous-manifest FILE] [--fail-on-removed]\n\nExport selected pages, sections, and named snippets as Markdown and passive HTML.\nConfigure typed resources in an export target; --document selects whole pages.\nNavigation, facets, and a prior website build are not required.\n--review writes an API-review candidate; status needs-review exits 2 until pinned.\n--previous-manifest compares public references with an earlier reviewed export.\n--fail-on-removed requires that baseline and refuses to replace output if references disappear.\n";
|
|
1
|
+
export declare const exportHelp = "Usage: shoalrun export [config] --out DIRECTORY [--target NAME]\n [--format markdown|html|both] [--document ID]...\n [--channel C --version V --language L [--product P]] [--public-base /help/] [--review]\n [--profile FILE] [--previous-manifest FILE] [--fail-on-removed]\n\nExport selected pages, sections, and named snippets as Markdown and passive HTML.\nConfigure typed resources in an export target; --document selects whole pages.\nNavigation, facets, and a prior website build are not required.\n--review writes an API-review candidate; status needs-review exits 2 until pinned.\n--previous-manifest compares public references with an earlier reviewed export.\n--fail-on-removed requires that baseline and refuses to replace output if references disappear.\n";
|
|
2
2
|
export declare function runExportCommand(args: string[]): Promise<{
|
|
3
3
|
status: string;
|
|
4
4
|
output: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { exportContent } from './content-export.js';
|
|
2
2
|
export const exportHelp = `Usage: shoalrun export [config] --out DIRECTORY [--target NAME]
|
|
3
3
|
[--format markdown|html|both] [--document ID]...
|
|
4
|
-
[--channel C --version V --language L] [--public-base /help/] [--review]
|
|
4
|
+
[--channel C --version V --language L [--product P]] [--public-base /help/] [--review]
|
|
5
5
|
[--profile FILE] [--previous-manifest FILE] [--fail-on-removed]
|
|
6
6
|
|
|
7
7
|
Export selected pages, sections, and named snippets as Markdown and passive HTML.
|
|
@@ -30,7 +30,7 @@ export async function runExportCommand(args) {
|
|
|
30
30
|
continue;
|
|
31
31
|
}
|
|
32
32
|
if (arg.startsWith('--')) {
|
|
33
|
-
if (!['--out', '--target', '--format', '--document', '--channel', '--version', '--language', '--public-base', '--previous-manifest', '--profile'].includes(arg) || !args[index + 1] || args[index + 1].startsWith('--'))
|
|
33
|
+
if (!['--out', '--target', '--format', '--document', '--channel', '--version', '--language', '--product', '--public-base', '--previous-manifest', '--profile'].includes(arg) || !args[index + 1] || args[index + 1].startsWith('--'))
|
|
34
34
|
throw new Error(exportHelp);
|
|
35
35
|
const value = args[++index];
|
|
36
36
|
if (arg === '--document') {
|
|
@@ -56,10 +56,10 @@ export async function runExportCommand(args) {
|
|
|
56
56
|
if (format)
|
|
57
57
|
options.formats = format === 'both' ? ['markdown', 'html'] : [format];
|
|
58
58
|
const coordinates = ['--channel', '--version', '--language'].map(key => values.get(key));
|
|
59
|
-
if (coordinates.some(Boolean)) {
|
|
59
|
+
if (coordinates.some(Boolean) || values.has('--product')) {
|
|
60
60
|
if (!coordinates.every(Boolean))
|
|
61
61
|
throw new Error('Select all three export publication coordinates: --channel, --version, and --language');
|
|
62
|
-
options.publication = { channel: coordinates[0], version: coordinates[1], language: coordinates[2] };
|
|
62
|
+
options.publication = { channel: coordinates[0], version: coordinates[1], language: coordinates[2], ...(values.has('--product') ? { product: values.get('--product') } : {}) };
|
|
63
63
|
}
|
|
64
64
|
options.profile = values.get('--profile');
|
|
65
65
|
options.target = values.get('--target');
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { validContentPublication } from './content-delivery-validation.js';
|
|
1
2
|
import { contentRefKey } from './content-delivery-contract.js';
|
|
2
3
|
const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
3
4
|
const nonempty = (value) => typeof value === 'string' && value.length > 0 && value.trim() === value;
|
|
4
|
-
const keyFor = ({ publication, ref }) => JSON.stringify([publication.channel, publication.version, publication.language, contentRefKey(ref)]);
|
|
5
|
+
const keyFor = ({ publication, ref }) => JSON.stringify([publication.channel, publication.version, publication.language, ...(publication.product === undefined ? [] : [publication.product]), contentRefKey(ref)]);
|
|
5
6
|
/** Validate the public identity surface, without reading files or executing source. */
|
|
6
7
|
function references(manifest, label, requireReviewed) {
|
|
7
8
|
const fail = () => { throw new Error(`${label} must be a content export manifest with valid, unique public resource references`); };
|
|
8
|
-
if (!object(manifest) || manifest.schemaVersion !== 1 || manifest.kind !== 'shoalrun-content-export' || !Array.isArray(manifest.resources) || !manifest.resources.length)
|
|
9
|
+
if (!object(manifest) || manifest.schemaVersion !== 1 && manifest.schemaVersion !== 2 || manifest.kind !== 'shoalrun-content-export' || !Array.isArray(manifest.resources) || !manifest.resources.length)
|
|
9
10
|
return fail();
|
|
10
11
|
const publication = manifest.publication;
|
|
11
|
-
if (!
|
|
12
|
+
if (!validContentPublication(publication) || !object(publication) || manifest.schemaVersion !== (publication.product === undefined ? 1 : 2))
|
|
12
13
|
return fail();
|
|
13
14
|
if (!object(manifest.review) || !['ok', 'required'].includes(String(manifest.review.status)))
|
|
14
15
|
return fail();
|
|
@@ -18,13 +19,13 @@ function references(manifest, label, requireReviewed) {
|
|
|
18
19
|
for (const resource of manifest.resources) {
|
|
19
20
|
if (!object(resource) || !object(resource.ref) || !object(resource.publication))
|
|
20
21
|
return fail();
|
|
21
|
-
if (
|
|
22
|
+
if (!validContentPublication(resource.publication) || !['channel', 'version', 'language', 'product'].every(key => resource.publication && resource.publication[key] === publication[key]))
|
|
22
23
|
return fail();
|
|
23
24
|
const ref = resource.ref;
|
|
24
25
|
const keys = ref.kind === 'page' ? ['kind', 'documentId'] : ref.kind === 'section' ? ['kind', 'documentId', 'sectionId'] : ref.kind === 'snippet' ? ['kind', 'id'] : [];
|
|
25
26
|
if (!keys.length || Object.keys(ref).length !== keys.length || !keys.every(key => nonempty(ref[key])))
|
|
26
27
|
return fail();
|
|
27
|
-
const entry = { publication: { channel: publication.channel, version: publication.version, language: publication.language }, ref: { ...ref } };
|
|
28
|
+
const entry = { publication: { channel: publication.channel, version: publication.version, language: publication.language, ...(publication.product !== undefined ? { product: publication.product } : {}) }, ref: { ...ref } };
|
|
28
29
|
const key = keyFor(entry);
|
|
29
30
|
if (result.has(key))
|
|
30
31
|
return fail();
|
|
@@ -66,8 +66,10 @@ export function validateExportTarget(value, readerFilters) {
|
|
|
66
66
|
};
|
|
67
67
|
let publication;
|
|
68
68
|
if (value.publication !== undefined) {
|
|
69
|
-
if (!isConfigMapping(value.publication) || Object.keys(value.publication).some(key => !['channel', 'version', 'language'].includes(key)) || ['channel', 'version', 'language'].some(key => typeof value.publication === 'object' && (typeof value.publication[key] !== 'string' || !value.publication[key].trim())))
|
|
69
|
+
if (!isConfigMapping(value.publication) || Object.keys(value.publication).some(key => !['channel', 'version', 'language', 'product'].includes(key)) || ['channel', 'version', 'language'].some(key => typeof value.publication === 'object' && (typeof value.publication[key] !== 'string' || !value.publication[key].trim())))
|
|
70
70
|
throw new Error('Export publication needs channel, version, and language');
|
|
71
|
+
if (value.publication.product !== undefined && !nonempty(value.publication.product))
|
|
72
|
+
throw new Error('Export publication product must be nonempty text');
|
|
71
73
|
publication = value.publication;
|
|
72
74
|
}
|
|
73
75
|
if (value.apiReview !== undefined && (!isConfigMapping(value.apiReview) || Object.values(value.apiReview).some(digest => typeof digest !== 'string' || !/^[a-f0-9]{64}$/.test(digest))))
|
package/dist/content-export.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { documentKey, samePublication } from './publication-identity.js';
|
|
1
2
|
import { pruneFeatureTree, profileSelection } from './deployment-profile.js';
|
|
2
3
|
import { readFile, realpath } from 'node:fs/promises';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
6
|
import { loadConfig, explainSegments } from './config.js';
|
|
6
|
-
import { configField, isConfigMapping, requirePublicationsSection, requireSiteSection, resolvedCompilerConfig } from './compiler-config.js';
|
|
7
|
+
import { configField, isConfigMapping, requirePublicationsSection, resolvePublication, requireSiteSection, resolvedCompilerConfig } from './compiler-config.js';
|
|
7
8
|
import { defaultLanguage } from './frontmatter.js';
|
|
8
9
|
import { normalizeBasePath, sitePath } from './site-path.js';
|
|
9
10
|
import { prepareContentWorkspace } from './content-workspace.js';
|
|
@@ -32,13 +33,13 @@ import { isolateExportTree, markExportSource, exportHeadingInventory, preserveEx
|
|
|
32
33
|
import { selectSection } from './section-identity.js';
|
|
33
34
|
import { compareContentManifests } from './content-export-comparison.js';
|
|
34
35
|
const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
35
|
-
const keyFor = (doc) =>
|
|
36
|
-
const resourceIdentity = (item) => JSON.stringify([item.ref.kind, item.ref.kind === 'snippet' ? item.ref.id : item.ref.documentId, item.ref.kind === 'section' ? item.ref.sectionId : null, item.doc.variant.channel, item.doc.variant.version, item.doc.variant.language]);
|
|
36
|
+
const keyFor = (doc) => documentKey(doc.frontmatter.id, doc.variant);
|
|
37
|
+
const resourceIdentity = (item) => JSON.stringify([item.ref.kind, item.ref.kind === 'snippet' ? item.ref.id : item.ref.documentId, item.ref.kind === 'section' ? item.ref.sectionId : null, item.doc.variant.channel, item.doc.variant.version, item.doc.variant.language, ...(item.doc.variant.product === undefined ? [] : [item.doc.variant.product])]);
|
|
37
38
|
// Pages and their sections share a source; named snippet instances do not.
|
|
38
|
-
const sourceKeyFor = (doc, kind = 'document') => JSON.stringify([kind, doc.frontmatter.id, doc.variant.channel, doc.variant.version, doc.variant.language]);
|
|
39
|
+
const sourceKeyFor = (doc, kind = 'document') => JSON.stringify([kind, doc.frontmatter.id, doc.variant.channel, doc.variant.version, doc.variant.language, ...(doc.variant.product === undefined ? [] : [doc.variant.product])]);
|
|
39
40
|
const selectedSourceKey = (item) => sourceKeyFor(item.doc, item.ref.kind === 'snippet' ? 'snippet' : 'document');
|
|
40
41
|
const resourceKey = (item) => `resource-${exportDigest(resourceIdentity(item)).slice(0, 24)}`;
|
|
41
|
-
const sameVariant =
|
|
42
|
+
const sameVariant = samePublication;
|
|
42
43
|
const visitTree = (node, visit) => {
|
|
43
44
|
if (!node || typeof node !== 'object')
|
|
44
45
|
return;
|
|
@@ -77,9 +78,9 @@ export async function exportContent(configFile, destination, options = {}) {
|
|
|
77
78
|
const target = validateExportTarget({ ...raw, ...(options.formats ? { formats: options.formats } : {}), ...(options.documents ? { documents: options.documents } : {}), ...(options.publication ? { publication: options.publication } : {}), ...(options.publicBase ? { publicBase: options.publicBase } : {}) }, config.readerFilters);
|
|
78
79
|
const language = defaultLanguage(config);
|
|
79
80
|
const enabled = config.publications.enabled;
|
|
80
|
-
if (!Array.isArray(enabled) || !enabled.length || enabled.some(value => !isConfigMapping(value)
|
|
81
|
+
if (!Array.isArray(enabled) || !enabled.length || enabled.some(value => !isConfigMapping(value)))
|
|
81
82
|
throw new Error('publications.enabled must declare valid publication combinations');
|
|
82
|
-
const variants = enabled.map(value => (
|
|
83
|
+
const variants = enabled.map(value => resolvePublication(publications, value, language));
|
|
83
84
|
const unique = [...new Map(variants.map(variant => [JSON.stringify(variant), variant])).values()];
|
|
84
85
|
const publication = target.publication ?? (unique.length === 1 ? unique[0] : undefined);
|
|
85
86
|
if (!publication)
|
|
@@ -431,7 +432,7 @@ export async function exportContent(configFile, destination, options = {}) {
|
|
|
431
432
|
notices += `\n${path.basename(file)}:\n${await readFile(resolvedNotice, 'utf8')}\n`;
|
|
432
433
|
}
|
|
433
434
|
artifacts.set('NOTICES.txt', notices);
|
|
434
|
-
const manifest = { schemaVersion: 1, kind: 'shoalrun-content-export', publicBase: target.publicBase, publication,
|
|
435
|
+
const manifest = { schemaVersion: publication.product === undefined ? 1 : 2, kind: 'shoalrun-content-export', publicBase: target.publicBase, publication,
|
|
435
436
|
review: { status: unreviewed.length ? 'required' : 'ok', apis: reviews.map(row => ({ apiId: row.apiId, digest: row.digest })) },
|
|
436
437
|
resources: records, assets: [...assets.records.values()].sort((a, b) => compare(a.path, b.path)),
|
|
437
438
|
files: [...artifacts].map(([filename, content]) => ({ path: filename, bytes: Buffer.byteLength(content), digest: exportDigest(content) })).sort((a, b) => compare(a.path, b.path)), diagnostics };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { samePublication } from './publication-identity.js';
|
|
1
2
|
import { ContentDeliveryError, contentRefKey } from './content-delivery-contract.js';
|
|
2
3
|
import { contentResourceKey } from './content-rest-contract.js';
|
|
3
4
|
import { validContentPublication, validContentRef, validateContentResources, safeContentPath } from './content-delivery-validation.js';
|
|
@@ -5,7 +6,6 @@ import { freeze, sha256, readBounded } from './content-delivery-transport.js';
|
|
|
5
6
|
const digestPattern = /^[a-f0-9]{64}$/;
|
|
6
7
|
const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
7
8
|
const exactKeys = (value, keys) => record(value) && Object.keys(value).length === keys.length && Object.keys(value).every(key => keys.includes(key));
|
|
8
|
-
const samePublication = (left, right) => left.channel === right.channel && left.version === right.version && left.language === right.language;
|
|
9
9
|
const invalid = (message) => { throw new ContentDeliveryError('invalid_manifest', message); };
|
|
10
10
|
/** Preloads a REST inventory and pins all subsequent reads to that revision. */
|
|
11
11
|
export async function openRestContentSource(options) {
|
|
@@ -39,6 +39,8 @@ export async function openRestContentSource(options) {
|
|
|
39
39
|
url.pathname = baseUrl.pathname.replace(/\/$/, '') + '/resources' + suffix;
|
|
40
40
|
for (const key of ['channel', 'version', 'language'])
|
|
41
41
|
url.searchParams.set(key, publication[key]);
|
|
42
|
+
if (publication.product !== undefined)
|
|
43
|
+
url.searchParams.set('product', publication.product);
|
|
42
44
|
if (revision !== undefined)
|
|
43
45
|
url.searchParams.set('revision', revision);
|
|
44
46
|
return url;
|
|
@@ -103,7 +105,7 @@ export async function openRestContentSource(options) {
|
|
|
103
105
|
throw error;
|
|
104
106
|
return invalid('REST inventory is not valid UTF-8 JSON.');
|
|
105
107
|
}
|
|
106
|
-
if (!exactKeys(envelope, ['schemaVersion', 'revision', 'publication', 'resources']) || envelope.schemaVersion !== 1 || !digestPattern.test(envelope.revision ?? '') || !validContentPublication(envelope.publication) || !samePublication(envelope.publication, publication))
|
|
108
|
+
if (!exactKeys(envelope, ['schemaVersion', 'revision', 'publication', 'resources']) || envelope.schemaVersion !== (publication.product === undefined ? 1 : 2) || !digestPattern.test(envelope.revision ?? '') || !validContentPublication(envelope.publication) || !samePublication(envelope.publication, publication))
|
|
107
109
|
invalid('Invalid REST inventory identity.');
|
|
108
110
|
if (requestedRevision !== undefined && requestedRevision !== envelope.revision)
|
|
109
111
|
throw new ContentDeliveryError('stale_revision', 'REST inventory differs from the requested revision.');
|
|
@@ -6,13 +6,13 @@ export type ContentRestEntry = {
|
|
|
6
6
|
resource: ContentResource;
|
|
7
7
|
};
|
|
8
8
|
export type ContentRestList = {
|
|
9
|
-
schemaVersion: 1;
|
|
9
|
+
schemaVersion: 1 | 2;
|
|
10
10
|
revision: string;
|
|
11
11
|
publication: ContentPublication;
|
|
12
12
|
resources: ContentRestEntry[];
|
|
13
13
|
};
|
|
14
14
|
export type ContentRestResource = {
|
|
15
|
-
schemaVersion: 1;
|
|
15
|
+
schemaVersion: 1 | 2;
|
|
16
16
|
revision: string;
|
|
17
17
|
publication: ContentPublication;
|
|
18
18
|
key: string;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ContentDeliveryError, contentRefKey } from './content-delivery-contract.js';
|
|
2
|
+
import { validContentPublication } from './content-delivery-validation.js';
|
|
2
3
|
import { contentResourceKey } from './content-rest-contract.js';
|
|
3
|
-
const publicationKey = (publication) => JSON.stringify([publication.channel, publication.version, publication.language]);
|
|
4
|
+
const publicationKey = (publication) => JSON.stringify([publication.channel, publication.version, publication.language, ...(publication.product === undefined ? [] : [publication.product])]);
|
|
4
5
|
const digest = async (bytes) => [...new Uint8Array(await crypto.subtle.digest('SHA-256', bytes))].map(value => value.toString(16).padStart(2, '0')).join('');
|
|
5
6
|
const encoder = new TextEncoder();
|
|
6
|
-
const validPublication =
|
|
7
|
+
const validPublication = validContentPublication;
|
|
7
8
|
const canonical = (value) => Array.isArray(value) ? value.map(canonical) : value && typeof value === 'object' ? Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key])])) : value;
|
|
8
9
|
const same = (left, right) => JSON.stringify(canonical(left)) === JSON.stringify(canonical(right));
|
|
9
10
|
/** Serve already-approved, pinned snapshots. The caller retains source ownership. */
|
|
@@ -38,16 +39,20 @@ export function createContentRestHandler(options) {
|
|
|
38
39
|
const parts = url.pathname.slice(prefix.length).split('/').slice(1);
|
|
39
40
|
if (parts.length !== 0 && parts.length !== 1 && !(parts.length === 3 && parts[1] === 'representations'))
|
|
40
41
|
return error(404, 'not_found', 'Unknown content route.');
|
|
41
|
-
const allowed = new Set(['channel', 'version', 'language', 'revision']);
|
|
42
|
+
const allowed = new Set(['channel', 'version', 'language', 'product', 'revision']);
|
|
42
43
|
if ([...url.searchParams.keys()].some(key => !allowed.has(key) || url.searchParams.getAll(key).length !== 1))
|
|
43
44
|
return error(400, 'invalid_request', 'Unknown or repeated query parameter.');
|
|
44
45
|
const publication = Object.fromEntries(['channel', 'version', 'language'].map(key => [key, url.searchParams.get(key)]));
|
|
45
|
-
if (
|
|
46
|
+
if (url.searchParams.has('product'))
|
|
47
|
+
publication.product = url.searchParams.get('product');
|
|
48
|
+
if (!validPublication(publication))
|
|
46
49
|
return error(400, 'invalid_request', 'channel, version, and language are required.');
|
|
47
50
|
const revision = url.searchParams.get('revision');
|
|
48
51
|
if (revision !== null && !/^[a-f0-9]{64}$/.test(revision) || parts.length > 0 && revision === null)
|
|
49
52
|
return error(400, 'invalid_request', 'A valid revision is required for resource requests.');
|
|
50
53
|
const selected = publications.get(publicationKey(publication));
|
|
54
|
+
if (!selected && publication.product === undefined && [...publications.values()].some(item => item.publication.product !== undefined && item.publication.channel === publication.channel && item.publication.version === publication.version && item.publication.language === publication.language))
|
|
55
|
+
return error(400, 'invalid_request', 'product is required for product-scoped publications.');
|
|
51
56
|
if (!selected)
|
|
52
57
|
return error(404, 'not_found', 'Publication not found.');
|
|
53
58
|
if (revision !== null && revision !== selected.revision)
|
|
@@ -59,9 +64,9 @@ export function createContentRestHandler(options) {
|
|
|
59
64
|
let body;
|
|
60
65
|
let mediaType = 'application/json';
|
|
61
66
|
if (!parts.length)
|
|
62
|
-
body = JSON.stringify({ schemaVersion: 1, revision: selected.revision, publication: selected.publication, resources: selected.resources });
|
|
67
|
+
body = JSON.stringify({ schemaVersion: selected.publication.product === undefined ? 1 : 2, revision: selected.revision, publication: selected.publication, resources: selected.resources });
|
|
63
68
|
else if (parts.length === 1)
|
|
64
|
-
body = JSON.stringify({ schemaVersion: 1, revision: selected.revision, publication: selected.publication, ...resource });
|
|
69
|
+
body = JSON.stringify({ schemaVersion: selected.publication.product === undefined ? 1 : 2, revision: selected.revision, publication: selected.publication, ...resource });
|
|
65
70
|
else {
|
|
66
71
|
const format = parts[2];
|
|
67
72
|
if (!['html', 'markdown'].includes(format) || !resource.resource.representations[format])
|
package/dist/content-source.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { SubjectDeprecation, ResolvedSubjectDeprecation } from './subject-d
|
|
|
3
3
|
import type { ReaderSelection } from './reader-filters.js';
|
|
4
4
|
import type { StandaloneSectionDeclaration } from './section-identity.js';
|
|
5
5
|
export type Variant = {
|
|
6
|
+
product?: string;
|
|
6
7
|
channel: string;
|
|
7
8
|
version: string;
|
|
8
9
|
language: string;
|
|
@@ -18,9 +19,14 @@ export type Frontmatter = {
|
|
|
18
19
|
updated?: string;
|
|
19
20
|
verified?: string;
|
|
20
21
|
releaseVersion?: string;
|
|
22
|
+
availability?: {
|
|
23
|
+
since?: string;
|
|
24
|
+
through?: string;
|
|
25
|
+
};
|
|
21
26
|
channel?: string;
|
|
22
27
|
version?: string;
|
|
23
28
|
publications?: Array<{
|
|
29
|
+
product?: string;
|
|
24
30
|
channel: string;
|
|
25
31
|
version: string;
|
|
26
32
|
}>;
|
|
@@ -92,6 +98,13 @@ export type PublicationRoutingConfig = {
|
|
|
92
98
|
versions: Record<string, {
|
|
93
99
|
pathPrefix?: string;
|
|
94
100
|
}>;
|
|
101
|
+
products?: Record<string, {
|
|
102
|
+
pathPrefix: string;
|
|
103
|
+
defaultVersion: string;
|
|
104
|
+
versions: Record<string, {
|
|
105
|
+
pathPrefix?: string;
|
|
106
|
+
}>;
|
|
107
|
+
}>;
|
|
95
108
|
};
|
|
96
109
|
};
|
|
97
110
|
export declare function readDocument(file: string, frontmatterConfig?: unknown, enrich?: (source: Record<string, unknown>) => Promise<Record<string, unknown>>, sourceText?: string): Promise<{
|
package/dist/content-source.js
CHANGED
|
@@ -26,7 +26,10 @@ export async function readDocument(file, frontmatterConfig, enrich, sourceText)
|
|
|
26
26
|
}
|
|
27
27
|
export function routeFor(frontmatter, variant, config) {
|
|
28
28
|
const channel = config.publications.channels[variant.channel];
|
|
29
|
-
const
|
|
29
|
+
const product = variant.product === undefined ? undefined : config.publications.products?.[variant.product];
|
|
30
|
+
if (variant.product !== undefined && !product)
|
|
31
|
+
throw new Error(`Unknown publication product ${variant.product}`);
|
|
32
|
+
const version = (product?.versions ?? config.publications.versions)[variant.version];
|
|
30
33
|
if (!channel || !version)
|
|
31
34
|
throw new Error(`Unknown publication ${variant.channel}/${variant.version}`);
|
|
32
35
|
const slug = frontmatter.slug;
|
|
@@ -35,7 +38,7 @@ export function routeFor(frontmatter, variant, config) {
|
|
|
35
38
|
if (/^\/(?:\.well-known|api)(?:\/|$)/i.test(slug))
|
|
36
39
|
throw new Error(`${frontmatter.id}: slug uses a reserved discovery path`);
|
|
37
40
|
const languagePrefix = variant.language === defaultLanguage(config) ? '' : `/${variant.language}`;
|
|
38
|
-
const parts = [normalizeBasePath(config.site.basePath), languagePrefix, channel.pathPrefix ?? '', version.pathPrefix ?? '', slug].filter(Boolean);
|
|
41
|
+
const parts = [normalizeBasePath(config.site.basePath), languagePrefix, product?.pathPrefix ?? '', channel.pathPrefix ?? '', version.pathPrefix ?? '', slug].filter(Boolean);
|
|
39
42
|
const normalized = '/' + parts.join('/').replace(/\/+/g, '/').replace(/^\//, '').replace(/\/$/, '');
|
|
40
43
|
return normalized === '/' ? '/' : normalized;
|
|
41
44
|
}
|
|
@@ -47,7 +47,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
47
47
|
path: string;
|
|
48
48
|
[key: string]: unknown;
|
|
49
49
|
};
|
|
50
|
+
product?: string;
|
|
50
51
|
publications?: Array<{
|
|
52
|
+
product?: string;
|
|
51
53
|
channel: string;
|
|
52
54
|
version: string;
|
|
53
55
|
source: {
|
|
@@ -90,7 +92,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
90
92
|
path: string;
|
|
91
93
|
[key: string]: unknown;
|
|
92
94
|
};
|
|
95
|
+
product?: string;
|
|
93
96
|
publications?: Array<{
|
|
97
|
+
product?: string;
|
|
94
98
|
channel: string;
|
|
95
99
|
version: string;
|
|
96
100
|
source: {
|
|
@@ -134,7 +138,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
134
138
|
path: string;
|
|
135
139
|
[key: string]: unknown;
|
|
136
140
|
};
|
|
141
|
+
product?: string;
|
|
137
142
|
publications?: Array<{
|
|
143
|
+
product?: string;
|
|
138
144
|
channel: string;
|
|
139
145
|
version: string;
|
|
140
146
|
source: {
|
|
@@ -173,7 +179,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
173
179
|
path: string;
|
|
174
180
|
[key: string]: unknown;
|
|
175
181
|
};
|
|
182
|
+
product?: string;
|
|
176
183
|
publications?: Array<{
|
|
184
|
+
product?: string;
|
|
177
185
|
channel: string;
|
|
178
186
|
version: string;
|
|
179
187
|
source: {
|
|
@@ -216,7 +224,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
216
224
|
path: string;
|
|
217
225
|
[key: string]: unknown;
|
|
218
226
|
};
|
|
227
|
+
product?: string;
|
|
219
228
|
publications?: Array<{
|
|
229
|
+
product?: string;
|
|
220
230
|
channel: string;
|
|
221
231
|
version: string;
|
|
222
232
|
source: {
|
|
@@ -270,7 +280,9 @@ export declare function prepareContentWorkspace({ base, basePath, config, loaded
|
|
|
270
280
|
path: string;
|
|
271
281
|
[key: string]: unknown;
|
|
272
282
|
};
|
|
283
|
+
product?: string;
|
|
273
284
|
publications?: Array<{
|
|
285
|
+
product?: string;
|
|
274
286
|
channel: string;
|
|
275
287
|
version: string;
|
|
276
288
|
source: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { documentKey } from './publication-identity.js';
|
|
1
2
|
import { matchesFeatures } from './deployment-profile.js';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { readFile } from 'node:fs/promises';
|
|
@@ -6,7 +7,7 @@ import { planAuthoredDocuments } from './publication-plan.js';
|
|
|
6
7
|
import { materializeApiReferences } from './api-publication-plan.js';
|
|
7
8
|
import { explainSegments } from './config.js';
|
|
8
9
|
import { validateSnippetConfig } from './snippets.js';
|
|
9
|
-
const keyFor =
|
|
10
|
+
const keyFor = documentKey;
|
|
10
11
|
/** Shared source resolution. No website navigation, styles, hosting or provider setup. */
|
|
11
12
|
export async function prepareContentWorkspace({ base, basePath, config, loaded, variants, language, readerFilters, contentFilter, metadataProvider, metadataDependencies, sourceOverrides, authoringFiles, allowRouteCollisions }) {
|
|
12
13
|
const { docs, knownDocumentIds, knownDocumentTypes, authoredOperationIds, routeOwners, contentDir } = await planAuthoredDocuments({
|
package/dist/content.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { publicationKey } from './publication-identity.js';
|
|
1
2
|
import { fictionalDocument, resolveLlmsDiscovery } from './llms-discovery.js';
|
|
2
3
|
import YAML from 'yaml';
|
|
3
4
|
import { nativePublicFields, protectedMetadataRoots, publicFrontmatterPaths } from './frontmatter.js';
|
|
@@ -8,7 +9,7 @@ export { transformMdx } from './component-transform.js';
|
|
|
8
9
|
export { renderHtml } from './html-renderer.js';
|
|
9
10
|
export { buildHtmlPage, shareCardText, typeLabel } from './page-renderer.js';
|
|
10
11
|
// API separators are visually hidden punctuation; join them to the preceding text so search reads "integer; default: 0".
|
|
11
|
-
const variantKey =
|
|
12
|
+
const variantKey = publicationKey;
|
|
12
13
|
const plainText = (html) => html.replace(/<(script|style)[^]*?<\/\1>/g, ' ').replace(/(?:<\/[a-z]+>)?<span class="api-separator">([^<]*)<\/span>/g, '$1').replace(/<[^>]+>/g, ' ')
|
|
13
14
|
.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'|'/g, "'").replace(/&/g, '&').replace(/\s+/g, ' ').trim();
|
|
14
15
|
// One compact record per published page; headings allow results to deep-link into a section.
|
|
@@ -54,7 +55,7 @@ export function projectMetadata(doc, config) {
|
|
|
54
55
|
throw new Error('Markdown metadata projection must be a mapping');
|
|
55
56
|
const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
56
57
|
const safePath = (value) => /^[A-Za-z_][A-Za-z0-9_-]*(?:\.[A-Za-z_][A-Za-z0-9_-]*)*$/.test(value);
|
|
57
|
-
const publicationFields = new Set(['channel', 'version', 'language', 'canonicalUrl']);
|
|
58
|
+
const publicationFields = new Set(['product', 'channel', 'version', 'language', 'canonicalUrl']);
|
|
58
59
|
const approved = publicFrontmatterPaths(config.frontmatter);
|
|
59
60
|
const validateSource = (source) => {
|
|
60
61
|
if (!safePath(source))
|
package/dist/cookbook-chooser.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { samePublication } from './publication-identity.js';
|
|
1
2
|
const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
2
3
|
const keys = (value, allowed) => Object.keys(value).every(key => allowed.includes(key));
|
|
3
4
|
const validId = (value) => typeof value === 'string' && /^[a-z][a-z0-9-]*$/.test(value);
|
|
@@ -35,7 +36,7 @@ export function cookbookChooserComponent(node, file) {
|
|
|
35
36
|
return { type: 'docCookbookChooser', id: attributes[0].value, sourceFile: file };
|
|
36
37
|
}
|
|
37
38
|
export function resolveCookbookTree(tree, current, documents, cookbooks, targets) {
|
|
38
|
-
const sameVariant = (a, b) => a.variant
|
|
39
|
+
const sameVariant = (a, b) => samePublication(a.variant, b.variant);
|
|
39
40
|
const walk = (node) => {
|
|
40
41
|
if (node.type !== 'docCookbookChooser')
|
|
41
42
|
return node.children ? { ...node, children: node.children.map(walk) } : node;
|
|
@@ -5,6 +5,7 @@ export type FeatureRequirements = {
|
|
|
5
5
|
export type FeatureContext = {
|
|
6
6
|
requireClassification?: boolean;
|
|
7
7
|
classificationPublications?: Array<{
|
|
8
|
+
product?: string;
|
|
8
9
|
channel: string;
|
|
9
10
|
version: string;
|
|
10
11
|
language: string;
|
|
@@ -49,4 +50,4 @@ export declare function profileSelection(resolution: ProfileResolution | undefin
|
|
|
49
50
|
}[];
|
|
50
51
|
} | undefined;
|
|
51
52
|
/** A profile is data, never executable configuration or a directory to discover. */
|
|
52
|
-
export declare function resolveDeploymentProfile(settings: unknown, config: Record<string, any>, declaringFile: string, profileFile?: string): Promise<ProfileResolution | undefined>;
|
|
53
|
+
export declare function resolveDeploymentProfile(settings: unknown, config: Record<string, any>, declaringFile: string, profileFile?: string, onDependency?: (file: string) => void): Promise<ProfileResolution | undefined>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolvePublication } from './compiler-config.js';
|
|
2
|
+
import { publicationKey } from './publication-identity.js';
|
|
1
3
|
import { readFile, lstat, realpath } from 'node:fs/promises';
|
|
2
4
|
import path from 'node:path';
|
|
3
5
|
import { createHash } from 'node:crypto';
|
|
@@ -95,7 +97,7 @@ export function profileSelection(resolution) {
|
|
|
95
97
|
return { schemaVersion: 1, profileDigest: resolution.digest, features: [...resolution.context.grants].sort(), provenance: resolution.context.provenance, decisions: resolution.context.decisions };
|
|
96
98
|
}
|
|
97
99
|
/** A profile is data, never executable configuration or a directory to discover. */
|
|
98
|
-
export async function resolveDeploymentProfile(settings, config, declaringFile, profileFile) {
|
|
100
|
+
export async function resolveDeploymentProfile(settings, config, declaringFile, profileFile, onDependency) {
|
|
99
101
|
if (settings === undefined) {
|
|
100
102
|
if (profileFile)
|
|
101
103
|
throw new Error('--profile requires profiles.manifest in the shared configuration');
|
|
@@ -108,6 +110,7 @@ export async function resolveDeploymentProfile(settings, config, declaringFile,
|
|
|
108
110
|
if (settings[setting] !== undefined && typeof settings[setting] !== 'boolean')
|
|
109
111
|
throw new Error(`profiles.${setting} must be boolean`);
|
|
110
112
|
const manifestFile = path.resolve(path.dirname(declaringFile), settings.manifest);
|
|
113
|
+
onDependency?.(manifestFile);
|
|
111
114
|
const manifestBytes = await readFile(manifestFile);
|
|
112
115
|
const manifest = parseYaml(manifestBytes.toString('utf8'), manifestFile);
|
|
113
116
|
keys(manifest, ['schemaVersion', 'features', 'skus'], 'SKU manifest');
|
|
@@ -142,13 +145,15 @@ export async function resolveDeploymentProfile(settings, config, declaringFile,
|
|
|
142
145
|
const context = { features, digest, pruneNavigation: settings.pruneNavigation ?? false, decisions: [], provenance: Object.create(null) };
|
|
143
146
|
context.requireClassification = settings.requireClassification ?? false;
|
|
144
147
|
if (context.requireClassification)
|
|
145
|
-
context.classificationPublications = (config.publications?.enabled ?? []).map((entry) => (
|
|
148
|
+
context.classificationPublications = (config.publications?.enabled ?? []).map((entry) => resolvePublication(config.publications, entry, defaultLanguage(config)));
|
|
146
149
|
if (!profileFile) {
|
|
147
150
|
if (settings.required !== false)
|
|
148
151
|
throw new Error('This project requires an explicit --profile FILE');
|
|
149
152
|
return { context, overlay: {}, dependencies: [manifestFile], assetFiles: [], digest };
|
|
150
153
|
}
|
|
154
|
+
onDependency?.(path.resolve(profileFile));
|
|
151
155
|
const file = await realpath(path.resolve(profileFile));
|
|
156
|
+
onDependency?.(file);
|
|
152
157
|
const bytes = await readFile(file);
|
|
153
158
|
const profile = parseYaml(bytes.toString('utf8'), file);
|
|
154
159
|
profileData(profile);
|
|
@@ -185,7 +190,12 @@ export async function resolveDeploymentProfile(settings, config, declaringFile,
|
|
|
185
190
|
const overlay = {};
|
|
186
191
|
const assetFiles = [];
|
|
187
192
|
if (profile.site !== undefined) {
|
|
188
|
-
keys(profile.site, ['title', 'origin', 'basePath', 'favicon', 'logo', 'header', 'footer', 'indexing'], 'Profile site');
|
|
193
|
+
keys(profile.site, ['title', 'origin', 'basePath', 'favicon', 'logo', 'header', 'footer', 'indexing', 'publicationSelector'], 'Profile site');
|
|
194
|
+
if (profile.site.publicationSelector !== undefined) {
|
|
195
|
+
keys(profile.site.publicationSelector, ['showLanguage'], 'Profile site.publicationSelector');
|
|
196
|
+
if (profile.site.publicationSelector.showLanguage !== undefined && typeof profile.site.publicationSelector.showLanguage !== 'boolean')
|
|
197
|
+
throw new Error('Profile site.publicationSelector.showLanguage must be boolean');
|
|
198
|
+
}
|
|
189
199
|
if (profile.site.title !== undefined && (typeof profile.site.title !== 'string' || !profile.site.title.trim()))
|
|
190
200
|
throw new Error('Profile site.title must be nonempty text');
|
|
191
201
|
if (profile.site.indexing !== undefined && typeof profile.site.indexing !== 'boolean')
|
|
@@ -221,11 +231,31 @@ export async function resolveDeploymentProfile(settings, config, declaringFile,
|
|
|
221
231
|
throw new Error('Profile asset must stay within the profile directory');
|
|
222
232
|
// Explicit assets only. Symlinks must not introduce an undeclared capture root.
|
|
223
233
|
let current = target;
|
|
234
|
+
const ancestry = [];
|
|
224
235
|
while (current !== path.dirname(file)) {
|
|
225
|
-
|
|
226
|
-
throw new Error('Profile assets must not use symlinks');
|
|
236
|
+
ancestry.unshift(current);
|
|
227
237
|
current = path.dirname(current);
|
|
228
238
|
}
|
|
239
|
+
for (const entry of ancestry) {
|
|
240
|
+
let info;
|
|
241
|
+
try {
|
|
242
|
+
info = await lstat(entry);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
// Every existing ancestor has passed the containment/symlink check.
|
|
246
|
+
// Watch only this declared target so creating it can repair a preview.
|
|
247
|
+
if (error.code === 'ENOENT')
|
|
248
|
+
onDependency?.(target);
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
if (info.isSymbolicLink())
|
|
252
|
+
throw new Error('Profile assets must not use symlinks');
|
|
253
|
+
if (entry !== target && !info.isDirectory()) {
|
|
254
|
+
onDependency?.(target);
|
|
255
|
+
throw new Error('Profile asset parents must be directories');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
onDependency?.(target);
|
|
229
259
|
if (!(await lstat(target)).isFile())
|
|
230
260
|
throw new Error(`Profile ${setting} must be a regular file`);
|
|
231
261
|
assetFiles.push(target);
|
|
@@ -257,13 +287,13 @@ export async function resolveDeploymentProfile(settings, config, declaringFile,
|
|
|
257
287
|
keys(profile.publications, ['enabled'], 'Profile publications');
|
|
258
288
|
const enabled = profile.publications.enabled;
|
|
259
289
|
const language = defaultLanguage(config);
|
|
260
|
-
const coordinate = (value) =>
|
|
290
|
+
const coordinate = (value) => publicationKey(resolvePublication(config.publications, value, language));
|
|
261
291
|
if (!Array.isArray(enabled) || !enabled.length)
|
|
262
292
|
throw new Error('Profile publications.enabled must be a nonempty subset of shared publications.enabled');
|
|
263
293
|
const selected = new Set();
|
|
264
294
|
for (const variant of enabled) {
|
|
265
|
-
keys(variant, ['channel', 'version', 'language'], 'Profile publication');
|
|
266
|
-
if (typeof variant.channel !== 'string' || typeof variant.version !== 'string' || (variant.language !== undefined && typeof variant.language !== 'string') || !config.publications?.enabled?.some((entry) => coordinate(entry) === coordinate(variant)))
|
|
295
|
+
keys(variant, ['product', 'channel', 'version', 'language'], 'Profile publication');
|
|
296
|
+
if (typeof variant.channel !== 'string' || (variant.version !== undefined && typeof variant.version !== 'string') || (variant.product !== undefined && typeof variant.product !== 'string') || (variant.language !== undefined && typeof variant.language !== 'string') || !config.publications?.enabled?.some((entry) => coordinate(entry) === coordinate(variant)))
|
|
267
297
|
throw new Error('Profile publication is not enabled by the shared configuration');
|
|
268
298
|
const key = coordinate(variant);
|
|
269
299
|
if (selected.has(key))
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { Server } from 'node:http';
|
|
2
|
-
export declare function startDev(configFile: string, outputDirectory: string, host?: string, port?: number
|
|
2
|
+
export declare function startDev(configFile: string, outputDirectory: string, host?: string, port?: number, options?: {
|
|
3
|
+
profile?: string;
|
|
4
|
+
}): Promise<Server>;
|