@shoalrun/cli 0.0.0-stage → 0.1.0-alpha.11
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 +269 -0
- package/CHANGELOG.md +82 -0
- package/LICENSE +202 -0
- package/README.md +189 -2
- package/agent-docs/.well-known/shoalrun/navigation/changelog-tab-50f26fe22670.txt +33 -0
- package/agent-docs/.well-known/shoalrun/navigation/docs-50f26fe22670.txt +24 -0
- package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +9 -0
- package/agent-docs/SNAPSHOT.json +9 -0
- package/agent-docs/about.md +49 -0
- package/agent-docs/api-docs/focused-contracts.md +68 -0
- package/agent-docs/api-docs/generate.md +189 -0
- package/agent-docs/api-docs/generate.sections/add-useful-examples.md +47 -0
- package/agent-docs/api-docs/generate.sections/choose-generated-references-or-mdx.md +50 -0
- package/agent-docs/api-docs/generate.sections/describe-filters-that-do-not-use-their-openapi-parameter-name.md +52 -0
- package/agent-docs/api-docs/generate.sections/generate-many-pages-selectively.md +71 -0
- package/agent-docs/api-docs/generate.sections/link-guides-to-api-references.md +48 -0
- package/agent-docs/api-docs/generate.sections/map-extension-values-to-shoalrun-status.md +52 -0
- package/agent-docs/api-docs/generate.sections/override-generated-reference-order-in-navigation.md +60 -0
- package/agent-docs/api-docs/generate.sections/related-reading.md +38 -0
- package/agent-docs/api-docs/generate.sections/use-a-template-for-editorial-context.md +45 -0
- package/agent-docs/api-docs/support.md +97 -0
- package/agent-docs/author/add-page.md +124 -0
- package/agent-docs/author/agent-overview.md +59 -0
- package/agent-docs/author/agent-workflow.md +65 -0
- package/agent-docs/author/agents.md +53 -0
- package/agent-docs/author/analytics.md +286 -0
- package/agent-docs/author/analytics.sections/adapter-exports-and-consent.md +51 -0
- package/agent-docs/author/analytics.sections/built-in-events.md +52 -0
- package/agent-docs/author/analytics.sections/configure-an-adapter.md +51 -0
- package/agent-docs/author/analytics.sections/custom-interactions.md +57 -0
- package/agent-docs/author/analytics.sections/event-format.md +59 -0
- package/agent-docs/author/analytics.sections/html-markdown-and-agents.md +42 -0
- package/agent-docs/author/analytics.sections/inspect-events-locally.md +36 -0
- package/agent-docs/author/analytics.sections/map-events-to-your-service.md +42 -0
- package/agent-docs/author/analytics.sections/posthog-example.md +126 -0
- package/agent-docs/author/analytics.sections/related-reading.md +42 -0
- package/agent-docs/author/authoring-agent.md +102 -0
- package/agent-docs/author/coding-agent.md +90 -0
- package/agent-docs/author/components/action-link.md +41 -0
- package/agent-docs/author/components/api-embeds.md +263 -0
- package/agent-docs/author/components/api-embeds.sections/apiexample.md +117 -0
- package/agent-docs/author/components/api-embeds.sections/html-markdown-and-agents.md +37 -0
- package/agent-docs/author/components/api-embeds.sections/related-reading.md +37 -0
- package/agent-docs/author/components/badge.md +76 -0
- package/agent-docs/author/components/breadcrumbs.md +57 -0
- package/agent-docs/author/components/callout.md +131 -0
- package/agent-docs/author/components/cards.md +168 -0
- package/agent-docs/author/components/cards.sections/add-a-lucide-icon.md +50 -0
- package/agent-docs/author/components/cards.sections/build-a-collection.md +69 -0
- package/agent-docs/author/components/cards.sections/curate-a-reading-list.md +66 -0
- package/agent-docs/author/components/cards.sections/html-markdown-and-agents.md +37 -0
- package/agent-docs/author/components/cards.sections/link-to-one-document.md +45 -0
- package/agent-docs/author/components/cards.sections/override-card-text.md +58 -0
- package/agent-docs/author/components/cards.sections/related-reading.md +43 -0
- package/agent-docs/author/components/code-blocks.md +117 -0
- package/agent-docs/author/components/collapsible.md +99 -0
- package/agent-docs/author/components/cookbook-chooser.md +86 -0
- package/agent-docs/author/components/custom/react.md +190 -0
- package/agent-docs/author/components/custom/react.sections/html-markdown-and-agents.md +36 -0
- package/agent-docs/author/components/custom/react.sections/interactive-react-example.md +88 -0
- package/agent-docs/author/components/custom/react.sections/registration.md +41 -0
- package/agent-docs/author/components/custom/react.sections/related-reading.md +30 -0
- package/agent-docs/author/components/custom/react.sections/share-the-model-with-the-browser.md +47 -0
- package/agent-docs/author/components/custom/react.sections/where-the-content-lives.md +100 -0
- package/agent-docs/author/components/custom.md +183 -0
- package/agent-docs/author/components/definition-list.md +54 -0
- package/agent-docs/author/components/diagrams/d2-gallery.md +861 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/basic-shapes.md +163 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/flows-and-structures.md +375 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/html-markdown-and-agents.md +33 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/layout-engines.md +169 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/related-reading.md +37 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/sequences-and-grids.md +123 -0
- package/agent-docs/author/components/diagrams/d2-gallery.sections/styles-and-code.md +125 -0
- package/agent-docs/author/components/diagrams/pele-gallery.md +1317 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/charts-and-planning.md +341 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/flowchart-shapes.md +269 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/flows-and-behavior.md +273 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/html-markdown-and-agents.md +31 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/related-reading.md +35 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/specialized-diagrams.md +229 -0
- package/agent-docs/author/components/diagrams/pele-gallery.sections/systems-and-structures.md +291 -0
- package/agent-docs/author/components/diagrams.md +155 -0
- package/agent-docs/author/components/doc-link.md +58 -0
- package/agent-docs/author/components/fields.md +121 -0
- package/agent-docs/author/components/file-tree.md +84 -0
- package/agent-docs/author/components/images.md +103 -0
- package/agent-docs/author/components/info-hint.md +61 -0
- package/agent-docs/author/components/kbd.md +45 -0
- package/agent-docs/author/components/math.md +39 -0
- package/agent-docs/author/components/only.md +65 -0
- package/agent-docs/author/components/progress.md +53 -0
- package/agent-docs/author/components/related-reading.md +48 -0
- package/agent-docs/author/components/steps.md +121 -0
- package/agent-docs/author/components/tables.md +64 -0
- package/agent-docs/author/components/tabs.md +129 -0
- package/agent-docs/author/components/timeline.md +74 -0
- package/agent-docs/author/components/tooltips.md +58 -0
- package/agent-docs/author/components/walkthroughs.md +390 -0
- package/agent-docs/author/components/walkthroughs.sections/attributes.md +45 -0
- package/agent-docs/author/components/walkthroughs.sections/build-up-code.md +133 -0
- package/agent-docs/author/components/walkthroughs.sections/choose-a-layout.md +141 -0
- package/agent-docs/author/components/walkthroughs.sections/explain-one-file.md +126 -0
- package/agent-docs/author/components/walkthroughs.sections/html-markdown-and-agents.md +38 -0
- package/agent-docs/author/components/walkthroughs.sections/related-reading.md +36 -0
- package/agent-docs/author/components/walkthroughs.sections/take-code-from-a-file.md +53 -0
- package/agent-docs/author/components.md +78 -0
- package/agent-docs/author/content.md +74 -0
- package/agent-docs/author/cookbooks.md +119 -0
- package/agent-docs/author/css.md +238 -0
- package/agent-docs/author/css.sections/borders-fields-and-navigation-tokens.md +70 -0
- package/agent-docs/author/css.sections/core-color-tokens.md +71 -0
- package/agent-docs/author/css.sections/page-attributes.md +69 -0
- package/agent-docs/author/css.sections/page-transitions.md +60 -0
- package/agent-docs/author/css.sections/responsive-behavior.md +58 -0
- package/agent-docs/author/css.sections/status-code-and-callout-tokens.md +89 -0
- package/agent-docs/author/css.sections/typography-shape-and-width-tokens.md +71 -0
- package/agent-docs/author/custom-metadata.md +177 -0
- package/agent-docs/author/custom-metadata.sections/add-a-custom-page-field.md +68 -0
- package/agent-docs/author/custom-metadata.sections/choose-text-for-each-surface.md +54 -0
- package/agent-docs/author/custom-metadata.sections/preview-changes-to-metadata-providers.md +33 -0
- package/agent-docs/author/custom-metadata.sections/read-metadata-from-a-project-module.md +57 -0
- package/agent-docs/author/custom-metadata.sections/related-reading.md +29 -0
- package/agent-docs/author/design-templates.md +49 -0
- package/agent-docs/author/design-writing-guides.md +73 -0
- package/agent-docs/author/frontmatter-reference.md +146 -0
- package/agent-docs/author/frontmatter-reference.sections/choose-a-publication-and-visibility.md +44 -0
- package/agent-docs/author/frontmatter-reference.sections/control-output-details.md +41 -0
- package/agent-docs/author/frontmatter-reference.sections/global-defaults-and-enforced-values.md +31 -0
- package/agent-docs/author/frontmatter-reference.sections/identify-and-route-a-page.md +40 -0
- package/agent-docs/author/frontmatter-reference.sections/point-agents-to-it.md +37 -0
- package/agent-docs/author/frontmatter-reference.sections/project-defined-fields.md +41 -0
- package/agent-docs/author/frontmatter-reference.sections/related-reading.md +35 -0
- package/agent-docs/author/frontmatter-reference.sections/use-the-local-files-while-authoring.md +33 -0
- package/agent-docs/author/frontmatter-reference.sections/when-the-files-update.md +31 -0
- package/agent-docs/author/frontmatter.md +255 -0
- package/agent-docs/author/frontmatter.sections/audience-badges.md +66 -0
- package/agent-docs/author/frontmatter.sections/give-deprecation-guidance.md +88 -0
- package/agent-docs/author/frontmatter.sections/global-defaults-and-enforced-values.md +75 -0
- package/agent-docs/author/frontmatter.sections/optional-native-fields.md +90 -0
- package/agent-docs/author/frontmatter.sections/publication-fields.md +85 -0
- package/agent-docs/author/frontmatter.sections/publishing-policy.md +71 -0
- package/agent-docs/author/frontmatter.sections/related-metadata-tasks.md +72 -0
- package/agent-docs/author/frontmatter.sections/related-reading.md +72 -0
- package/agent-docs/author/frontmatter.sections/required-after-inheritance.md +84 -0
- package/agent-docs/author/frontmatter.sections/seo-fields.md +79 -0
- package/agent-docs/author/frontmatter.sections/validation-rules.md +75 -0
- package/agent-docs/author/markdown-metadata.md +207 -0
- package/agent-docs/author/navigation.md +269 -0
- package/agent-docs/author/navigation.sections/arrange-authored-pages.md +58 -0
- package/agent-docs/author/navigation.sections/fill-an-api-tag-group.md +48 -0
- package/agent-docs/author/navigation.sections/hide-group-page-counts.md +45 -0
- package/agent-docs/author/navigation.sections/html-markdown-and-agents.md +40 -0
- package/agent-docs/author/navigation.sections/local-api-preview.md +47 -0
- package/agent-docs/author/navigation.sections/mix-guides-and-api-references.md +65 -0
- package/agent-docs/author/navigation.sections/optionally-split-a-large-menu-into-files.md +97 -0
- package/agent-docs/author/navigation.sections/reach-navigation-while-reading.md +38 -0
- package/agent-docs/author/navigation.sections/related-reading.md +44 -0
- package/agent-docs/author/navigation.sections/split-navigation-into-tabs.md +67 -0
- package/agent-docs/author/navigation.sections/subject-lifecycle-labels.md +42 -0
- package/agent-docs/author/reader-views.md +200 -0
- package/agent-docs/author/reader-views.sections/configure-the-choices.md +65 -0
- package/agent-docs/author/reader-views.sections/connect-your-own-control.md +59 -0
- package/agent-docs/author/reader-views.sections/how-it-works-for-agents.md +41 -0
- package/agent-docs/author/reader-views.sections/mark-pages.md +49 -0
- package/agent-docs/author/reader-views.sections/mark-sections-and-add-an-entry-choice.md +49 -0
- package/agent-docs/author/reader-views.sections/place-filter-controls.md +43 -0
- package/agent-docs/author/reader-views.sections/try-the-controls-here.md +64 -0
- package/agent-docs/author/recipe-drafts.md +181 -0
- package/agent-docs/author/recipe-drafts.sections/1-write-one-reusable-step.md +82 -0
- package/agent-docs/author/recipe-drafts.sections/2-list-the-steps-for-one-complete-goal.md +60 -0
- package/agent-docs/author/recipe-drafts.sections/3-generate-a-draft-and-review-it.md +55 -0
- package/agent-docs/author/recipe-drafts.sections/4-maintain-shoalrun-s-published-recipe-snapshots.md +66 -0
- package/agent-docs/author/recipe-drafts.sections/related-reading.md +45 -0
- package/agent-docs/author/recipe-drafts.sections/start-an-ingredient-from-an-api-example.md +50 -0
- package/agent-docs/author/recipes.md +127 -0
- package/agent-docs/author/recipes.sections/how-agents-use-this.md +50 -0
- package/agent-docs/author/recipes.sections/one-example-from-shoalrun.md +64 -0
- package/agent-docs/author/recipes.sections/related-reading.md +36 -0
- package/agent-docs/author/recipes.sections/try-a-complete-workflow.md +42 -0
- package/agent-docs/author/recipes.sections/use-recipes-for-task-oriented-how-tos.md +52 -0
- package/agent-docs/author/recipes.sections/what-changing-an-ingredient-updates.md +44 -0
- package/agent-docs/author/recipes.sections/what-each-file-does.md +48 -0
- package/agent-docs/author/recipes.sections/what-happens-and-when.md +45 -0
- package/agent-docs/author/related-reading.md +143 -0
- package/agent-docs/author/related-reading.sections/automatic-footers.md +35 -0
- package/agent-docs/author/related-reading.sections/declare-relationships.md +68 -0
- package/agent-docs/author/related-reading.sections/display-related-documents.md +54 -0
- package/agent-docs/author/related-reading.sections/inspect-output-and-changes.md +32 -0
- package/agent-docs/author/related-reading.sections/reading-paths-in-section-markdown.md +32 -0
- package/agent-docs/author/related-reading.sections/related-reading.md +34 -0
- package/agent-docs/author/related-reading.sections/where-relationship-explanations-come-from.md +34 -0
- package/agent-docs/author/release-notes.md +153 -0
- package/agent-docs/author/search.md +299 -0
- package/agent-docs/author/search.sections/choose-a-provider.md +52 -0
- package/agent-docs/author/search.sections/cli-and-mcp-ranking-details.md +49 -0
- package/agent-docs/author/search.sections/hosted-semantic-search-limits.md +55 -0
- package/agent-docs/author/search.sections/html-markdown-and-agents.md +37 -0
- package/agent-docs/author/search.sections/lexical-search.md +78 -0
- package/agent-docs/author/search.sections/local-semantic-preview.md +43 -0
- package/agent-docs/author/search.sections/read-a-search-result-with-an-agent.md +41 -0
- package/agent-docs/author/search.sections/related-reading.md +45 -0
- package/agent-docs/author/search.sections/reuse-the-lexical-index.md +81 -0
- package/agent-docs/author/search.sections/turn-search-off.md +46 -0
- package/agent-docs/author/search.sections/use-the-search-box.md +39 -0
- package/agent-docs/author/search.sections/write-a-custom-provider.md +98 -0
- package/agent-docs/author/snippets.md +118 -0
- package/agent-docs/author/taxonomy.md +121 -0
- package/agent-docs/author/templates.md +231 -0
- package/agent-docs/author/templates.sections/built-in-feature-templates.md +52 -0
- package/agent-docs/author/templates.sections/built-in-templates.md +48 -0
- package/agent-docs/author/templates.sections/choose-formatting-enforcement-for-your-project.md +69 -0
- package/agent-docs/author/templates.sections/create-or-edit-a-project-template.md +76 -0
- package/agent-docs/author/templates.sections/keep-the-four-shapes-distinct.md +46 -0
- package/agent-docs/author/templates.sections/project-added-templates.md +39 -0
- package/agent-docs/author/templates.sections/related-reading.md +47 -0
- package/agent-docs/author/templates.sections/scaffold-a-page.md +53 -0
- package/agent-docs/author/templates.sections/short-cli-and-derived-values.md +56 -0
- package/agent-docs/author/templates.sections/what-every-template-gives-you.md +44 -0
- package/agent-docs/author/workspace/commands.md +92 -0
- package/agent-docs/author/workspace.md +104 -0
- package/agent-docs/author/writing-style.md +137 -0
- package/agent-docs/author/writing-style.sections/adapt-this-example.md +28 -0
- package/agent-docs/author/writing-style.sections/choose-components-by-reader-need.md +42 -0
- package/agent-docs/author/writing-style.sections/evidence-and-uncertainty.md +32 -0
- package/agent-docs/author/writing-style.sections/example-audience-and-scope.md +28 -0
- package/agent-docs/author/writing-style.sections/ingredients-recipes-and-cookbooks.md +36 -0
- package/agent-docs/author/writing-style.sections/page-purpose-and-structure.md +41 -0
- package/agent-docs/author/writing-style.sections/procedures-and-examples.md +32 -0
- package/agent-docs/author/writing-style.sections/related-reading.md +32 -0
- package/agent-docs/author/writing-style.sections/review-a-draft.md +30 -0
- package/agent-docs/author/writing-style.sections/reviewed-writing-examples.md +39 -0
- package/agent-docs/author/writing-style.sections/voice-and-explanations.md +39 -0
- package/agent-docs/changelog/2026-10-14-agent-readiness.md +29 -0
- package/agent-docs/changelog/2026-10-15-evaluation-builds.md +84 -0
- package/agent-docs/changelog/2026-10-16-navigation-layouts.md +72 -0
- package/agent-docs/changelog/2026-10-17-mcp-hosting.md +60 -0
- package/agent-docs/changelog/2026-10-18-search-and-tooltips.md +46 -0
- package/agent-docs/changelog/2026-10-19-visual-navigation.md +44 -0
- package/agent-docs/changelog/2026-10-25.md +45 -0
- package/agent-docs/changelog/2026-10-26.md +66 -0
- package/agent-docs/changelog/2026-10-27.md +85 -0
- package/agent-docs/changelog/authoring-preview.md +40 -0
- package/agent-docs/changelog/authoring-search.md +39 -0
- package/agent-docs/changelog/authoring-tools.md +34 -0
- package/agent-docs/changelog/working-tree-skill.md +38 -0
- package/agent-docs/changelog.md +115 -0
- package/agent-docs/chat/checks.md +175 -0
- package/agent-docs/chat/checks.sections/answer-ahead-of-time.md +38 -0
- package/agent-docs/chat/checks.sections/answer-for-one-audience.md +66 -0
- package/agent-docs/chat/checks.sections/answer-without-a-model.md +54 -0
- package/agent-docs/chat/checks.sections/follow-up-questions.md +54 -0
- package/agent-docs/chat/checks.sections/how-an-answer-is-checked.md +67 -0
- package/agent-docs/chat/checks.sections/questions-with-several-parts.md +44 -0
- package/agent-docs/chat/checks.sections/related-reading.md +42 -0
- package/agent-docs/chat/checks.sections/reuse-answers.md +50 -0
- package/agent-docs/chat/host.md +222 -0
- package/agent-docs/chat/host.sections/cap-the-daily-spend.md +78 -0
- package/agent-docs/chat/host.sections/keep-a-record-of-questions.md +64 -0
- package/agent-docs/chat/host.sections/related-reading.md +43 -0
- package/agent-docs/chat/passage-index.md +228 -0
- package/agent-docs/chat/passage-index.sections/build-the-index.md +72 -0
- package/agent-docs/chat/passage-index.sections/embed-passages.md +103 -0
- package/agent-docs/chat/passage-index.sections/how-the-default-chunker-splits-a-page.md +53 -0
- package/agent-docs/chat/passage-index.sections/limits.md +45 -0
- package/agent-docs/chat/passage-index.sections/passage-ids-and-links.md +52 -0
- package/agent-docs/chat/passage-index.sections/related-reading.md +42 -0
- package/agent-docs/chat/passage-index.sections/what-a-passage-contains.md +91 -0
- package/agent-docs/chat/prepared-answers.md +116 -0
- package/agent-docs/chat/settings.md +213 -0
- package/agent-docs/chat/settings.sections/choose-the-scorer.md +63 -0
- package/agent-docs/chat/settings.sections/configure-chat.md +80 -0
- package/agent-docs/chat/settings.sections/configure-retrieval.md +62 -0
- package/agent-docs/chat/settings.sections/related-reading.md +32 -0
- package/agent-docs/chat/settings.sections/send-extra-request-fields.md +42 -0
- package/agent-docs/chat/settings.sections/use-more-than-one-model.md +62 -0
- package/agent-docs/chat/settings.sections/when-the-scorer-is-down.md +42 -0
- package/agent-docs/chat/setup.md +97 -0
- package/agent-docs/chat.md +102 -0
- package/agent-docs/cli.md +445 -0
- package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +102 -0
- package/agent-docs/cli.sections/author-pages.md +94 -0
- package/agent-docs/cli.sections/build-and-serve.md +144 -0
- package/agent-docs/cli.sections/inspect-config-and-operations.md +41 -0
- package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +45 -0
- package/agent-docs/cli.sections/related-reading.md +33 -0
- package/agent-docs/cli.sections/search-and-chat.md +132 -0
- package/agent-docs/cli.sections/start-a-project.md +37 -0
- package/agent-docs/cli.sections/working-tree-authoring-tools.md +35 -0
- package/agent-docs/concepts.md +133 -0
- package/agent-docs/config/apis.md +136 -0
- package/agent-docs/config/content.md +264 -0
- package/agent-docs/config/content.sections/authoring.md +58 -0
- package/agent-docs/config/content.sections/badges.md +34 -0
- package/agent-docs/config/content.sections/callouts.md +34 -0
- package/agent-docs/config/content.sections/cookbooks.md +38 -0
- package/agent-docs/config/content.sections/frontmatter.md +75 -0
- package/agent-docs/config/content.sections/readerfilters.md +44 -0
- package/agent-docs/config/content.sections/related-reading.md +34 -0
- package/agent-docs/config/content.sections/relationships.md +76 -0
- package/agent-docs/config/content.sections/snippets.md +61 -0
- package/agent-docs/config/content.sections/templates.md +57 -0
- package/agent-docs/config/content.sections/variables.md +55 -0
- package/agent-docs/config/examples.md +354 -0
- package/agent-docs/config/examples.sections/feature-showcase.md +55 -0
- package/agent-docs/config/examples.sections/minimal-site.md +80 -0
- package/agent-docs/config/examples.sections/multilingual-help-center.md +110 -0
- package/agent-docs/config/examples.sections/parcel-api-documentation.md +153 -0
- package/agent-docs/config/examples.sections/related-reading.md +50 -0
- package/agent-docs/config/examples.sections/shared-company-preset.md +118 -0
- package/agent-docs/config/integrations.md +76 -0
- package/agent-docs/config/outputs.md +160 -0
- package/agent-docs/config/outputs.sections/exports.md +57 -0
- package/agent-docs/config/outputs.sections/metadata.md +42 -0
- package/agent-docs/config/outputs.sections/related-reading.md +34 -0
- package/agent-docs/config/publishing.md +219 -0
- package/agent-docs/config/publishing.sections/navigation.md +92 -0
- package/agent-docs/config/publishing.sections/redirects.md +79 -0
- package/agent-docs/config/publishing.sections/related-reading.md +33 -0
- package/agent-docs/config/site.md +193 -0
- package/agent-docs/config/site.sections/related-reading.md +33 -0
- package/agent-docs/config/site.sections/theme.md +74 -0
- package/agent-docs/config.md +195 -0
- package/agent-docs/configuration.md +384 -0
- package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +36 -0
- package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +76 -0
- package/agent-docs/configuration.sections/extract-a-section-with-include.md +75 -0
- package/agent-docs/configuration.sections/inspect-and-validate-changes.md +77 -0
- package/agent-docs/configuration.sections/related-reading.md +42 -0
- package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +54 -0
- package/agent-docs/configuration.sections/share-defaults-through-extends.md +121 -0
- package/agent-docs/configuration.sections/start-with-one-working-file.md +81 -0
- package/agent-docs/configuration.sections/understand-the-three-stages.md +59 -0
- package/agent-docs/configuration.sections/understand-where-paths-point.md +53 -0
- package/agent-docs/connect/mcp.md +85 -0
- package/agent-docs/contribute/agent-skills.md +72 -0
- package/agent-docs/cookbooks/authoring.md +68 -0
- package/agent-docs/cookbooks/site-workflows.md +59 -0
- package/agent-docs/cookbooks/welcome-email.md +55 -0
- package/agent-docs/documents.json +20058 -0
- package/agent-docs/example-api/cedar/create-enrollment-7af3e5d2.md +594 -0
- package/agent-docs/example-api/cedar/get-legacy-parcel-6758d051.md +122 -0
- package/agent-docs/example-api/cedar/get-parcel-edee10e6.md +122 -0
- package/agent-docs/example-api/cedar/list-parcels-0345fb5f.md +271 -0
- package/agent-docs/example-api/cedar/parcel-delivered-7d1ba6db.md +122 -0
- package/agent-docs/example-api/cedar/upload-manifest-1af17891.md +101 -0
- package/agent-docs/example-api/cedar.md +39 -0
- package/agent-docs/example-api/create-note.md +344 -0
- package/agent-docs/example-api/generated/get-note-cbedb319.md +165 -0
- package/agent-docs/example-api/write-note.md +55 -0
- package/agent-docs/explore.md +54 -0
- package/agent-docs/glossary.md +827 -0
- package/agent-docs/index.md +249 -0
- package/agent-docs/ingredients/audit-site.md +27 -0
- package/agent-docs/ingredients/build-site.md +29 -0
- package/agent-docs/ingredients/compile-framework.md +28 -0
- package/agent-docs/ingredients/complete-page.md +30 -0
- package/agent-docs/ingredients/inspect-agent-bundle.md +28 -0
- package/agent-docs/ingredients/inspect-build.md +41 -0
- package/agent-docs/ingredients/preview-site.md +31 -0
- package/agent-docs/ingredients/refresh-agent-bundle.md +29 -0
- package/agent-docs/ingredients/scaffold-page.md +28 -0
- package/agent-docs/non-goals.md +58 -0
- package/agent-docs/provenance.json +10 -0
- package/agent-docs/publish/agent-discovery.md +79 -0
- package/agent-docs/publish/agent-friendliness.md +201 -0
- package/agent-docs/publish/agent-friendliness.sections/discover-a-page-with-a-small-context-budget.md +61 -0
- package/agent-docs/publish/agent-friendliness.sections/distinguish-examples-from-a-real-service.md +48 -0
- package/agent-docs/publish/agent-friendliness.sections/evidence-has-a-scope.md +46 -0
- package/agent-docs/publish/agent-friendliness.sections/keep-shared-instructions-complete.md +48 -0
- package/agent-docs/publish/agent-friendliness.sections/related-reading.md +52 -0
- package/agent-docs/publish/agent-friendliness.sections/secret-handshake.md +50 -0
- package/agent-docs/publish/agent-friendliness.sections/try-the-page-controls.md +62 -0
- package/agent-docs/publish/agent-friendliness.sections/use-the-transport-your-client-supports.md +50 -0
- package/agent-docs/publish/agent-friendliness.sections/verify-the-page-and-detect-changes.md +58 -0
- package/agent-docs/publish/agent-friendliness.sections/what-an-agent-reads.md +68 -0
- package/agent-docs/publish/agent-friendliness.sections/what-happens-to-an-unsupported-component.md +60 -0
- package/agent-docs/publish/api-references.md +217 -0
- package/agent-docs/publish/api-references.sections/add-useful-examples.md +36 -0
- package/agent-docs/publish/api-references.sections/author-the-reference-page.md +65 -0
- package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +48 -0
- package/agent-docs/publish/api-references.sections/describe-filters-that-do-not-use-their-openapi-parameter-name.md +36 -0
- package/agent-docs/publish/api-references.sections/generate-many-pages-selectively.md +36 -0
- package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +36 -0
- package/agent-docs/publish/api-references.sections/link-guides-to-api-references.md +36 -0
- package/agent-docs/publish/api-references.sections/map-extension-values-to-shoalrun-status.md +36 -0
- package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +38 -0
- package/agent-docs/publish/api-references.sections/publish-several-versions.md +36 -0
- package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +62 -0
- package/agent-docs/publish/api-references.sections/register-the-operation.md +64 -0
- package/agent-docs/publish/api-references.sections/related-reading.md +42 -0
- package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +54 -0
- package/agent-docs/publish/api-references.sections/use-a-template-for-editorial-context.md +36 -0
- package/agent-docs/publish/api-references.sections/what-readers-get.md +38 -0
- package/agent-docs/publish/audit.md +160 -0
- package/agent-docs/publish/audit.sections/add-project-tests.md +57 -0
- package/agent-docs/publish/audit.sections/check-agent-evaluation-reports.md +52 -0
- package/agent-docs/publish/audit.sections/check-before-pushing.md +80 -0
- package/agent-docs/publish/audit.sections/connect-a-documentation-test-suite.md +54 -0
- package/agent-docs/publish/audit.sections/read-the-report.md +67 -0
- package/agent-docs/publish/audit.sections/related-reading.md +47 -0
- package/agent-docs/publish/content-export.md +208 -0
- package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +40 -0
- package/agent-docs/publish/content-export.sections/check-the-result.md +27 -0
- package/agent-docs/publish/content-export.sections/export-selected-pages.md +113 -0
- package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +29 -0
- package/agent-docs/publish/content-export.sections/prerequisites.md +29 -0
- package/agent-docs/publish/content-export.sections/related-reading.md +35 -0
- package/agent-docs/publish/content-export.sections/review-exported-api-material.md +44 -0
- package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +34 -0
- package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +43 -0
- package/agent-docs/publish/content-negotiation.md +121 -0
- package/agent-docs/publish/content-negotiation.sections/hosting-contract.md +60 -0
- package/agent-docs/publish/content-negotiation.sections/missing-pages.md +51 -0
- package/agent-docs/publish/content-negotiation.sections/related-reading.md +45 -0
- package/agent-docs/publish/content-negotiation.sections/validators-and-manifest-links.md +49 -0
- package/agent-docs/publish/content-negotiation.sections/verify-the-deployed-url.md +62 -0
- package/agent-docs/publish/content-negotiation.sections/what-if-the-host-cannot-negotiate.md +47 -0
- package/agent-docs/publish/content-negotiation.sections/what-shoalrun-builds-and-what-the-host-does.md +49 -0
- package/agent-docs/publish/content-negotiation.sections/why-this-matters.md +47 -0
- package/agent-docs/publish/deployment-check.md +72 -0
- package/agent-docs/publish/evals.md +175 -0
- package/agent-docs/publish/evals.sections/add-the-audit-hook.md +63 -0
- package/agent-docs/publish/evals.sections/check-the-report.md +36 -0
- package/agent-docs/publish/evals.sections/define-a-task-file.md +47 -0
- package/agent-docs/publish/evals.sections/diagnose-a-different-build.md +42 -0
- package/agent-docs/publish/evals.sections/prepare-a-report-for-the-built-site.md +39 -0
- package/agent-docs/publish/evals.sections/related-reading.md +36 -0
- package/agent-docs/publish/evals.sections/run-and-review-the-tasks.md +54 -0
- package/agent-docs/publish/evals.sections/shoalrun-s-own-example.md +42 -0
- package/agent-docs/publish/host-adapters.md +60 -0
- package/agent-docs/publish/manni.md +227 -0
- package/agent-docs/publish/manni.sections/check-the-result.md +40 -0
- package/agent-docs/publish/manni.sections/how-this-site-uses-manni.md +83 -0
- package/agent-docs/publish/manni.sections/optional-custom-policies.md +42 -0
- package/agent-docs/publish/manni.sections/prerequisites.md +40 -0
- package/agent-docs/publish/mcp-analytics.md +356 -0
- package/agent-docs/publish/mcp-analytics.sections/adapter-exports.md +50 -0
- package/agent-docs/publish/mcp-analytics.sections/enable-analytics.md +45 -0
- package/agent-docs/publish/mcp-analytics.sections/event-fields-and-service-mappings.md +53 -0
- package/agent-docs/publish/mcp-analytics.sections/optionally-collect-intent-and-group-calls.md +62 -0
- package/agent-docs/publish/mcp-analytics.sections/optionally-identify-the-client-and-model.md +54 -0
- package/agent-docs/publish/mcp-analytics.sections/related-reading.md +36 -0
- package/agent-docs/publish/mcp-analytics.sections/safeguards-and-limits.md +46 -0
- package/agent-docs/publish/mcp.md +190 -0
- package/agent-docs/publish/mcp.sections/check-budgets-and-errors.md +52 -0
- package/agent-docs/publish/mcp.sections/choose-the-documentation-source.md +51 -0
- package/agent-docs/publish/mcp.sections/configure-the-client.md +55 -0
- package/agent-docs/publish/mcp.sections/generate-a-vercel-endpoint.md +50 -0
- package/agent-docs/publish/mcp.sections/related-reading.md +42 -0
- package/agent-docs/publish/mcp.sections/search-then-read.md +53 -0
- package/agent-docs/publish/mcp.sections/serve-a-public-endpoint-on-node.md +79 -0
- package/agent-docs/publish/mcp.sections/verify-the-connection.md +40 -0
- package/agent-docs/publish/mcp.sections/why-offer-mcp-for-public-docs.md +42 -0
- package/agent-docs/publish/openapi-extension-mappings.md +84 -0
- package/agent-docs/publish/output.md +220 -0
- package/agent-docs/publish/output.sections/api-contracts.md +48 -0
- package/agent-docs/publish/output.sections/code-highlighting.md +38 -0
- package/agent-docs/publish/output.sections/current-limits.md +40 -0
- package/agent-docs/publish/output.sections/incremental-sync.md +69 -0
- package/agent-docs/publish/output.sections/manifest-records-and-sections.md +46 -0
- package/agent-docs/publish/output.sections/navigation-section-indexes.md +42 -0
- package/agent-docs/publish/output.sections/page-formats.md +46 -0
- package/agent-docs/publish/output.sections/published-output-contract.md +58 -0
- package/agent-docs/publish/output.sections/reader-appearance-and-controls.md +44 -0
- package/agent-docs/publish/output.sections/related-reading.md +34 -0
- package/agent-docs/publish/output.sections/response-identity.md +38 -0
- package/agent-docs/publish/output.sections/site-files.md +64 -0
- package/agent-docs/publish/output.sections/validate-an-existing-build-locally.md +48 -0
- package/agent-docs/publish/output.sections/where-files-go.md +49 -0
- package/agent-docs/publish/publications.md +153 -0
- package/agent-docs/publish/revisions.md +104 -0
- package/agent-docs/publish/seo.md +119 -0
- package/agent-docs/publish/single-source-sites.md +168 -0
- package/agent-docs/publish/troubleshooting.md +112 -0
- package/agent-docs/publish/vercel.md +130 -0
- package/agent-docs/publish/vercel.sections/check-the-deployment.md +54 -0
- package/agent-docs/publish/vercel.sections/include-an-mcp-endpoint.md +38 -0
- package/agent-docs/publish/vercel.sections/prepare-your-project.md +52 -0
- package/agent-docs/publish/vercel.sections/related-reading.md +38 -0
- package/agent-docs/publish.md +95 -0
- package/agent-docs/recipes/add-page.md +194 -0
- package/agent-docs/recipes/add-page.sections/audit-the-shoalrun-docs-project.md +40 -0
- package/agent-docs/recipes/add-page.sections/before-you-start.md +33 -0
- package/agent-docs/recipes/add-page.sections/build-the-shoalrun-docs-site.md +42 -0
- package/agent-docs/recipes/add-page.sections/check-agent-search-and-page-lookup.md +42 -0
- package/agent-docs/recipes/add-page.sections/check-the-built-page-artifacts.md +54 -0
- package/agent-docs/recipes/add-page.sections/check-the-outcome.md +28 -0
- package/agent-docs/recipes/add-page.sections/complete-the-guide-and-add-navigation.md +42 -0
- package/agent-docs/recipes/add-page.sections/install-the-site-dependencies.md +41 -0
- package/agent-docs/recipes/add-page.sections/regenerate-the-agent-documentation-bundle.md +42 -0
- package/agent-docs/recipes/add-page.sections/related-reading.md +30 -0
- package/agent-docs/recipes/add-page.sections/scaffold-a-new-guide.md +42 -0
- package/agent-docs/recipes/audit-docs.md +122 -0
- package/agent-docs/recipes/build-docs.md +105 -0
- package/agent-docs/recipes/preview-hybrid-search.md +84 -0
- package/agent-docs/recipes/preview-page.md +124 -0
- package/agent-docs/recipes/queue-email.md +49 -0
- package/agent-docs/recipes/refresh-agent-docs.md +109 -0
- package/agent-docs/recipes/send-welcome-email.md +92 -0
- package/agent-docs/reference/agent-skills.md +73 -0
- package/agent-docs/search-and-chat.md +87 -0
- package/agent-docs/search-index.json +1 -0
- package/agent-docs/start.md +197 -0
- package/agent-docs/start.sections/add-the-page-to-navigation.md +50 -0
- package/agent-docs/start.sections/build-and-check-both-outputs.md +50 -0
- package/agent-docs/start.sections/build-this-site.md +35 -0
- package/agent-docs/start.sections/check-writing-style.md +35 -0
- package/agent-docs/start.sections/create-a-page.md +105 -0
- package/agent-docs/start.sections/make-it-yours.md +37 -0
- package/agent-docs/start.sections/prerequisites.md +37 -0
- package/agent-docs/start.sections/related-reading.md +45 -0
- package/agent-docs/start.sections/start-your-own-project.md +53 -0
- package/agent-docs/status.md +75 -0
- package/agent-docs/styling/color-modes.md +85 -0
- package/agent-docs/styling/footer.md +67 -0
- package/agent-docs/styling/header.md +65 -0
- package/agent-docs/styling/layouts.md +193 -0
- package/agent-docs/styling/layouts.sections/build-a-landing-page.md +61 -0
- package/agent-docs/styling/layouts.sections/build-a-splash-page.md +88 -0
- package/agent-docs/styling/layouts.sections/control-navigation-tabs.md +51 -0
- package/agent-docs/styling/layouts.sections/customize-the-hero.md +50 -0
- package/agent-docs/styling/layouts.sections/hero.md +83 -0
- package/agent-docs/styling/layouts.sections/related-reading.md +42 -0
- package/agent-docs/styling/palettes.md +140 -0
- package/agent-docs/styling/share-images.md +105 -0
- package/agent-docs/styling/themes.md +125 -0
- package/agent-docs/styling/try.md +106 -0
- package/agent-docs/what-is-shoalrun.md +56 -0
- package/assets/analytics.js +72 -0
- package/assets/ask-widget.js +320 -0
- package/assets/code-samples.js +28 -0
- package/assets/components.js +32 -0
- package/assets/cookbook-chooser.js +170 -0
- package/assets/copy-markdown.js +24 -0
- package/assets/example-panel.js +77 -0
- package/assets/file-tree.js +49 -0
- package/assets/image-viewer.js +41 -0
- package/assets/mode.js +26 -0
- package/assets/navigation.js +233 -0
- package/assets/reader-filters.js +305 -0
- package/assets/reader.js +111 -0
- package/assets/search-highlight.js +32 -0
- package/assets/search-lexical.js +66 -0
- package/assets/search.js +150 -0
- package/assets/table-filter.js +63 -0
- package/assets/tabs.js +80 -0
- package/assets/theme-preview.css +17 -0
- package/assets/theme-preview.js +135 -0
- package/assets/theme-switcher.js +113 -0
- package/assets/tooltips.js +81 -0
- package/assets/walkthrough.js +233 -0
- package/dist/agent-discovery.d.ts +11 -0
- package/dist/agent-discovery.js +37 -0
- package/dist/analytics.d.ts +2 -0
- package/dist/analytics.js +13 -0
- package/dist/answer-cache.d.ts +24 -0
- package/dist/answer-cache.js +55 -0
- package/dist/answer-cards.d.ts +71 -0
- package/dist/answer-cards.js +148 -0
- package/dist/api-embeds.d.ts +22 -0
- package/dist/api-embeds.js +84 -0
- package/dist/api-identity.d.ts +6 -0
- package/dist/api-identity.js +7 -0
- package/dist/api-materialize.d.ts +12 -0
- package/dist/api-materialize.js +120 -0
- package/dist/api-publication-plan.d.ts +86 -0
- package/dist/api-publication-plan.js +187 -0
- package/dist/api-publication-review.d.ts +23 -0
- package/dist/api-publication-review.js +58 -0
- package/dist/api-selection.d.ts +21 -0
- package/dist/api-selection.js +84 -0
- package/dist/api.d.ts +74 -0
- package/dist/api.js +782 -0
- package/dist/artifact-bundle.d.ts +96 -0
- package/dist/artifact-bundle.js +306 -0
- package/dist/ask-function.d.ts +19 -0
- package/dist/ask-function.js +139 -0
- package/dist/ask-handler.d.ts +38 -0
- package/dist/ask-handler.js +157 -0
- package/dist/ask-log-kv.d.ts +14 -0
- package/dist/ask-log-kv.js +69 -0
- package/dist/ask-log.d.ts +106 -0
- package/dist/ask-log.js +159 -0
- package/dist/ask-setup.d.ts +43 -0
- package/dist/ask-setup.js +99 -0
- package/dist/ask.d.ts +152 -0
- package/dist/ask.js +532 -0
- package/dist/audit.d.ts +29 -0
- package/dist/audit.js +171 -0
- package/dist/authored-change.d.ts +22 -0
- package/dist/authored-change.js +47 -0
- package/dist/authoring-api.d.ts +18 -0
- package/dist/authoring-api.js +15 -0
- package/dist/authoring-findings.d.ts +31 -0
- package/dist/authoring-findings.js +104 -0
- package/dist/authoring-guidance.d.ts +15 -0
- package/dist/authoring-guidance.js +57 -0
- package/dist/authoring-preview.d.ts +24 -0
- package/dist/authoring-preview.js +160 -0
- package/dist/authoring-project-command.d.ts +7 -0
- package/dist/authoring-project-command.js +52 -0
- package/dist/authoring-project.d.ts +104 -0
- package/dist/authoring-project.js +287 -0
- package/dist/authoring-review-command.d.ts +1 -0
- package/dist/authoring-review-command.js +68 -0
- package/dist/authoring-review.d.ts +72 -0
- package/dist/authoring-review.js +71 -0
- package/dist/authoring-snapshot.d.ts +66 -0
- package/dist/authoring-snapshot.js +293 -0
- package/dist/authoring-validation-command.d.ts +1 -0
- package/dist/authoring-validation-command.js +54 -0
- package/dist/authoring-validation.d.ts +101 -0
- package/dist/authoring-validation.js +348 -0
- package/dist/badges.d.ts +16 -0
- package/dist/badges.js +57 -0
- package/dist/budget-store.d.ts +21 -0
- package/dist/budget-store.js +90 -0
- package/dist/budget.d.ts +45 -0
- package/dist/budget.js +128 -0
- package/dist/build-info.d.ts +10 -0
- package/dist/build-info.js +15 -0
- package/dist/callouts.d.ts +18 -0
- package/dist/callouts.js +63 -0
- package/dist/cards.d.ts +35 -0
- package/dist/cards.js +237 -0
- package/dist/chat-config.d.ts +117 -0
- package/dist/chat-config.js +400 -0
- package/dist/chat-pause.d.ts +1 -0
- package/dist/chat-pause.js +3 -0
- package/dist/chat.d.ts +46 -0
- package/dist/chat.js +78 -0
- package/dist/cli-discovery.d.ts +4 -0
- package/dist/cli-discovery.js +86 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +750 -0
- package/dist/code-samples.d.ts +50 -0
- package/dist/code-samples.js +181 -0
- package/dist/compact-discovery.d.ts +15 -0
- package/dist/compact-discovery.js +78 -0
- package/dist/compiler-config.d.ts +67 -0
- package/dist/compiler-config.js +66 -0
- package/dist/compiler.d.ts +208 -0
- package/dist/compiler.js +524 -0
- package/dist/component-bundle.d.ts +4 -0
- package/dist/component-bundle.js +32 -0
- package/dist/component-content.d.ts +78 -0
- package/dist/component-content.js +47 -0
- package/dist/component-manifest.d.ts +15 -0
- package/dist/component-manifest.js +84 -0
- package/dist/component-names.d.ts +1 -0
- package/dist/component-names.js +1 -0
- package/dist/component-plugins.d.ts +28 -0
- package/dist/component-plugins.js +141 -0
- package/dist/component-transform.d.ts +10 -0
- package/dist/component-transform.js +697 -0
- package/dist/components.d.ts +2 -0
- package/dist/components.js +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.js +149 -0
- package/dist/content-export-assets.d.ts +23 -0
- package/dist/content-export-assets.js +103 -0
- package/dist/content-export-command.d.ts +20 -0
- package/dist/content-export-command.js +57 -0
- package/dist/content-export-config.d.ts +16 -0
- package/dist/content-export-config.js +50 -0
- package/dist/content-export-render.d.ts +12 -0
- package/dist/content-export-render.js +132 -0
- package/dist/content-export.d.ts +30 -0
- package/dist/content-export.js +307 -0
- package/dist/content-filter.d.ts +4 -0
- package/dist/content-filter.js +16 -0
- package/dist/content-source.d.ts +100 -0
- package/dist/content-source.js +42 -0
- package/dist/content-workspace.d.ts +293 -0
- package/dist/content-workspace.js +69 -0
- package/dist/content.d.ts +41 -0
- package/dist/content.js +176 -0
- package/dist/cookbook-chooser.d.ts +19 -0
- package/dist/cookbook-chooser.js +56 -0
- package/dist/dev.d.ts +2 -0
- package/dist/dev.js +113 -0
- package/dist/diagram-svg.d.ts +1 -0
- package/dist/diagram-svg.js +44 -0
- package/dist/diagrams.d.ts +7 -0
- package/dist/diagrams.js +102 -0
- package/dist/docs-author.d.ts +86 -0
- package/dist/docs-author.js +380 -0
- package/dist/docs-command.d.ts +8 -0
- package/dist/docs-command.js +62 -0
- package/dist/docs-eval.d.ts +146 -0
- package/dist/docs-eval.js +231 -0
- package/dist/docs-mcp.d.ts +12 -0
- package/dist/docs-mcp.js +82 -0
- package/dist/docs-tool.d.ts +81 -0
- package/dist/docs-tool.js +7 -0
- package/dist/document-sync.d.ts +36 -0
- package/dist/document-sync.js +58 -0
- package/dist/documentation-core.d.ts +148 -0
- package/dist/documentation-core.js +160 -0
- package/dist/embeddings.d.ts +68 -0
- package/dist/embeddings.js +198 -0
- package/dist/focused-audit.d.ts +10 -0
- package/dist/focused-audit.js +69 -0
- package/dist/focused-openapi.d.ts +2 -0
- package/dist/focused-openapi.js +140 -0
- package/dist/fonts.d.ts +54 -0
- package/dist/fonts.js +92 -0
- package/dist/freshness.d.ts +7 -0
- package/dist/freshness.js +58 -0
- package/dist/frontmatter.d.ts +24 -0
- package/dist/frontmatter.js +342 -0
- package/dist/function-package.d.ts +1 -0
- package/dist/function-package.js +58 -0
- package/dist/highlight.d.ts +14 -0
- package/dist/highlight.js +114 -0
- package/dist/html-renderer.d.ts +10 -0
- package/dist/html-renderer.js +63 -0
- package/dist/icons.d.ts +8 -0
- package/dist/icons.js +40 -0
- package/dist/index-build.d.ts +55 -0
- package/dist/index-build.js +227 -0
- package/dist/ingredient-draft.d.ts +17 -0
- package/dist/ingredient-draft.js +94 -0
- package/dist/ingredient-workflow.d.ts +8 -0
- package/dist/ingredient-workflow.js +25 -0
- package/dist/init.d.ts +8 -0
- package/dist/init.js +66 -0
- package/dist/jev.d.ts +62 -0
- package/dist/jev.js +190 -0
- package/dist/link-audit.d.ts +12 -0
- package/dist/link-audit.js +146 -0
- package/dist/llms-discovery.d.ts +11 -0
- package/dist/llms-discovery.js +23 -0
- package/dist/markdown-sections.d.ts +15 -0
- package/dist/markdown-sections.js +60 -0
- package/dist/markdown-size.d.ts +7 -0
- package/dist/markdown-size.js +6 -0
- package/dist/mcp-analytics.d.ts +38 -0
- package/dist/mcp-analytics.js +35 -0
- package/dist/mcp-artifacts.d.ts +2 -0
- package/dist/mcp-artifacts.js +78 -0
- package/dist/mcp-client-metadata.d.ts +18 -0
- package/dist/mcp-client-metadata.js +69 -0
- package/dist/mcp-config.d.ts +23 -0
- package/dist/mcp-config.js +56 -0
- package/dist/mcp-http.d.ts +19 -0
- package/dist/mcp-http.js +157 -0
- package/dist/mcp-integrity.d.ts +3 -0
- package/dist/mcp-integrity.js +4 -0
- package/dist/mcp-node.d.ts +4 -0
- package/dist/mcp-node.js +68 -0
- package/dist/mcp-vercel-runtime.d.ts +3 -0
- package/dist/mcp-vercel-runtime.js +36 -0
- package/dist/mcp-vercel.d.ts +15 -0
- package/dist/mcp-vercel.js +65 -0
- package/dist/metadata-provider.d.ts +19 -0
- package/dist/metadata-provider.js +38 -0
- package/dist/negotiation.d.ts +10 -0
- package/dist/negotiation.js +35 -0
- package/dist/not-found.d.ts +16 -0
- package/dist/not-found.js +25 -0
- package/dist/output-commit.d.ts +1 -0
- package/dist/output-commit.js +133 -0
- package/dist/output-location.d.ts +3 -0
- package/dist/output-location.js +30 -0
- package/dist/page-materialization.d.ts +78 -0
- package/dist/page-materialization.js +132 -0
- package/dist/page-renderer.d.ts +71 -0
- package/dist/page-renderer.js +177 -0
- package/dist/palettes.d.ts +41 -0
- package/dist/palettes.js +160 -0
- package/dist/procedure-components.d.ts +2 -0
- package/dist/procedure-components.js +94 -0
- package/dist/project-navigation.d.ts +41 -0
- package/dist/project-navigation.js +190 -0
- package/dist/provider-http.d.ts +10 -0
- package/dist/provider-http.js +60 -0
- package/dist/publication-manifest.d.ts +229 -0
- package/dist/publication-manifest.js +53 -0
- package/dist/publication-plan.d.ts +34 -0
- package/dist/publication-plan.js +85 -0
- package/dist/publication-render.d.ts +71 -0
- package/dist/publication-render.js +92 -0
- package/dist/reader-filters.d.ts +30 -0
- package/dist/reader-filters.js +105 -0
- package/dist/recipe-draft.d.ts +17 -0
- package/dist/recipe-draft.js +147 -0
- package/dist/reference-audit.d.ts +18 -0
- package/dist/reference-audit.js +169 -0
- package/dist/remote-import.d.ts +62 -0
- package/dist/remote-import.js +292 -0
- package/dist/representation-tree.d.ts +3 -0
- package/dist/representation-tree.js +320 -0
- package/dist/retrieval-config.d.ts +30 -0
- package/dist/retrieval-config.js +83 -0
- package/dist/retrieval.d.ts +60 -0
- package/dist/retrieval.js +228 -0
- package/dist/scaffold.d.ts +39 -0
- package/dist/scaffold.js +167 -0
- package/dist/search-config.d.ts +8 -0
- package/dist/search-config.js +26 -0
- package/dist/search-handler.d.ts +16 -0
- package/dist/search-handler.js +111 -0
- package/dist/search-identifier.d.ts +3 -0
- package/dist/search-identifier.js +25 -0
- package/dist/search-literal.d.ts +1 -0
- package/dist/search-literal.js +28 -0
- package/dist/search-query.d.ts +54 -0
- package/dist/search-query.js +120 -0
- package/dist/search-results.d.ts +6 -0
- package/dist/search-results.js +45 -0
- package/dist/search-snippet.d.ts +11 -0
- package/dist/search-snippet.js +93 -0
- package/dist/search-synonyms.d.ts +8 -0
- package/dist/search-synonyms.js +46 -0
- package/dist/semantic-markdown.d.ts +10 -0
- package/dist/semantic-markdown.js +39 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +223 -0
- package/dist/share-images.d.ts +24 -0
- package/dist/share-images.js +187 -0
- package/dist/site-path.d.ts +2 -0
- package/dist/site-path.js +15 -0
- package/dist/sitemap.d.ts +8 -0
- package/dist/sitemap.js +58 -0
- package/dist/snippets.d.ts +19 -0
- package/dist/snippets.js +84 -0
- package/dist/structured-model-output.d.ts +6 -0
- package/dist/structured-model-output.js +21 -0
- package/dist/subject-deprecation.d.ts +21 -0
- package/dist/subject-deprecation.js +57 -0
- package/dist/surface-text.d.ts +4 -0
- package/dist/surface-text.js +42 -0
- package/dist/taxonomy.d.ts +14 -0
- package/dist/taxonomy.js +88 -0
- package/dist/turnstile.d.ts +21 -0
- package/dist/turnstile.js +52 -0
- package/dist/vale.d.ts +28 -0
- package/dist/vale.js +103 -0
- package/dist/vercel-function.d.ts +21 -0
- package/dist/vercel-function.js +108 -0
- package/dist/vercel.d.ts +11 -0
- package/dist/vercel.js +103 -0
- package/dist/walkthrough.d.ts +25 -0
- package/dist/walkthrough.js +336 -0
- package/dist/yaml-value.d.ts +2 -0
- package/dist/yaml-value.js +36 -0
- package/example-configs/api-docs/README.md +59 -0
- package/example-configs/api-docs/apis/cedar-parcel.yaml +413 -0
- package/example-configs/api-docs/content/create-enrollment.mdx +11 -0
- package/example-configs/api-docs/content/overview.mdx +36 -0
- package/example-configs/api-docs/content/quickstart.mdx +52 -0
- package/example-configs/api-docs/docs.config.yaml +104 -0
- package/example-configs/faceted-sites/README.md +31 -0
- package/example-configs/faceted-sites/base.yaml +30 -0
- package/example-configs/faceted-sites/content/api.md +12 -0
- package/example-configs/faceted-sites/content/home.md +10 -0
- package/example-configs/faceted-sites/content/operations.md +12 -0
- package/example-configs/faceted-sites/developers.config.yaml +8 -0
- package/example-configs/faceted-sites/docs.config.yaml +7 -0
- package/example-configs/faceted-sites/europe.config.yaml +9 -0
- package/example-configs/minimal/content/install.mdx +12 -0
- package/example-configs/minimal/content/welcome.mdx +8 -0
- package/example-configs/minimal/docs.config.yaml +31 -0
- package/example-configs/multilingual/content/de/home.mdx +9 -0
- package/example-configs/multilingual/content/de/reset-password.mdx +9 -0
- package/example-configs/multilingual/content/home.mdx +10 -0
- package/example-configs/multilingual/content/reset-password.mdx +12 -0
- package/example-configs/multilingual/docs.config.yaml +61 -0
- package/example-configs/multilingual/snippets/contact.mdx +1 -0
- package/example-configs/notifications/apis/notifications.yaml +132 -0
- package/example-configs/notifications/content/cookbook.mdx +17 -0
- package/example-configs/notifications/content/get-message.mdx +14 -0
- package/example-configs/notifications/content/queue-email.mdx +42 -0
- package/example-configs/notifications/content/queue-push.mdx +33 -0
- package/example-configs/notifications/content/queue-sms.mdx +33 -0
- package/example-configs/notifications/content/send-email.mdx +14 -0
- package/example-configs/notifications/content/send-push.mdx +14 -0
- package/example-configs/notifications/content/send-sms.mdx +14 -0
- package/example-configs/notifications/content/start.mdx +13 -0
- package/example-configs/notifications/content/welcome-cookbook.mdx +21 -0
- package/example-configs/notifications/content/welcome-email.mdx +82 -0
- package/example-configs/notifications/demo.mjs +43 -0
- package/example-configs/notifications/docs.config.yaml +88 -0
- package/example-configs/notifications/ingredient-drafts/README.md +41 -0
- package/example-configs/notifications/ingredient-drafts/check-delivery.mdx +13 -0
- package/example-configs/notifications/ingredient-drafts/queue-welcome-email.mdx +48 -0
- package/example-configs/notifications/ingredient-specs/queue-welcome-email.yaml +7 -0
- package/example-configs/notifications/ingredients/check-delivery.mdx +42 -0
- package/example-configs/notifications/ingredients/queue-welcome-email.mdx +37 -0
- package/example-configs/notifications/recipe-drafts/send-welcome-email.mdx +91 -0
- package/example-configs/notifications/recipe-specs/send-welcome-email.yaml +11 -0
- package/example-configs/reference-stress/README.md +32 -0
- package/example-configs/reference-stress/apis/cedar-parcel.yaml +413 -0
- package/example-configs/reference-stress/content/enrollment-shapes.mdx +16 -0
- package/example-configs/reference-stress/content/overview.mdx +14 -0
- package/example-configs/reference-stress/docs.config.yaml +55 -0
- package/example-configs/shared-preset/shared/company-docs.yaml +46 -0
- package/example-configs/shared-preset/shared/runbook.mdx +7 -0
- package/example-configs/shared-preset/site/content/failed-invoices.mdx +15 -0
- package/example-configs/shared-preset/site/content/start.mdx +9 -0
- package/example-configs/shared-preset/site/docs.config.yaml +18 -0
- package/example-configs/showcase/README.md +20 -0
- package/example-configs/showcase/apis/cedar-parcel.yaml +413 -0
- package/example-configs/showcase/content/assets/collection.svg +1 -0
- package/example-configs/showcase/content/code.mdx +100 -0
- package/example-configs/showcase/content/create-enrollment.mdx +11 -0
- package/example-configs/showcase/content/features.mdx +39 -0
- package/example-configs/showcase/content/landing.mdx +36 -0
- package/example-configs/showcase/content/overview.mdx +42 -0
- package/example-configs/showcase/content/personalization.mdx +38 -0
- package/example-configs/showcase/content/preview.mdx +35 -0
- package/example-configs/showcase/content/procedures.mdx +88 -0
- package/example-configs/showcase/content/quickstart.mdx +64 -0
- package/example-configs/showcase/content/reading.mdx +99 -0
- package/example-configs/showcase/content/verify.mdx +27 -0
- package/example-configs/showcase/content/visuals.mdx +47 -0
- package/example-configs/showcase/content/workflows.mdx +12 -0
- package/example-configs/showcase/docs.config.yaml +149 -0
- package/example-configs/showcase/snippets/sandbox.mdx +1 -0
- package/examples/analytics/README.md +56 -0
- package/examples/analytics/inspector.js +25 -0
- package/examples/analytics/posthog.js +36 -0
- package/examples/components/comparison.mjs +8 -0
- package/examples/components/components.json +6 -0
- package/examples/components/copy-text/LICENSE.react-dom.txt +21 -0
- package/examples/components/copy-text/LICENSE.react.txt +21 -0
- package/examples/components/copy-text/LICENSE.scheduler.txt +21 -0
- package/examples/components/copy-text/browser.jsx +21 -0
- package/examples/components/copy-text/components.json +6 -0
- package/examples/components/copy-text/package-lock.json +41 -0
- package/examples/components/copy-text/package.json +9 -0
- package/examples/components/copy-text/plugin.mjs +5 -0
- package/examples/components/retry-budget/LICENSE.react-dom.txt +21 -0
- package/examples/components/retry-budget/LICENSE.react.txt +21 -0
- package/examples/components/retry-budget/LICENSE.scheduler.txt +21 -0
- package/examples/components/retry-budget/browser.jsx +50 -0
- package/examples/components/retry-budget/components.json +6 -0
- package/examples/components/retry-budget/model.js +22 -0
- package/examples/components/retry-budget/package-lock.json +41 -0
- package/examples/components/retry-budget/package.json +9 -0
- package/examples/components/retry-budget/plugin.mjs +31 -0
- package/examples/components/retry-budget/policy.json +9 -0
- package/examples/components/retry-budget/style.css +25 -0
- package/examples/diagrams/d2-gallery.json +138 -0
- package/examples/diagrams/gallery.json +236 -0
- package/examples/help-drawer/README.md +44 -0
- package/examples/help-drawer/app.js +53 -0
- package/examples/help-drawer/components/components.json +1 -0
- package/examples/help-drawer/components/support.mjs +10 -0
- package/examples/help-drawer/content/account.md +8 -0
- package/examples/help-drawer/content/billing.mdx +29 -0
- package/examples/help-drawer/content/keys.mdx +46 -0
- package/examples/help-drawer/content/settings.svg +1 -0
- package/examples/help-drawer/docs.config.yaml +30 -0
- package/examples/help-drawer/index.html +26 -0
- package/examples/help-drawer/preview.mjs +33 -0
- package/examples/mcp-analytics/README.md +59 -0
- package/examples/mcp-analytics/posthog.mjs +159 -0
- package/package.json +100 -4
- package/schemas/content-export.schema.json +55 -0
- package/skills/shoalrun-author/SKILL.md +52 -0
- package/skills/shoalrun-component-author/SKILL.md +24 -0
- package/skills/shoalrun-recipes/SKILL.md +25 -0
- package/skills/shoalrun-setup/SKILL.md +34 -0
- package/skills/shoalrun-walkthrough/SKILL.md +18 -0
- package/styles/fonts/figtree-LICENSE.txt +93 -0
- package/styles/fonts/figtree-italic.woff2 +0 -0
- package/styles/fonts/figtree.woff2 +0 -0
- package/styles/fonts/inter-LICENSE.txt +93 -0
- package/styles/fonts/inter-italic.woff2 +0 -0
- package/styles/fonts/inter.woff2 +0 -0
- package/styles/fonts/jetbrains-mono-LICENSE.txt +93 -0
- package/styles/fonts/jetbrains-mono.woff2 +0 -0
- package/styles/fonts/jost-LICENSE.txt +93 -0
- package/styles/fonts/jost-italic.woff2 +0 -0
- package/styles/fonts/jost.woff2 +0 -0
- package/styles/fonts/share/figtree-400.ttf +0 -0
- package/styles/fonts/share/figtree-700.ttf +0 -0
- package/styles/fonts/share/inter-400.ttf +0 -0
- package/styles/fonts/share/inter-700.ttf +0 -0
- package/styles/fonts/share/jetbrains-mono-700.ttf +0 -0
- package/styles/fonts/share/jost-italic-800.ttf +0 -0
- package/styles/fonts/share/metrics.json +1 -0
- package/styles/fonts/share/source-serif-4-400.ttf +0 -0
- package/styles/fonts/source-serif-4-LICENSE.txt +93 -0
- package/styles/fonts/source-serif-4-italic.woff2 +0 -0
- package/styles/fonts/source-serif-4.woff2 +0 -0
- package/styles/header.css +56 -0
- package/styles/site.css +825 -0
- package/styles/themes/ledger.css +93 -0
- package/styles/themes/palettes/amethyst.yaml +127 -0
- package/styles/themes/palettes/coral.yaml +127 -0
- package/styles/themes/palettes/harbor.yaml +127 -0
- package/styles/themes/palettes/ink.yaml +127 -0
- package/styles/themes/palettes/kelp.yaml +127 -0
- package/styles/themes/palettes/vice.yaml +127 -0
- package/styles/themes/reef.css +68 -0
- package/styles/themes/vice.css +56 -0
- package/styles/tokens.css +91 -0
- package/templates/api-reference.mdx +133 -0
- package/templates/cookbook.mdx +38 -0
- package/templates/explanation.mdx +76 -0
- package/templates/guide.mdx +175 -0
- package/templates/how-to.mdx +171 -0
- package/templates/ingredient.mdx +53 -0
- package/templates/recipe.mdx +76 -0
- package/templates/reference.mdx +171 -0
- package/templates/troubleshooting.mdx +159 -0
- package/templates/tutorial.mdx +165 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type ValidationFinding } from './authoring-findings.js';
|
|
2
|
+
import { type SnapshotCapture, type SnapshotInput } from './authoring-snapshot.js';
|
|
3
|
+
export type ValidationOptions = {
|
|
4
|
+
files?: string[];
|
|
5
|
+
ids?: string[];
|
|
6
|
+
baselineFile?: string;
|
|
7
|
+
artifactsDirectory?: string;
|
|
8
|
+
runConfiguredChecks?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type ValidationCheck = {
|
|
11
|
+
id: string;
|
|
12
|
+
status: 'passed' | 'failed' | 'skipped' | 'unavailable';
|
|
13
|
+
explanation?: string;
|
|
14
|
+
documents?: number;
|
|
15
|
+
findings?: number;
|
|
16
|
+
};
|
|
17
|
+
export type ValidationReport = {
|
|
18
|
+
schemaVersion: 1;
|
|
19
|
+
kind: 'shoalrun-authoring-validation';
|
|
20
|
+
status: 'ok' | 'failed' | 'incomplete' | 'unavailable' | 'stale';
|
|
21
|
+
snapshotId: string;
|
|
22
|
+
project: string;
|
|
23
|
+
config: string;
|
|
24
|
+
baseline: {
|
|
25
|
+
kind: 'explicit-declaration' | 'task-baseline';
|
|
26
|
+
file?: string;
|
|
27
|
+
digest?: string;
|
|
28
|
+
};
|
|
29
|
+
changed: Array<{
|
|
30
|
+
file: string;
|
|
31
|
+
operation: 'created' | 'modified' | 'deleted' | 'declared';
|
|
32
|
+
beforeDigest: string | null;
|
|
33
|
+
digest: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
inputs: SnapshotInput[];
|
|
36
|
+
excluded: SnapshotCapture['excluded'];
|
|
37
|
+
externalDirectories: string[];
|
|
38
|
+
contentDigest: string;
|
|
39
|
+
configDigest?: string;
|
|
40
|
+
validatorDigest: string;
|
|
41
|
+
runtimeDependencies: SnapshotInput[];
|
|
42
|
+
dependencies: string[];
|
|
43
|
+
checks: ValidationCheck[];
|
|
44
|
+
findings: ValidationFinding[];
|
|
45
|
+
coverage: {
|
|
46
|
+
scope: 'complete-captured-project';
|
|
47
|
+
authored: string[];
|
|
48
|
+
affected: string[];
|
|
49
|
+
rendered: Array<{
|
|
50
|
+
id: string;
|
|
51
|
+
file: string;
|
|
52
|
+
route: string;
|
|
53
|
+
markdown: string;
|
|
54
|
+
}>;
|
|
55
|
+
notRendered: string[];
|
|
56
|
+
};
|
|
57
|
+
artifacts: {
|
|
58
|
+
directory: string;
|
|
59
|
+
project: string;
|
|
60
|
+
site: string;
|
|
61
|
+
report: string;
|
|
62
|
+
digest: string | null;
|
|
63
|
+
lifecycle: string;
|
|
64
|
+
};
|
|
65
|
+
freshness: {
|
|
66
|
+
current: boolean;
|
|
67
|
+
checkedAt: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export declare function validationArtifactDigest(directory: string): Promise<string | null>;
|
|
71
|
+
/** Public entry: no plan/apply, source writes, provider or autonomous orchestration. */
|
|
72
|
+
export declare function validateAuthoringChanges(configFile: string, options: ValidationOptions): Promise<ValidationReport>;
|
|
73
|
+
export declare function validateAuthoringChangesWithHooks(configFile: string, options: ValidationOptions, hooks?: {
|
|
74
|
+
afterCapture?: () => Promise<void>;
|
|
75
|
+
afterChecks?: () => Promise<void>;
|
|
76
|
+
}): Promise<ValidationReport>;
|
|
77
|
+
/** Shared reader for retained reports; this never runs project code. */
|
|
78
|
+
export declare function readValidationReport(reportFile: string): Promise<ValidationReport>;
|
|
79
|
+
/** Refresh applicability without rebuilding, applying or mutating source. */
|
|
80
|
+
export declare function authoringValidationStatus(reportFile: string): Promise<{
|
|
81
|
+
schemaVersion: number;
|
|
82
|
+
status: "stale" | "failed" | "ok" | "unavailable" | "incomplete";
|
|
83
|
+
snapshotId: string;
|
|
84
|
+
report: string;
|
|
85
|
+
current: boolean;
|
|
86
|
+
changed: {
|
|
87
|
+
source: boolean;
|
|
88
|
+
baseline: boolean;
|
|
89
|
+
validator: boolean;
|
|
90
|
+
artifacts: boolean;
|
|
91
|
+
};
|
|
92
|
+
nextAction: string;
|
|
93
|
+
}>;
|
|
94
|
+
export declare const validationFailure: (error: unknown) => {
|
|
95
|
+
schemaVersion: number;
|
|
96
|
+
status: string;
|
|
97
|
+
error: {
|
|
98
|
+
code: string;
|
|
99
|
+
message: string;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { chmod, mkdir, mkdtemp, readFile, readdir, realpath, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { compile } from './compiler.js';
|
|
7
|
+
import { loadConfig } from './config.js';
|
|
8
|
+
import { readDocument } from './content-source.js';
|
|
9
|
+
import { auditLinks } from './link-audit.js';
|
|
10
|
+
import { auditFocusedContracts } from './focused-audit.js';
|
|
11
|
+
import { auditReference } from './reference-audit.js';
|
|
12
|
+
import { iconLicenseFile } from './icons.js';
|
|
13
|
+
import { parseAuditSettings, runAuditTest } from './audit.js';
|
|
14
|
+
import { configFindingLocation, validationFinding } from './authoring-findings.js';
|
|
15
|
+
import { authoringArtifactPath, captureSnapshotInputs, collectSnapshotInputs, confirmSnapshotInputs, excludedNames, isWithin, parseAuthoringBaseline, relativeInput, sha256, SnapshotError, validatorInputs } from './authoring-snapshot.js';
|
|
16
|
+
const framework = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
|
+
// Include ordinary hoisted dependency locations in installed npm packages too.
|
|
18
|
+
const checkModulePaths = (createRequire(import.meta.url).resolve.paths('yaml') ?? []).filter(directory => path.basename(directory) === 'node_modules').join(path.delimiter);
|
|
19
|
+
const modes = new Set(['created', 'modified', 'deleted', 'declared']);
|
|
20
|
+
const finding = (code, explanation, nextAction, severity = 'error') => ({ code, severity, explanation, nextAction });
|
|
21
|
+
export async function validationArtifactDigest(directory) {
|
|
22
|
+
const entries = [];
|
|
23
|
+
const visit = async (current) => {
|
|
24
|
+
for (const entry of (await readdir(current, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
25
|
+
const file = path.join(current, entry.name);
|
|
26
|
+
if (entry.isDirectory())
|
|
27
|
+
await visit(file);
|
|
28
|
+
else if (entry.isFile())
|
|
29
|
+
entries.push([path.relative(directory, file), sha256(await readFile(file))]);
|
|
30
|
+
else
|
|
31
|
+
throw new SnapshotError('unsafe_path', 'Artifacts must contain regular files and directories');
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
await visit(directory);
|
|
36
|
+
return sha256(JSON.stringify(entries));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error.code === 'ENOENT')
|
|
40
|
+
return null;
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function checkedOptions(options) {
|
|
45
|
+
const selected = (options.files?.length ?? 0) + (options.ids?.length ?? 0);
|
|
46
|
+
if (options.baselineFile && selected || !options.baselineFile && !selected)
|
|
47
|
+
throw new SnapshotError('invalid_input', 'Validate with explicit files/IDs or one task baseline, not both.');
|
|
48
|
+
for (const key of ['files', 'ids'])
|
|
49
|
+
if (options[key] !== undefined && (!Array.isArray(options[key]) || options[key].some(item => typeof item !== 'string' || !item.trim()) || new Set(options[key]).size !== options[key].length))
|
|
50
|
+
throw new SnapshotError('invalid_input', `${key} must contain distinct nonempty strings`);
|
|
51
|
+
if (options.runConfiguredChecks !== undefined && typeof options.runConfiguredChecks !== 'boolean')
|
|
52
|
+
throw new SnapshotError('invalid_input', 'runConfiguredChecks must be boolean');
|
|
53
|
+
}
|
|
54
|
+
/** Public entry: no plan/apply, source writes, provider or autonomous orchestration. */
|
|
55
|
+
export async function validateAuthoringChanges(configFile, options) {
|
|
56
|
+
return validateAuthoringChangesWithHooks(configFile, options);
|
|
57
|
+
}
|
|
58
|
+
// Internal injection boundary for deterministic capture/check race fixtures.
|
|
59
|
+
export async function validateAuthoringChangesWithHooks(configFile, options, hooks = {}) {
|
|
60
|
+
checkedOptions(options);
|
|
61
|
+
const capture = await captureSnapshotInputs(configFile);
|
|
62
|
+
const runtime = await validatorInputs();
|
|
63
|
+
let baseline = { kind: 'explicit-declaration' };
|
|
64
|
+
const previous = new Map();
|
|
65
|
+
if (options.baselineFile) {
|
|
66
|
+
const raw = await readFile(options.baselineFile);
|
|
67
|
+
const value = parseAuthoringBaseline(JSON.parse(raw.toString('utf8')), capture.root, capture.config);
|
|
68
|
+
baseline = { kind: 'task-baseline', file: await realpath(options.baselineFile), digest: sha256(raw) };
|
|
69
|
+
for (const input of value.inputs)
|
|
70
|
+
previous.set(input.file, input);
|
|
71
|
+
// A dependency removed from config is not necessarily a deleted file. Retain
|
|
72
|
+
// baseline scope for extant sibling inputs so change classification is honest.
|
|
73
|
+
const oldExternal = [];
|
|
74
|
+
for (const input of value.inputs)
|
|
75
|
+
if ((!isWithin(capture.root, path.resolve(capture.root, input.file)) || input.file.split(path.sep).includes('node_modules')) && await stat(relativeInput(capture.root, input.file)).then(() => true, () => false))
|
|
76
|
+
oldExternal.push(input.file);
|
|
77
|
+
const oldDirectories = [];
|
|
78
|
+
for (const directory of value.externalDirectories)
|
|
79
|
+
if (await stat(relativeInput(capture.root, directory)).then(() => true, () => false))
|
|
80
|
+
oldDirectories.push(directory);
|
|
81
|
+
const combinedDirectories = [...new Set([...capture.externalDirectories, ...oldDirectories])].sort();
|
|
82
|
+
const combined = await collectSnapshotInputs(capture.root, [...new Set([...oldExternal, ...capture.inputs.filter(input => (!isWithin(capture.root, path.resolve(capture.root, input.file)) || input.file.split(path.sep).includes('node_modules'))).map(input => input.file)])], combinedDirectories);
|
|
83
|
+
for (const input of capture.inputs)
|
|
84
|
+
if (combined.inputs.find(current => current.file === input.file)?.digest !== input.digest)
|
|
85
|
+
throw new SnapshotError('stale_input', `Input changed while comparing the task baseline: ${input.file}`);
|
|
86
|
+
Object.assign(capture, combined, { externalDirectories: combinedDirectories });
|
|
87
|
+
}
|
|
88
|
+
let loaded;
|
|
89
|
+
// Loading configuration is read-only. Compilation and executable extensions
|
|
90
|
+
// are never run on the original project.
|
|
91
|
+
try {
|
|
92
|
+
loaded = await loadConfig(path.join(capture.root, capture.config));
|
|
93
|
+
}
|
|
94
|
+
catch { /* Snapshot compiler diagnoses invalid YAML/config. */ }
|
|
95
|
+
const contentDir = path.resolve(capture.root, String(loaded?.value.site?.contentDir ?? 'content'));
|
|
96
|
+
if (!isWithin(capture.root, contentDir) || contentDir === capture.root)
|
|
97
|
+
throw new SnapshotError('unsafe_path', 'Authoring validation requires content inside the project configuration directory.');
|
|
98
|
+
const authored = capture.inputs.filter(input => isWithin(contentDir, path.resolve(capture.root, input.file)) && /\.mdx?$/.test(input.file)).map(input => input.file);
|
|
99
|
+
const selected = new Set();
|
|
100
|
+
if (baseline.kind === 'task-baseline') {
|
|
101
|
+
for (const file of new Set([...previous.keys(), ...capture.inputs.map(input => input.file)])) {
|
|
102
|
+
const old = previous.get(file), current = capture.inputs.find(input => input.file === file);
|
|
103
|
+
if (old?.digest !== current?.digest || old?.mode !== current?.mode)
|
|
104
|
+
selected.add(file);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
for (const file of options.files ?? []) {
|
|
109
|
+
const absolute = relativeInput(capture.root, file);
|
|
110
|
+
const normalized = path.relative(capture.root, absolute);
|
|
111
|
+
if (normalized.split(path.sep).some(part => excludedNames.has(part) || part === '.env' || part.startsWith('.env.')))
|
|
112
|
+
throw new SnapshotError('invalid_input', `Selected file is excluded from capture: ${file}`);
|
|
113
|
+
if (!isWithin(capture.root, absolute) && !capture.inputs.some(input => input.file === normalized))
|
|
114
|
+
throw new SnapshotError('invalid_input', `Select an existing captured dependency: ${file}`);
|
|
115
|
+
selected.add(normalized);
|
|
116
|
+
}
|
|
117
|
+
for (const id of options.ids ?? []) {
|
|
118
|
+
let matched = false;
|
|
119
|
+
for (const file of authored) {
|
|
120
|
+
try {
|
|
121
|
+
const doc = await readDocument(path.join(capture.root, file), loaded?.value.frontmatter, undefined, capture.buffers.get(file).toString('utf8'));
|
|
122
|
+
if (doc.frontmatter.id === id) {
|
|
123
|
+
selected.add(file);
|
|
124
|
+
matched = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch { /* Broken pages can be explicitly selected by path. */ }
|
|
128
|
+
}
|
|
129
|
+
if (!matched)
|
|
130
|
+
throw new SnapshotError('invalid_input', `No authored page with ID ${id}; select a broken or deleted page by file path.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const changed = [...selected].sort().map(file => {
|
|
134
|
+
const old = previous.get(file), current = capture.inputs.find(input => input.file === file);
|
|
135
|
+
return { file, operation: (!current ? 'deleted' : baseline.kind === 'explicit-declaration' ? 'declared' : !old ? 'created' : 'modified'), beforeDigest: old?.digest ?? null, digest: current?.digest ?? null };
|
|
136
|
+
});
|
|
137
|
+
// Configuration, snippets, source dependencies and deletions can affect any
|
|
138
|
+
// page. Use conservative complete-site coverage rather than missing companions.
|
|
139
|
+
const broad = [...selected].some(file => !authored.includes(file));
|
|
140
|
+
const affected = broad ? authored : authored.filter(file => selected.has(file));
|
|
141
|
+
const contentDigest = sha256(JSON.stringify(capture.inputs));
|
|
142
|
+
const snapshotId = sha256(JSON.stringify([capture.config, contentDigest, runtime.digest, baseline, changed, !!options.runConfiguredChecks]));
|
|
143
|
+
const directory = options.artifactsDirectory ? await authoringArtifactPath(capture.root, options.artifactsDirectory) : await realpath(await mkdtemp(path.join(os.tmpdir(), 'shoalrun-validation-')));
|
|
144
|
+
if (options.artifactsDirectory) {
|
|
145
|
+
await mkdir(path.dirname(directory), { recursive: true });
|
|
146
|
+
await mkdir(directory);
|
|
147
|
+
}
|
|
148
|
+
const tree = path.join(directory, 'tree'), shadow = path.join(tree, path.basename(capture.root)), site = path.join(directory, 'site');
|
|
149
|
+
const report = { schemaVersion: 1, kind: 'shoalrun-authoring-validation', status: 'incomplete', snapshotId, project: capture.root, config: capture.config, baseline, changed, inputs: capture.inputs, excluded: capture.excluded, externalDirectories: capture.externalDirectories, contentDigest, configDigest: capture.configDigest, validatorDigest: runtime.digest, runtimeDependencies: [], dependencies: [], checks: [], findings: [],
|
|
150
|
+
coverage: { scope: 'complete-captured-project', authored, affected, rendered: [], notRendered: [...affected] },
|
|
151
|
+
artifacts: { directory, project: shadow, site, report: path.join(directory, 'report.json'), digest: null, lifecycle: 'Retained local validation artifacts. Remove this artifact directory when finished; it is separate from working-tree source. No preview service is started.' },
|
|
152
|
+
freshness: { current: true, checkedAt: new Date().toISOString() } };
|
|
153
|
+
const addError = (error) => report.findings.push(validationFinding(error, capture, shadow, loaded));
|
|
154
|
+
const absentInputsUnchanged = async () => {
|
|
155
|
+
for (const input of changed)
|
|
156
|
+
if (input.digest === null && await stat(path.resolve(capture.root, input.file)).then(() => true, () => false))
|
|
157
|
+
return false;
|
|
158
|
+
return true;
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
for (const input of capture.inputs) {
|
|
162
|
+
const target = path.resolve(shadow, input.file);
|
|
163
|
+
if (!isWithin(tree, target))
|
|
164
|
+
throw new SnapshotError('unsafe_path', `Cannot materialize ${input.file}`);
|
|
165
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
166
|
+
await writeFile(target, capture.buffers.get(input.file), { flag: 'wx' });
|
|
167
|
+
await chmod(target, input.mode);
|
|
168
|
+
}
|
|
169
|
+
// Preserve the repository boundary for sibling Walkthrough sources without
|
|
170
|
+
// copying Git metadata or making the working tree a build destination.
|
|
171
|
+
if (await stat(path.join(path.dirname(capture.root), '.git')).then(() => true, () => false))
|
|
172
|
+
await mkdir(path.join(tree, '.git'));
|
|
173
|
+
await hooks.afterCapture?.();
|
|
174
|
+
if (!await confirmSnapshotInputs(capture) || !await absentInputsUnchanged())
|
|
175
|
+
throw new SnapshotError('stale_input', 'Working tree changed during snapshot capture; retry validation.');
|
|
176
|
+
const stagedConfig = path.join(shadow, capture.config);
|
|
177
|
+
loaded = await loadConfig(stagedConfig);
|
|
178
|
+
if (capture.configDigest && loaded.digest !== capture.configDigest)
|
|
179
|
+
throw new SnapshotError('stale_input', 'Captured configuration does not match the inspected configuration; retry.');
|
|
180
|
+
// Local executable metadata/highlighting modules are not a provider-free
|
|
181
|
+
// inspection primitive. Report unavailable instead of executing unknown code.
|
|
182
|
+
const config = loaded.value;
|
|
183
|
+
if (config.metadata?.provider || config.outputs?.html?.highlighting?.module) {
|
|
184
|
+
report.checks.push({ id: 'compile', status: 'unavailable', explanation: 'Custom executable metadata/highlighting modules are not supported by snapshot validation yet.' });
|
|
185
|
+
report.findings.push(finding('validation.extension-unavailable', 'This project configures an executable metadata/highlighting extension; it was not invoked.', 'Use the existing trusted build workflow, or remove the extension only if project policy permits.', 'review-needed'));
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
for (const file of affected) {
|
|
189
|
+
try {
|
|
190
|
+
const doc = await readDocument(path.join(shadow, file), loaded.value.frontmatter, undefined, capture.buffers.get(file).toString('utf8'));
|
|
191
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(doc.frontmatter.id))
|
|
192
|
+
report.findings.push({ ...finding('validation.identity', 'Page IDs must begin with a letter/digit and contain only letters, digits, dots, underscores or hyphens.', 'Choose a stable ID and update its references.'), file, reference: 'guide.frontmatter-reference' });
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
addError(error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const manifest = await compile(stagedConfig, site, {}, { authoringFiles: new Set(affected.map(file => path.join(shadow, file))) });
|
|
200
|
+
report.dependencies = manifest.dependencies.map(file => isWithin(tree, file) ? path.relative(shadow, file) : file);
|
|
201
|
+
for (const dependency of manifest.dependencies) {
|
|
202
|
+
if (isWithin(tree, dependency)) {
|
|
203
|
+
if (!capture.buffers.has(path.relative(shadow, dependency)))
|
|
204
|
+
throw new SnapshotError('unsupported_dependency', `Compiler dependency was not captured: ${path.relative(shadow, dependency)}`);
|
|
205
|
+
}
|
|
206
|
+
else if (isWithin(framework, dependency) || dependency === iconLicenseFile)
|
|
207
|
+
report.runtimeDependencies.push({ file: dependency, digest: sha256(await readFile(dependency)), mode: (await stat(dependency)).mode & 0o777 });
|
|
208
|
+
else
|
|
209
|
+
throw new SnapshotError('unsupported_dependency', `Compiler attempted to use an uncaptured dependency: ${dependency}`);
|
|
210
|
+
}
|
|
211
|
+
report.coverage.rendered = (manifest.authoringSources ?? []).map(doc => ({ id: doc.id, file: path.relative(shadow, doc.file), route: doc.url, markdown: doc.markdownUrl }));
|
|
212
|
+
report.coverage.notRendered = affected.filter(file => !report.coverage.rendered.some(doc => doc.file === file));
|
|
213
|
+
for (const file of report.coverage.notRendered)
|
|
214
|
+
report.findings.push({ ...finding('validation.excluded-page', 'This affected authored page did not render in any enabled publication.', 'Correct its publication/locale selection or enable an isolated review publication and validate again.'), file });
|
|
215
|
+
report.checks.push({ id: 'compile', status: 'passed', documents: manifest.documents.length });
|
|
216
|
+
const settings = parseAuditSettings(config.audit);
|
|
217
|
+
if (settings.links) {
|
|
218
|
+
const links = await auditLinks(site, config.site?.origin);
|
|
219
|
+
report.checks.push({ id: 'representations-and-links', status: links.status === 'ok' ? 'passed' : 'failed', documents: links.pages, findings: links.findings.length });
|
|
220
|
+
for (const problem of links.findings) {
|
|
221
|
+
const document = report.coverage.rendered.find(doc => doc.route === problem.target || doc.markdown === problem.target);
|
|
222
|
+
report.findings.push({ ...finding('validation.link', problem.message, 'Repair the link/anchor in the authored source and validate again.'), ...(document ? { file: document.file } : {}) });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else
|
|
226
|
+
report.checks.push({ id: 'representations-and-links', status: 'skipped', explanation: 'Disabled by audit.links; compiler document-link validation still ran.' });
|
|
227
|
+
if (settings.focusedContracts) {
|
|
228
|
+
const review = await auditFocusedContracts(site);
|
|
229
|
+
report.checks.push({ id: 'focused-contracts', status: review.status === 'ok' ? 'passed' : 'failed', findings: review.failures.length });
|
|
230
|
+
for (const failure of review.failures)
|
|
231
|
+
report.findings.push(finding('validation.focused-contract', failure.message, 'Repair the API contract/example and validate again.'));
|
|
232
|
+
}
|
|
233
|
+
else
|
|
234
|
+
report.checks.push({ id: 'focused-contracts', status: 'skipped', explanation: 'Disabled by audit.focusedContracts.' });
|
|
235
|
+
if (settings.api) {
|
|
236
|
+
const sources = manifest.dependencies.filter(file => /\.(?:json|ya?ml)$/.test(file) && !loaded.dependencies.includes(file));
|
|
237
|
+
for (const source of sources) {
|
|
238
|
+
// Only OpenAPI documents are passed to the canonical API auditor.
|
|
239
|
+
const raw = await readFile(source, 'utf8');
|
|
240
|
+
if (!/(?:"openapi"\s*:|^openapi\s*:)/m.test(raw))
|
|
241
|
+
continue;
|
|
242
|
+
const review = await auditReference(source);
|
|
243
|
+
report.checks.push({ id: `api:${path.relative(shadow, source)}`, status: review.status === 'ok' ? 'passed' : 'failed', findings: review.failures.length });
|
|
244
|
+
for (const failure of review.failures)
|
|
245
|
+
report.findings.push({ ...finding('validation.api-example', failure.message, 'Repair the API example/contract and validate again.'), file: path.relative(shadow, source) });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else
|
|
249
|
+
report.checks.push({ id: 'api-examples', status: 'skipped', explanation: 'Disabled by audit.api.' });
|
|
250
|
+
for (let index = 0; index < settings.tests.length; index++) {
|
|
251
|
+
const spec = settings.tests[index];
|
|
252
|
+
if (!options.runConfiguredChecks) {
|
|
253
|
+
report.checks.push({ id: `test:${spec.id}`, status: 'skipped', explanation: 'Configured commands require an explicit --run-checks request under harness execution permissions.' });
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const result = await runAuditTest(spec, shadow, {
|
|
257
|
+
SHOALRUN_VALIDATION_SITE: site, SHOALRUN_VALIDATION_SNAPSHOT: snapshotId,
|
|
258
|
+
// CommonJS checks can use the installed tool's dependencies without
|
|
259
|
+
// copying node_modules or resolving against the author's live tree.
|
|
260
|
+
NODE_PATH: checkModulePaths,
|
|
261
|
+
});
|
|
262
|
+
const unavailable = result.findings.some(item => /ENOENT|EACCES|MODULE_NOT_FOUND|ERR_MODULE_NOT_FOUND/.test(item.message));
|
|
263
|
+
report.checks.push({ id: result.id, status: result.status === 'ok' ? 'passed' : unavailable ? 'unavailable' : 'failed' });
|
|
264
|
+
for (const item of result.findings)
|
|
265
|
+
report.findings.push({ ...finding('validation.project-check', item.message.split(shadow + path.sep).join(''), 'Inspect the configured check output, repair actionable errors or make the validator available, then validate again.', unavailable ? 'review-needed' : 'error'), ...configFindingLocation(loaded, ['audit', 'tests', String(index)], capture, shadow) });
|
|
266
|
+
}
|
|
267
|
+
if (settings.evals)
|
|
268
|
+
report.checks.push({ id: 'evals', status: 'skipped', explanation: 'Harness/model evaluations are not executed by the provider-free snapshot validator.' });
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
const unavailable = error instanceof SnapshotError && error.code === 'unsupported_dependency' || /Could not find Chrome|Browser was not found|no executable was found|Failed to launch the browser process|spawn .*ENOENT/.test(error.message);
|
|
272
|
+
report.checks.push({ id: 'compile-and-checks', status: unavailable ? 'unavailable' : 'failed', explanation: error.message.split(shadow + path.sep).join('') });
|
|
273
|
+
const diagnostic = validationFinding(error, capture, shadow, loaded);
|
|
274
|
+
if (unavailable) {
|
|
275
|
+
diagnostic.code = 'validation.validator-unavailable';
|
|
276
|
+
diagnostic.severity = 'review-needed';
|
|
277
|
+
diagnostic.nextAction = 'Make the renderer/dependency available in the captured environment and validate again.';
|
|
278
|
+
}
|
|
279
|
+
report.findings.push(diagnostic);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
await hooks.afterChecks?.();
|
|
283
|
+
// A trusted check may create cache/output in excluded locations, but cannot
|
|
284
|
+
// change or remove any captured input and still receive a passing report.
|
|
285
|
+
const stagedCapture = { root: shadow, inputs: capture.inputs, externalDirectories: capture.externalDirectories };
|
|
286
|
+
if (!await confirmSnapshotInputs(stagedCapture))
|
|
287
|
+
report.findings.push(finding('validation.snapshot-modified', 'A build or configured check changed the captured project inputs.', 'Fix the check so it leaves source inputs unchanged; validate a new snapshot.'));
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
if (error instanceof SnapshotError && error.code === 'stale_input') {
|
|
291
|
+
report.findings.push(finding('validation.stale-input', error.message, 'Retry capture after concurrent edits stop.'));
|
|
292
|
+
report.freshness.current = false;
|
|
293
|
+
}
|
|
294
|
+
else
|
|
295
|
+
addError(error);
|
|
296
|
+
}
|
|
297
|
+
let runtimeDependencyChanged = false;
|
|
298
|
+
for (const dependency of report.runtimeDependencies)
|
|
299
|
+
if (sha256(await readFile(dependency.file).catch(() => Buffer.alloc(0))) !== dependency.digest)
|
|
300
|
+
runtimeDependencyChanged = true;
|
|
301
|
+
if (!await confirmSnapshotInputs(capture) || !await absentInputsUnchanged() || (await validatorInputs()).digest !== runtime.digest || runtimeDependencyChanged || baseline.file && sha256(await readFile(baseline.file).catch(() => Buffer.alloc(0))) !== baseline.digest) {
|
|
302
|
+
report.freshness.current = false;
|
|
303
|
+
report.findings.push(finding('validation.stale-input', 'Working-tree, baseline or validator inputs changed during validation.', 'Validate the current working tree again; this report describes only the captured inputs.'));
|
|
304
|
+
}
|
|
305
|
+
report.freshness.checkedAt = new Date().toISOString();
|
|
306
|
+
report.status = !report.freshness.current ? 'stale' : report.findings.some(item => item.severity === 'error') || report.checks.some(check => check.status === 'failed') ? 'failed' : report.checks.some(check => check.status === 'unavailable') ? 'unavailable' : report.checks.some(check => check.status === 'skipped') ? 'incomplete' : 'ok';
|
|
307
|
+
report.artifacts.digest = await validationArtifactDigest(site);
|
|
308
|
+
await writeFile(report.artifacts.report, JSON.stringify(report, null, 2) + '\n', { flag: 'wx' });
|
|
309
|
+
return report;
|
|
310
|
+
}
|
|
311
|
+
/** Shared reader for retained reports; this never runs project code. */
|
|
312
|
+
export async function readValidationReport(reportFile) {
|
|
313
|
+
const raw = await readFile(reportFile, 'utf8');
|
|
314
|
+
let report;
|
|
315
|
+
try {
|
|
316
|
+
report = JSON.parse(raw);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
throw new SnapshotError('invalid_input', 'Validation report must be valid JSON');
|
|
320
|
+
}
|
|
321
|
+
if (!report || report.schemaVersion !== 1 || report.kind !== 'shoalrun-authoring-validation' || !Array.isArray(report.inputs) || !Array.isArray(report.externalDirectories) || !Array.isArray(report.runtimeDependencies) || !Array.isArray(report.changed) || report.changed.some(item => !item || !modes.has(item.operation)))
|
|
322
|
+
throw new SnapshotError('invalid_input', 'Expected a version-1 authoring validation report');
|
|
323
|
+
if (!report.baseline || !report.coverage || !Array.isArray(report.coverage.rendered) || !Array.isArray(report.coverage.affected) || !Array.isArray(report.coverage.notRendered) || !Array.isArray(report.checks) || !Array.isArray(report.findings) || !report.artifacts || !report.freshness || typeof report.project !== 'string' || !path.isAbsolute(report.project) || typeof report.snapshotId !== 'string' || !/^[a-f0-9]{64}$/.test(report.snapshotId))
|
|
324
|
+
throw new SnapshotError('invalid_input', 'Malformed authoring validation report');
|
|
325
|
+
for (const input of report.inputs)
|
|
326
|
+
relativeInput(report.project, input.file);
|
|
327
|
+
return report;
|
|
328
|
+
}
|
|
329
|
+
/** Refresh applicability without rebuilding, applying or mutating source. */
|
|
330
|
+
export async function authoringValidationStatus(reportFile) {
|
|
331
|
+
const report = await readValidationReport(reportFile);
|
|
332
|
+
let missingInputCreated = false;
|
|
333
|
+
for (const input of report.changed)
|
|
334
|
+
if (input.digest === null && await stat(relativeInput(report.project, input.file)).then(() => true, () => false))
|
|
335
|
+
missingInputCreated = true;
|
|
336
|
+
const changed = missingInputCreated || sha256(JSON.stringify(report.inputs)) !== report.contentDigest || !await confirmSnapshotInputs({ root: report.project, inputs: report.inputs, externalDirectories: report.externalDirectories });
|
|
337
|
+
const runtime = await validatorInputs();
|
|
338
|
+
let baselineChanged = false, dependencyChanged = false;
|
|
339
|
+
if (report.baseline.file)
|
|
340
|
+
baselineChanged = sha256(await readFile(report.baseline.file).catch(() => Buffer.alloc(0))) !== report.baseline.digest;
|
|
341
|
+
for (const dependency of report.runtimeDependencies)
|
|
342
|
+
if (sha256(await readFile(dependency.file).catch(() => Buffer.alloc(0))) !== dependency.digest)
|
|
343
|
+
dependencyChanged = true;
|
|
344
|
+
const artifactChanged = await validationArtifactDigest(report.artifacts.site) !== report.artifacts.digest || !await confirmSnapshotInputs({ root: report.artifacts.project, inputs: report.inputs, externalDirectories: report.externalDirectories });
|
|
345
|
+
const current = report.freshness.current && !changed && !baselineChanged && !dependencyChanged && !artifactChanged && runtime.digest === report.validatorDigest;
|
|
346
|
+
return { schemaVersion: 1, status: current ? report.status : 'stale', snapshotId: report.snapshotId, report: path.resolve(reportFile), current, changed: { source: changed, baseline: baselineChanged, validator: runtime.digest !== report.validatorDigest || dependencyChanged, artifacts: artifactChanged }, nextAction: current ? 'Review the reported coverage and findings.' : 'Run docs validate again for the current working tree; old findings and previews do not verify new edits.' };
|
|
347
|
+
}
|
|
348
|
+
export const validationFailure = (error) => ({ schemaVersion: 1, status: 'error', error: { code: error instanceof SnapshotError ? error.code : 'internal_error', message: error instanceof Error ? error.message : 'Snapshot validation failed' } });
|
package/dist/badges.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Mode, type Palette } from './palettes.js';
|
|
2
|
+
export declare const builtInBadgeVariants: readonly ["neutral", "info", "success", "warning", "new"];
|
|
3
|
+
type BadgeColors = {
|
|
4
|
+
background: string;
|
|
5
|
+
text: string;
|
|
6
|
+
border: string;
|
|
7
|
+
};
|
|
8
|
+
export type BadgeVariant = {
|
|
9
|
+
light?: BadgeColors;
|
|
10
|
+
dark?: BadgeColors;
|
|
11
|
+
};
|
|
12
|
+
export type BadgeVariants = Map<string, BadgeVariant>;
|
|
13
|
+
export declare function resolveBadgeVariants(config: unknown, file: string): BadgeVariants;
|
|
14
|
+
export declare function badgeContrastProblems(variants: BadgeVariants, palette: Palette, modes: Mode[]): string[];
|
|
15
|
+
export declare function badgeCss(variants: BadgeVariants, mode: Mode | 'system'): string | undefined;
|
|
16
|
+
export {};
|
package/dist/badges.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { contrast } from './palettes.js';
|
|
2
|
+
export const builtInBadgeVariants = ['neutral', 'info', 'success', 'warning', 'new'];
|
|
3
|
+
const mapping = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
4
|
+
const namePattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
5
|
+
const hexColor = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
6
|
+
function colors(value, where) {
|
|
7
|
+
if (!mapping(value) || Object.keys(value).some(key => !['background', 'text', 'border'].includes(key)))
|
|
8
|
+
throw new Error(`${where} only accepts background, text, and border`);
|
|
9
|
+
for (const key of ['background', 'text'])
|
|
10
|
+
if (typeof value[key] !== 'string' || !hexColor.test(value[key]))
|
|
11
|
+
throw new Error(`${where}.${key} must be a hex color`);
|
|
12
|
+
if (value.border !== undefined && (typeof value.border !== 'string' || !hexColor.test(value.border)))
|
|
13
|
+
throw new Error(`${where}.border must be a hex color`);
|
|
14
|
+
return { background: value.background, text: value.text, border: (value.border ?? value.text) };
|
|
15
|
+
}
|
|
16
|
+
export function resolveBadgeVariants(config, file) {
|
|
17
|
+
const variants = new Map(builtInBadgeVariants.map(name => [name, {}]));
|
|
18
|
+
if (config === undefined)
|
|
19
|
+
return variants;
|
|
20
|
+
if (!mapping(config) || Object.keys(config).some(key => key !== 'variants') || !mapping(config.variants))
|
|
21
|
+
throw new Error(`${file}: badges must contain a variants mapping`);
|
|
22
|
+
for (const [name, value] of Object.entries(config.variants)) {
|
|
23
|
+
if (!namePattern.test(name))
|
|
24
|
+
throw new Error(`${file}: badges.variants name "${name}" must use lowercase kebab-case`);
|
|
25
|
+
if (!mapping(value) || Object.keys(value).some(key => !['light', 'dark'].includes(key)) || !value.light)
|
|
26
|
+
throw new Error(`${file}: badges.variants.${name} needs light colors and optional dark colors`);
|
|
27
|
+
variants.set(name, { light: colors(value.light, `${file}: badges.variants.${name}.light`), ...(value.dark ? { dark: colors(value.dark, `${file}: badges.variants.${name}.dark`) } : {}) });
|
|
28
|
+
}
|
|
29
|
+
return variants;
|
|
30
|
+
}
|
|
31
|
+
export function badgeContrastProblems(variants, palette, modes) {
|
|
32
|
+
return [...variants].flatMap(([name, variant]) => modes.flatMap(mode => {
|
|
33
|
+
const colors = variant[mode];
|
|
34
|
+
if (!variant.light)
|
|
35
|
+
return [];
|
|
36
|
+
if (!colors)
|
|
37
|
+
return [`badges.variants.${name} needs dark colors because the site shows dark mode`];
|
|
38
|
+
const ratio = contrast(colors.text, colors.background, palette[mode].page);
|
|
39
|
+
return ratio + 1e-9 < 4.5 ? [`badges.variants.${name} ${mode}: text ${colors.text} on background ${colors.background} is ${ratio.toFixed(2)}:1; needs 4.5:1`] : [];
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
export function badgeCss(variants, mode) {
|
|
43
|
+
const custom = [...variants].filter(([, variant]) => variant.light);
|
|
44
|
+
if (!custom.length)
|
|
45
|
+
return undefined;
|
|
46
|
+
const rules = (selected) => custom.map(([name, variant]) => {
|
|
47
|
+
const colors = variant[selected] ?? variant.light;
|
|
48
|
+
return `.content .doc-badge-${name}{background:${colors.background};color:${colors.text};border-color:${colors.border}}`;
|
|
49
|
+
}).join('\n');
|
|
50
|
+
if (mode !== 'system')
|
|
51
|
+
return `${rules(mode)}\n`;
|
|
52
|
+
const darkRules = custom.map(([name, variant]) => {
|
|
53
|
+
const colors = variant.dark;
|
|
54
|
+
return `.content .doc-badge-${name}{background:${colors.background};color:${colors.text};border-color:${colors.border}}`;
|
|
55
|
+
}).join('\n');
|
|
56
|
+
return `${rules('light')}\n@media(prefers-color-scheme:dark){:root:not([data-mode=light]) ${darkRules.replaceAll('\n', '\n:root:not([data-mode=light]) ')}}\n:root[data-mode=dark] ${darkRules.replaceAll('\n', '\n:root[data-mode=dark] ')}\n`;
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BudgetStore } from './budget.js';
|
|
2
|
+
export type RestStoreOptions = {
|
|
3
|
+
url: string;
|
|
4
|
+
token: string;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
fetch?: typeof fetch;
|
|
7
|
+
};
|
|
8
|
+
export declare function envBudgetStore(settings: {
|
|
9
|
+
urlEnv: string;
|
|
10
|
+
tokenEnv: string;
|
|
11
|
+
}, env?: Record<string, string | undefined>, send?: typeof fetch): BudgetStore;
|
|
12
|
+
export type RestRedis = {
|
|
13
|
+
command(args: string[]): Promise<unknown>;
|
|
14
|
+
pipeline(commands: string[][]): Promise<unknown[]>;
|
|
15
|
+
};
|
|
16
|
+
export declare function restRedis(options: RestStoreOptions): RestRedis;
|
|
17
|
+
export declare function envRedis(settings: {
|
|
18
|
+
urlEnv: string;
|
|
19
|
+
tokenEnv: string;
|
|
20
|
+
}, env?: Record<string, string | undefined>, send?: typeof fetch): RestRedis;
|
|
21
|
+
export declare function restBudgetStore(options: RestStoreOptions): BudgetStore;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// A store whose address and token come from named environment variables, read on first use. A missing variable is an error at the first
|
|
2
|
+
// question, which DailyBudget counts as a spent budget. It never falls back to counters that each server instance keeps for itself.
|
|
3
|
+
export function envBudgetStore(settings, env = process.env, send) {
|
|
4
|
+
let built;
|
|
5
|
+
const store = () => {
|
|
6
|
+
if (built)
|
|
7
|
+
return built;
|
|
8
|
+
const url = env[settings.urlEnv];
|
|
9
|
+
const token = env[settings.tokenEnv];
|
|
10
|
+
if (!url)
|
|
11
|
+
throw new Error(`Set ${settings.urlEnv} to use the budget store`);
|
|
12
|
+
if (!token)
|
|
13
|
+
throw new Error(`Set ${settings.tokenEnv} to use the budget store`);
|
|
14
|
+
return built = restBudgetStore({ url, token, ...(send ? { fetch: send } : {}) });
|
|
15
|
+
};
|
|
16
|
+
return { add: async (key, amount, ttl) => store().add(key, amount, ttl), get: async (key) => store().get(key) };
|
|
17
|
+
}
|
|
18
|
+
const local = (host) => /^(localhost|127\.0\.0\.1|\[::1\])$/.test(host);
|
|
19
|
+
export function restRedis(options) {
|
|
20
|
+
let base;
|
|
21
|
+
try {
|
|
22
|
+
base = new URL(options.url);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new Error('The budget store address is not a valid URL');
|
|
26
|
+
}
|
|
27
|
+
if (base.protocol !== 'https:' && !(base.protocol === 'http:' && local(base.hostname)))
|
|
28
|
+
throw new Error('The budget store address must use https, so the token is never sent in the clear');
|
|
29
|
+
if (base.username || base.password || base.search || base.hash)
|
|
30
|
+
throw new Error('The budget store address must not contain credentials or a query');
|
|
31
|
+
const root = base.href.replace(/\/+$/, '');
|
|
32
|
+
const send = options.fetch ?? fetch;
|
|
33
|
+
async function post(path, body) {
|
|
34
|
+
let response;
|
|
35
|
+
try {
|
|
36
|
+
response = await send(`${root}${path}`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${options.token}` }, body: JSON.stringify(body), signal: AbortSignal.timeout(options.timeoutMs ?? 2000) });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`The budget store request failed: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
if (!response.ok)
|
|
42
|
+
throw new Error(`The budget store returned ${response.status}`);
|
|
43
|
+
return response.json();
|
|
44
|
+
}
|
|
45
|
+
const value = (entry) => {
|
|
46
|
+
const item = entry;
|
|
47
|
+
if (!item || typeof item !== 'object' || item.error !== undefined)
|
|
48
|
+
throw new Error('The budget store returned an error');
|
|
49
|
+
return item.result;
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
async command(args) { return value(await post('', args)); },
|
|
53
|
+
async pipeline(commands) {
|
|
54
|
+
const answers = await post('/pipeline', commands);
|
|
55
|
+
if (!Array.isArray(answers) || answers.length !== commands.length)
|
|
56
|
+
throw new Error('The budget store returned an unexpected answer');
|
|
57
|
+
return answers.map(value);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// The same client, with its address and token read from named environment variables on first use.
|
|
62
|
+
export function envRedis(settings, env = process.env, send) {
|
|
63
|
+
let built;
|
|
64
|
+
const client = () => {
|
|
65
|
+
if (built)
|
|
66
|
+
return built;
|
|
67
|
+
const url = env[settings.urlEnv];
|
|
68
|
+
const token = env[settings.tokenEnv];
|
|
69
|
+
if (!url)
|
|
70
|
+
throw new Error(`Set ${settings.urlEnv} to use the budget store`);
|
|
71
|
+
if (!token)
|
|
72
|
+
throw new Error(`Set ${settings.tokenEnv} to use the budget store`);
|
|
73
|
+
return built = restRedis({ url, token, ...(send ? { fetch: send } : {}) });
|
|
74
|
+
};
|
|
75
|
+
return { command: async (args) => client().command(args), pipeline: async (commands) => client().pipeline(commands) };
|
|
76
|
+
}
|
|
77
|
+
export function restBudgetStore(options) {
|
|
78
|
+
const redis = restRedis(options);
|
|
79
|
+
const count = (raw) => {
|
|
80
|
+
const total = raw === null || raw === undefined ? 0 : Number(raw);
|
|
81
|
+
if (!Number.isFinite(total) || total < 0)
|
|
82
|
+
throw new Error('The budget store returned a value that is not a count');
|
|
83
|
+
return total;
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
// INCRBY makes the counter, and EXPIRE with NX gives it a lifetime only the first time, so later questions don't extend it.
|
|
87
|
+
async add(key, amount, ttlSeconds) { return count((await redis.pipeline([['INCRBY', key, String(amount)], ['EXPIRE', key, String(ttlSeconds), 'NX']]))[0]); },
|
|
88
|
+
async get(key) { return count(await redis.command(['GET', key])); }
|
|
89
|
+
};
|
|
90
|
+
}
|