@warpgogol/werkstatt-shared 0.2.0
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/package.json +352 -0
- package/src/checks/index.ts +24 -0
- package/src/checks/lib/astro-site-url.ts +30 -0
- package/src/checks/lib/i18n.ts +30 -0
- package/src/checks/result-helpers.ts +102 -0
- package/src/checks/suppressions-config.ts +195 -0
- package/src/index.ts +14 -0
- package/src/integration/README.md +38 -0
- package/src/integration/adapters.ts +143 -0
- package/src/integration/crm-buffer.ts +491 -0
- package/src/integration/dispatch.ts +106 -0
- package/src/integration/funnel.ts +379 -0
- package/src/integration/index.ts +56 -0
- package/src/integration/lifecycle.ts +155 -0
- package/src/integration/orchestration.ts +439 -0
- package/src/integration/port-barrel.ts +124 -0
- package/src/integration/port.ts +143 -0
- package/src/integration/qstash.ts +134 -0
- package/src/integration/sharding.ts +133 -0
- package/src/integration/tests/deliver-event.test.ts +52 -0
- package/src/integration/tests/dispatch.test.ts +88 -0
- package/src/integration/tests/funnel-bridge.test.ts +46 -0
- package/src/integration/tests/hub-runtime.test.ts +128 -0
- package/src/integration/tests/lifecycle.test.ts +69 -0
- package/src/integration/tests/qstash.test.ts +83 -0
- package/src/integration/tests/sharding.test.ts +64 -0
- package/src/integration/vitest.config.ts +8 -0
- package/src/integration-adapter-supabase-crm/adapter.ts +437 -0
- package/src/integration-adapter-supabase-crm/client.ts +605 -0
- package/src/integration-adapter-supabase-crm/index.ts +28 -0
- package/src/integration-adapter-supabase-crm/pipedrive-sync-target.ts +482 -0
- package/src/integration-adapter-supabase-crm/supabase-rest.ts +89 -0
- package/src/integration-adapter-supabase-crm/tenant-registry.ts +334 -0
- package/src/integration-adapter-supabase-crm/tests/change-balance.pbt.test.ts +83 -0
- package/src/integration-adapter-supabase-crm/tests/funnel-persistence.test.ts +409 -0
- package/src/integration-adapter-supabase-crm/tests/lifecycle-sync.test.ts +288 -0
- package/src/integration-adapter-supabase-crm/tests/stage-map.test.ts +80 -0
- package/src/integration-adapter-supabase-crm/vitest.config.ts +8 -0
- package/src/integration-adapter-supabase-crm/worker.ts +223 -0
- package/src/observability/conventions.ts +93 -0
- package/src/observability/env-resolver.ts +57 -0
- package/src/observability/index.ts +57 -0
- package/src/observability/metric-registry.ts +184 -0
- package/src/observability/otlp-converter.ts +125 -0
- package/src/observability/otlp-json.ts +135 -0
- package/src/observability/otlp-transport.ts +68 -0
- package/src/observability/pusher.ts +142 -0
- package/src/observability/redact.ts +27 -0
- package/src/observability/tests/conventions.test.ts +100 -0
- package/src/observability/tests/metric-registry.test.ts +117 -0
- package/src/observability/tests/otlp-converter.pbt.test.ts +77 -0
- package/src/observability/tests/otlp-converter.test.ts +157 -0
- package/src/observability/tests/otlp-json.test.ts +120 -0
- package/src/observability/tests/pusher.test.ts +75 -0
- package/src/observability/tests/redact.pbt.test.ts +71 -0
- package/src/observability/tests/redact.test.ts +37 -0
- package/src/observability/typed-refs.ts +137 -0
- package/src/observability/vitest.config.ts +8 -0
- package/src/ontology/analytics/matomo-binding.yaml +172 -0
- package/src/ontology/analytics/matomo-fleet.registry.yaml +26 -0
- package/src/ontology/analytics/messkanon.yaml +151 -0
- package/src/ontology/archetype-registry.ts +61 -0
- package/src/ontology/archetypes/components/brand-label.yaml +19 -0
- package/src/ontology/archetypes/components/copyright.yaml +19 -0
- package/src/ontology/archetypes/components/currency-aware-price-display.yaml +19 -0
- package/src/ontology/archetypes/components/currency-selector.yaml +19 -0
- package/src/ontology/archetypes/components/footer-promo.yaml +19 -0
- package/src/ontology/archetypes/components/lang-switcher.yaml +19 -0
- package/src/ontology/archetypes/components/layout.yaml +19 -0
- package/src/ontology/archetypes/components/live-photo.yaml +20 -0
- package/src/ontology/archetypes/components/material-credit.yaml +20 -0
- package/src/ontology/archetypes/components/media.yaml +21 -0
- package/src/ontology/archetypes/components/nachweis-card.yaml +34 -0
- package/src/ontology/archetypes/components/nachweis-detail.yaml +43 -0
- package/src/ontology/archetypes/components/nachweis-list.yaml +37 -0
- package/src/ontology/archetypes/components/nachweis-verify.yaml +31 -0
- package/src/ontology/archetypes/components/not-found.yaml +22 -0
- package/src/ontology/archetypes/components/offer-capacity.yaml +21 -0
- package/src/ontology/archetypes/components/passport-header.yaml +19 -0
- package/src/ontology/archetypes/components/passport-provenance.yaml +20 -0
- package/src/ontology/archetypes/components/passport-score-grid.yaml +20 -0
- package/src/ontology/archetypes/components/passport-star-map.yaml +20 -0
- package/src/ontology/archetypes/components/person-profile.yaml +20 -0
- package/src/ontology/archetypes/components/pulsar.yaml +20 -0
- package/src/ontology/archetypes/components/responsive-image.yaml +19 -0
- package/src/ontology/archetypes/components/scroll-to-top.yaml +22 -0
- package/src/ontology/archetypes/components/social-meta.yaml +20 -0
- package/src/ontology/archetypes/components/structured-data.yaml +19 -0
- package/src/ontology/archetypes/index.json +1003 -0
- package/src/ontology/archetypes/index.yaml +821 -0
- package/src/ontology/archetypes/sections/approach.yaml +23 -0
- package/src/ontology/archetypes/sections/article-list.yaml +30 -0
- package/src/ontology/archetypes/sections/audience-cards.yaml +30 -0
- package/src/ontology/archetypes/sections/breadcrumbs.yaml +21 -0
- package/src/ontology/archetypes/sections/chat-widget.yaml +37 -0
- package/src/ontology/archetypes/sections/comparison-cards.yaml +31 -0
- package/src/ontology/archetypes/sections/controlled-responsibility-block.yaml +34 -0
- package/src/ontology/archetypes/sections/credits.yaml +29 -0
- package/src/ontology/archetypes/sections/donation-card.yaml +53 -0
- package/src/ontology/archetypes/sections/donation-use.yaml +23 -0
- package/src/ontology/archetypes/sections/dynamic-status-block.yaml +35 -0
- package/src/ontology/archetypes/sections/faq-list.yaml +26 -0
- package/src/ontology/archetypes/sections/final-cta.yaml +53 -0
- package/src/ontology/archetypes/sections/hero-decision-card.yaml +65 -0
- package/src/ontology/archetypes/sections/hero.yaml +50 -0
- package/src/ontology/archetypes/sections/impact.yaml +23 -0
- package/src/ontology/archetypes/sections/markdown.yaml +43 -0
- package/src/ontology/archetypes/sections/mountain-journey.yaml +43 -0
- package/src/ontology/archetypes/sections/navigation.yaml +20 -0
- package/src/ontology/archetypes/sections/notausgang-block.yaml +41 -0
- package/src/ontology/archetypes/sections/open-source-registry.yaml +26 -0
- package/src/ontology/archetypes/sections/ownership-block.yaml +57 -0
- package/src/ontology/archetypes/sections/people.yaml +48 -0
- package/src/ontology/archetypes/sections/price-card.yaml +50 -0
- package/src/ontology/archetypes/sections/problem.yaml +23 -0
- package/src/ontology/archetypes/sections/send-message.yaml +63 -0
- package/src/ontology/archetypes/sections/service-metadata-block.yaml +40 -0
- package/src/ontology/archetypes/sections/social-proof.yaml +27 -0
- package/src/ontology/archetypes/sections/transparency.yaml +32 -0
- package/src/ontology/archetypes/sections/trust-strip.yaml +42 -0
- package/src/ontology/archetypes/sections/video-section.yaml +27 -0
- package/src/ontology/archetypes/sections/women.yaml +29 -0
- package/src/ontology/biome-token-projection.ts +229 -0
- package/src/ontology/biomes/check-concrete-blueprint.yaml +118 -0
- package/src/ontology/biomes/handwerk-material-warm.yaml +135 -0
- package/src/ontology/biomes/nonprofit-trust.yaml +123 -0
- package/src/ontology/blueprints/offer.yaml +39 -0
- package/src/ontology/blueprints/prompts/local-market-signal.md +13 -0
- package/src/ontology/blueprints/prompts/website-local-narrative.md +24 -0
- package/src/ontology/blueprints/ratgeber.yaml +62 -0
- package/src/ontology/blueprints/website-local.yaml +309 -0
- package/src/ontology/blueprints/website-service.yaml +84 -0
- package/src/ontology/capabilities/lead.submit.yaml +44 -0
- package/src/ontology/cosmic/index.ts +48 -0
- package/src/ontology/cosmic/moon-catalog.ts +173 -0
- package/src/ontology/cosmic/planet-catalog.ts +82 -0
- package/src/ontology/cosmic/star-catalog.ts +337 -0
- package/src/ontology/enums.ts +159 -0
- package/src/ontology/external-surfaces/index.ts +158 -0
- package/src/ontology/external-surfaces/jsonld-types.yaml +135 -0
- package/src/ontology/external-surfaces/sitemap-shape.yaml +6 -0
- package/src/ontology/external-surfaces/url-schema.yaml +95 -0
- package/src/ontology/growth/events/contact-email-click.yaml +21 -0
- package/src/ontology/growth/events/contact-form-submit.yaml +25 -0
- package/src/ontology/growth/events/contact-phone-click.yaml +21 -0
- package/src/ontology/growth/events/contact-route-click.yaml +21 -0
- package/src/ontology/growth/events/contact-submit.yaml +28 -0
- package/src/ontology/growth/events/contact-whatsapp-click.yaml +21 -0
- package/src/ontology/growth/events/cta-click.yaml +30 -0
- package/src/ontology/growth/events/donation-confirmed.yaml +32 -0
- package/src/ontology/growth/events/donation-form-start.yaml +21 -0
- package/src/ontology/growth/events/donation-form-submit.yaml +29 -0
- package/src/ontology/growth/events/donation-intent.yaml +29 -0
- package/src/ontology/growth/events/form-error.yaml +27 -0
- package/src/ontology/growth/events/form-start.yaml +21 -0
- package/src/ontology/growth/events/form-submit.yaml +21 -0
- package/src/ontology/growth/events/outbound-click.yaml +25 -0
- package/src/ontology/growth/events/page-view.yaml +24 -0
- package/src/ontology/growth/events/passport-view.yaml +28 -0
- package/src/ontology/growth/events/star-map-navigate.yaml +30 -0
- package/src/ontology/index.ts +165 -0
- package/src/ontology/manifest.ts +344 -0
- package/src/ontology/operations/index.ts +1 -0
- package/src/ontology/schemas/biome.ts +303 -0
- package/src/ontology/schemas/capability.ts +104 -0
- package/src/ontology/schemas/constellation.ts +114 -0
- package/src/ontology/schemas/dns-records.ts +53 -0
- package/src/ontology/schemas/index.ts +95 -0
- package/src/ontology/schemas/manifest-resolver.ts +123 -0
- package/src/ontology/schemas/page-entry.ts +213 -0
- package/src/ontology/schemas/section-archetype.ts +109 -0
- package/src/ontology/schemas/site-family.ts +98 -0
- package/src/ontology/schemas/system/growth.ts +80 -0
- package/src/ontology/schemas/system/integrations.ts +143 -0
- package/src/ontology/schemas/system/manifest.ts +492 -0
- package/src/ontology/schemas/system/page-output.ts +99 -0
- package/src/ontology/schemas/system/release.ts +58 -0
- package/src/ontology/schemas/system/text.ts +58 -0
- package/src/ontology/schemas/system.ts +53 -0
- package/src/ontology/shared-section-props/body-fragments.ts +182 -0
- package/src/ontology/shared-section-props/catalog.ts +195 -0
- package/src/ontology/shared-section-props/common.ts +178 -0
- package/src/ontology/shared-section-props/index.ts +34 -0
- package/src/ontology/shared-section-props/visual-header.ts +163 -0
- package/src/ontology/site-families/charity-donation-trust/cultural-rules.yaml +6 -0
- package/src/ontology/site-families/charity-donation-trust/family.yaml +44 -0
- package/src/ontology/site-families/charity-donation-trust/linguistic-rules.yaml +6 -0
- package/src/ontology/site-families/check-quality-operator/cultural-rules.yaml +6 -0
- package/src/ontology/site-families/check-quality-operator/family.yaml +40 -0
- package/src/ontology/site-families/check-quality-operator/linguistic-rules.yaml +6 -0
- package/src/ontology/site-families/handwerk-trust-engineering/cultural-rules.yaml +6 -0
- package/src/ontology/site-families/handwerk-trust-engineering/family.yaml +53 -0
- package/src/ontology/site-families/handwerk-trust-engineering/linguistic-rules.yaml +6 -0
- package/src/ontology/tests/catalogs.pbt.test.ts +89 -0
- package/src/ontology/tests/enums.test.ts +203 -0
- package/src/ontology/tests/sternsystem-owner.test.ts +63 -0
- package/src/ontology/vitest.config.ts +8 -0
- package/src/passport/dht-sign.test.ts +99 -0
- package/src/passport/dht-sign.ts +73 -0
- package/src/passport/identity-sign.test.ts +134 -0
- package/src/passport/identity-sign.ts +85 -0
- package/src/passport/index.ts +53 -0
- package/src/passport/key-rotate.ts +133 -0
- package/src/passport/schema.ts +198 -0
- package/src/passport/sign.ts +225 -0
- package/src/passport/tests/schema.pbt.test.ts +93 -0
- package/src/passport/tests/schema.test.ts +222 -0
- package/src/passport/vitest.config.ts +8 -0
- package/src/share/agent/api-catalog.ts +77 -0
- package/src/share/agent/capability.ts +68 -0
- package/src/share/agent/dns-aid.test.ts +74 -0
- package/src/share/agent/dns-aid.ts +53 -0
- package/src/share/agent/fleet-catalog.ts +149 -0
- package/src/share/agent/index.ts +29 -0
- package/src/share/agent/knowledge.ts +96 -0
- package/src/share/agent/manifest.ts +126 -0
- package/src/share/agent/mcp-card.ts +63 -0
- package/src/share/agent/omit-empty.ts +77 -0
- package/src/share/agent/openapi.ts +157 -0
- package/src/share/agent/proof.ts +61 -0
- package/src/share/attribution-display.ts +86 -0
- package/src/share/check-hints.ts +38 -0
- package/src/share/content/entity-id.ts +65 -0
- package/src/share/content/index.ts +16 -0
- package/src/share/content/merge.ts +86 -0
- package/src/share/content/resolve-field-path.ts +39 -0
- package/src/share/content/substitute-deep.ts +47 -0
- package/src/share/content-discipline/index.ts +14 -0
- package/src/share/content-discipline/parsers.ts +66 -0
- package/src/share/content-discipline/types.ts +118 -0
- package/src/share/content-reference.ts +333 -0
- package/src/share/counter-utils.ts +75 -0
- package/src/share/css-value-normalize.ts +48 -0
- package/src/share/dev-props-validator.ts +131 -0
- package/src/share/entitlement.ts +172 -0
- package/src/share/env.d.ts +73 -0
- package/src/share/feature-policy.ts +367 -0
- package/src/share/formula-eval.ts +364 -0
- package/src/share/fs/index.ts +96 -0
- package/src/share/i18n/localization.ts +57 -0
- package/src/share/image-provider.ts +314 -0
- package/src/share/index.ts +86 -0
- package/src/share/knowledge/claim.ts +129 -0
- package/src/share/knowledge/derivation.ts +55 -0
- package/src/share/knowledge/freshness.ts +127 -0
- package/src/share/knowledge/index.ts +23 -0
- package/src/share/knowledge/ledger.ts +222 -0
- package/src/share/knowledge/plan.ts +122 -0
- package/src/share/knowledge/source.ts +170 -0
- package/src/share/legal/translation-policy.ts +133 -0
- package/src/share/material-credits.ts +181 -0
- package/src/share/middleware/language-redirect.ts +49 -0
- package/src/share/offer-capacity.ts +149 -0
- package/src/share/onboarding-yaml/index.ts +162 -0
- package/src/share/page.ts +351 -0
- package/src/share/redirects.test.ts +62 -0
- package/src/share/redirects.ts +54 -0
- package/src/share/rfc0042-utils.ts +95 -0
- package/src/share/runtime-context.ts +70 -0
- package/src/share/schemas/claim-records.ts +69 -0
- package/src/share/schemas/claims.ts +150 -0
- package/src/share/schemas/effects.ts +212 -0
- package/src/share/schemas/features.ts +147 -0
- package/src/share/schemas/horizontal-align.ts +22 -0
- package/src/share/schemas/icon-color.ts +27 -0
- package/src/share/schemas/index.ts +43 -0
- package/src/share/schemas/live-photo.ts +53 -0
- package/src/share/schemas/material-credit.ts +292 -0
- package/src/share/schemas/media.ts +220 -0
- package/src/share/schemas/navigation.ts +74 -0
- package/src/share/schemas/page-base.ts +33 -0
- package/src/share/schemas/participant.ts +247 -0
- package/src/share/schemas/person.ts +24 -0
- package/src/share/schemas/print.ts +93 -0
- package/src/share/schemas/section-background.ts +106 -0
- package/src/share/schemas/section-body.ts +138 -0
- package/src/share/schemas/section-cards.ts +37 -0
- package/src/share/schemas/section-cta.ts +74 -0
- package/src/share/schemas/section-header.ts +77 -0
- package/src/share/schemas/section-image.ts +77 -0
- package/src/share/schemas/section-motion.ts +52 -0
- package/src/share/schemas/section-shell.ts +63 -0
- package/src/share/schemas/section-stats.ts +37 -0
- package/src/share/schemas/site-background.ts +78 -0
- package/src/share/schemas/standard-list-item.ts +38 -0
- package/src/share/scripts/external-links.ts +45 -0
- package/src/share/scripts/gsap-counter.ts +168 -0
- package/src/share/scripts/gsap-mountain-journey.ts +236 -0
- package/src/share/scripts/gsap-parallax.ts +50 -0
- package/src/share/scripts/gsap-reveal.ts +65 -0
- package/src/share/scripts/gsap-stagger.ts +54 -0
- package/src/share/scripts/index.ts +25 -0
- package/src/share/scripts/inline-number-animation.ts +120 -0
- package/src/share/scripts/lenis.ts +109 -0
- package/src/share/scripts/live-photos.ts +250 -0
- package/src/share/scripts/lordicon.ts +94 -0
- package/src/share/scripts/orchestrator.ts +138 -0
- package/src/share/scripts/scheduler.ts +53 -0
- package/src/share/scripts/video-player.ts +116 -0
- package/src/share/semantic/ai.ts +140 -0
- package/src/share/semantic/block-extraction.ts +52 -0
- package/src/share/semantic/block-extractors/index.ts +502 -0
- package/src/share/semantic/breadcrumbs.ts +120 -0
- package/src/share/semantic/build-page.ts +309 -0
- package/src/share/semantic/business-projection.ts +278 -0
- package/src/share/semantic/derived-prices-loader.ts +36 -0
- package/src/share/semantic/extract.ts +118 -0
- package/src/share/semantic/feed.ts +124 -0
- package/src/share/semantic/ids.ts +76 -0
- package/src/share/semantic/image-sitemap.ts +153 -0
- package/src/share/semantic/index.ts +36 -0
- package/src/share/semantic/jsonld/article.ts +47 -0
- package/src/share/semantic/jsonld/breadcrumb.ts +47 -0
- package/src/share/semantic/jsonld/collection-list.ts +30 -0
- package/src/share/semantic/jsonld/context.ts +46 -0
- package/src/share/semantic/jsonld/faq.ts +49 -0
- package/src/share/semantic/jsonld/initiative.ts +53 -0
- package/src/share/semantic/jsonld/organization.ts +101 -0
- package/src/share/semantic/jsonld/person.ts +71 -0
- package/src/share/semantic/jsonld/service.ts +80 -0
- package/src/share/semantic/jsonld/shared.ts +31 -0
- package/src/share/semantic/jsonld/types.ts +18 -0
- package/src/share/semantic/jsonld/webpage.ts +98 -0
- package/src/share/semantic/jsonld/website.ts +27 -0
- package/src/share/semantic/jsonld.ts +75 -0
- package/src/share/semantic/llms-policy.ts +74 -0
- package/src/share/semantic/llms.ts +394 -0
- package/src/share/semantic/markdown-hygiene.ts +68 -0
- package/src/share/semantic/markdown-twin-provenance.ts +242 -0
- package/src/share/semantic/models.ts +402 -0
- package/src/share/semantic/organization-profile.ts +160 -0
- package/src/share/semantic/output-projection.ts +131 -0
- package/src/share/semantic/page-builders/markdown-page.ts +84 -0
- package/src/share/semantic/page-markdown.ts +234 -0
- package/src/share/semantic/page-utils.ts +125 -0
- package/src/share/semantic/price-marker-resolver.ts +92 -0
- package/src/share/semantic/robots.ts +127 -0
- package/src/share/semantic/update-stamp.ts +136 -0
- package/src/share/shared-context.ts +177 -0
- package/src/share/string-utils.ts +19 -0
- package/src/share/tests/api-catalog.test.ts +97 -0
- package/src/share/tests/breadcrumbs.test.ts +126 -0
- package/src/share/tests/build-page-price-markers.test.ts +160 -0
- package/src/share/tests/capability.test.ts +107 -0
- package/src/share/tests/claim.test.ts +90 -0
- package/src/share/tests/content-ref-index.test.ts +328 -0
- package/src/share/tests/create-dev-props-validator.test.ts +38 -0
- package/src/share/tests/derivation.test.ts +39 -0
- package/src/share/tests/dev-props-validator.test.ts +88 -0
- package/src/share/tests/fleet-catalog.test.ts +134 -0
- package/src/share/tests/formula-eval.test.ts +619 -0
- package/src/share/tests/freshness.test.ts +60 -0
- package/src/share/tests/hero-section-numbering-parity.test.ts +51 -0
- package/src/share/tests/image-sitemap.test.ts +101 -0
- package/src/share/tests/jsonld-service.test.ts +282 -0
- package/src/share/tests/knowledge.test.ts +86 -0
- package/src/share/tests/ledger.test.ts +125 -0
- package/src/share/tests/llms-0789.test.ts +63 -0
- package/src/share/tests/manifest.test.ts +100 -0
- package/src/share/tests/markdown-twin-provenance.test.ts +108 -0
- package/src/share/tests/mcp-card.test.ts +57 -0
- package/src/share/tests/onboarding-yaml.test.ts +111 -0
- package/src/share/tests/ontology-role-by-cosmic-name.test.ts +28 -0
- package/src/share/tests/openapi.test.ts +116 -0
- package/src/share/tests/organization-jsonld.test.ts +74 -0
- package/src/share/tests/output-projection.test.ts +61 -0
- package/src/share/tests/plan.test.ts +97 -0
- package/src/share/tests/price-marker-resolver.test.ts +141 -0
- package/src/share/tests/proof.test.ts +72 -0
- package/src/share/tests/resolve-field-path.test.ts +52 -0
- package/src/share/tests/source.test.ts +81 -0
- package/src/share/tests/substitute-deep.test.ts +65 -0
- package/src/share/tests/text-normalize.pbt.test.ts +143 -0
- package/src/share/tests/text-normalize.test.ts +285 -0
- package/src/share/tests/twin-path.test.ts +43 -0
- package/src/share/text-normalize.ts +548 -0
- package/src/share/text-position.ts +19 -0
- package/src/share/types/hls-js-light.d.ts +16 -0
- package/src/share/visibility.ts +167 -0
- package/src/share/vitest.config.ts +8 -0
- package/src/share/wrap-inline-numbers.ts +139 -0
- package/src/surface/blueprint-schema.ts +314 -0
- package/src/surface/blueprint-types.ts +256 -0
- package/src/surface/blueprint.ts +300 -0
- package/src/surface/breaker.ts +57 -0
- package/src/surface/decision-composer.ts +156 -0
- package/src/surface/eligibility.ts +372 -0
- package/src/surface/evidence-records.ts +97 -0
- package/src/surface/fleet.ts +60 -0
- package/src/surface/geo.ts +170 -0
- package/src/surface/governance.ts +146 -0
- package/src/surface/index.ts +216 -0
- package/src/surface/io/index.ts +18 -0
- package/src/surface/io/surface-module-context-io.ts +60 -0
- package/src/surface/io/visibility-outcomes-io.ts +46 -0
- package/src/surface/module-context.ts +120 -0
- package/src/surface/substance.ts +161 -0
- package/src/surface/tests/eligibility.pbt.test.ts +137 -0
- package/src/surface/tests/eligibility.test.ts +302 -0
- package/src/surface/types.ts +289 -0
- package/src/surface/visibility.ts +57 -0
- package/src/surface/vitest.config.ts +8 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>RFC-0789: tests for conditional agent discovery links in buildLlmsIndex.</purpose>
|
|
4
|
+
<keywords>RFC-0789, llms.txt, agent surface, discovery links, test</keywords>
|
|
5
|
+
</MODULE_CONTRACT>
|
|
6
|
+
<MODULE_MAP>
|
|
7
|
+
<entry key="tests">agent absent (default enabled), agent.enabled true, agent.enabled false, absolute URLs.</entry>
|
|
8
|
+
</MODULE_MAP>
|
|
9
|
+
<CHANGE_SUMMARY>
|
|
10
|
+
<item>RFC-0789: initial tests for conditional agent discovery links in buildLlmsIndex.</item>
|
|
11
|
+
</CHANGE_SUMMARY>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { test, expect } from "vitest";
|
|
15
|
+
import { buildLlmsIndex } from "../semantic/llms.ts";
|
|
16
|
+
import type { SemanticSiteModel } from "../semantic/models.ts";
|
|
17
|
+
|
|
18
|
+
function makeSite(overrides: Partial<SemanticSiteModel> = {}): SemanticSiteModel {
|
|
19
|
+
return {
|
|
20
|
+
baseUrl: "https://example.com",
|
|
21
|
+
lang: "de",
|
|
22
|
+
organization: {
|
|
23
|
+
name: "Test Org",
|
|
24
|
+
description: "A test organization.",
|
|
25
|
+
url: "https://example.com",
|
|
26
|
+
},
|
|
27
|
+
pages: [],
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
test("buildLlmsIndex: agent absent → all 4 agent discovery links present", () => {
|
|
33
|
+
const output = buildLlmsIndex(makeSite());
|
|
34
|
+
expect(output).toContain("agent.json");
|
|
35
|
+
expect(output).toContain("api-catalog");
|
|
36
|
+
expect(output).toContain("mcp/server-card.json");
|
|
37
|
+
expect(output).toContain("agent.openapi.json");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("buildLlmsIndex: agent.enabled true → all 4 agent discovery links present", () => {
|
|
41
|
+
const output = buildLlmsIndex(makeSite({ agent: { enabled: true } }));
|
|
42
|
+
expect(output).toContain("agent.json");
|
|
43
|
+
expect(output).toContain("api-catalog");
|
|
44
|
+
expect(output).toContain("mcp/server-card.json");
|
|
45
|
+
expect(output).toContain("agent.openapi.json");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("buildLlmsIndex: agent.enabled false → zero agent discovery links", () => {
|
|
49
|
+
const output = buildLlmsIndex(makeSite({ agent: { enabled: false } }));
|
|
50
|
+
expect(output).not.toContain("agent.json");
|
|
51
|
+
expect(output).not.toContain("api-catalog");
|
|
52
|
+
expect(output).not.toContain("server-card.json");
|
|
53
|
+
expect(output).not.toContain("agent.openapi.json");
|
|
54
|
+
expect(output).toContain("llms-full.txt");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("buildLlmsIndex: agent links use absolute https URLs", () => {
|
|
58
|
+
const output = buildLlmsIndex(makeSite());
|
|
59
|
+
expect(output).toContain("https://example.com/.well-known/agent.json");
|
|
60
|
+
expect(output).toContain("https://example.com/.well-known/api-catalog");
|
|
61
|
+
expect(output).toContain("https://example.com/.well-known/mcp/server-card.json");
|
|
62
|
+
expect(output).toContain("https://example.com/.well-known/agent.openapi.json");
|
|
63
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>RFC-0286: determinism + shape tests for the Agent Surface Manifest builder.</purpose>
|
|
4
|
+
<keywords>RFC-0286, agent surface, manifest, test</keywords>
|
|
5
|
+
</MODULE_CONTRACT>
|
|
6
|
+
<MODULE_MAP>
|
|
7
|
+
<entry key="tests">determinism, sorting, hash stability, empty-input safe default.</entry>
|
|
8
|
+
</MODULE_MAP>
|
|
9
|
+
<CHANGE_SUMMARY>
|
|
10
|
+
<item>RFC-0286: initial builder tests.</item>
|
|
11
|
+
</CHANGE_SUMMARY>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { test, expect } from "vitest";
|
|
15
|
+
import {
|
|
16
|
+
AGENT_SURFACE_VERSION,
|
|
17
|
+
buildAgentSurfaceManifest,
|
|
18
|
+
computeAgentManifestContentHash,
|
|
19
|
+
canonicalJson,
|
|
20
|
+
} from "../agent/manifest.ts";
|
|
21
|
+
|
|
22
|
+
const baseInput = {
|
|
23
|
+
site: "warpgogol-com",
|
|
24
|
+
baseUrl: "https://warpgogol.com/",
|
|
25
|
+
languages: { default: "de", supported: ["uk", "de"] },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
test("buildAgentSurfaceManifest: strips trailing slash and sorts supported languages", () => {
|
|
29
|
+
const m = buildAgentSurfaceManifest(baseInput);
|
|
30
|
+
expect(m.baseUrl).toBe("https://warpgogol.com");
|
|
31
|
+
expect(m.languages.supported).toEqual(["de", "uk"]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("buildAgentSurfaceManifest: safe default — empty knowledge/actions, null interfaces", () => {
|
|
35
|
+
const m = buildAgentSurfaceManifest(baseInput);
|
|
36
|
+
expect(m.knowledge).toEqual([]);
|
|
37
|
+
expect(m.actions).toEqual([]);
|
|
38
|
+
expect(m.interfaces.openapi).toBe(null);
|
|
39
|
+
expect(m.interfaces.mcp).toBe(null);
|
|
40
|
+
expect(m.interfaces.twins).toBe(null);
|
|
41
|
+
expect(m.proof).toBe(null);
|
|
42
|
+
expect(m.surfaceVersion).toBe(AGENT_SURFACE_VERSION);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("buildAgentSurfaceManifest: is deterministic across repeated calls (byte-identical)", () => {
|
|
46
|
+
const a = buildAgentSurfaceManifest(baseInput);
|
|
47
|
+
const b = buildAgentSurfaceManifest(baseInput);
|
|
48
|
+
expect(JSON.stringify(a)).toBe(JSON.stringify(b));
|
|
49
|
+
expect(a.contentHash).toBe(b.contentHash);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("buildAgentSurfaceManifest: sorts knowledge refs by domain and actions by id", () => {
|
|
53
|
+
const m = buildAgentSurfaceManifest({
|
|
54
|
+
...baseInput,
|
|
55
|
+
knowledge: [
|
|
56
|
+
{ domain: "offer", url: "/api/agent/v1/offer.json", schema: "gogol.agent.knowledge/offer@1" },
|
|
57
|
+
{
|
|
58
|
+
domain: "company",
|
|
59
|
+
url: "/api/agent/v1/company.json",
|
|
60
|
+
schema: "gogol.agent.knowledge/company@1",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
actions: [
|
|
64
|
+
{
|
|
65
|
+
id: "lead.submit",
|
|
66
|
+
url: "/api/agent/actions/lead.submit",
|
|
67
|
+
title: { de: "Anfrage senden" },
|
|
68
|
+
inputSchemaRef: "#/components/schemas/lead.submit-input",
|
|
69
|
+
entitlement: "agent.actions",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "appointment.request",
|
|
73
|
+
url: "/api/agent/actions/appointment.request",
|
|
74
|
+
title: { de: "Termin anfragen" },
|
|
75
|
+
inputSchemaRef: "#/components/schemas/appointment.request-input",
|
|
76
|
+
entitlement: "agent.actions",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
expect(m.knowledge.map((k) => k.domain)).toEqual(["company", "offer"]);
|
|
81
|
+
expect(m.actions.map((a) => a.id)).toEqual(["appointment.request", "lead.submit"]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("computeAgentManifestContentHash: excludes contentHash and proof fields from the hash input", () => {
|
|
85
|
+
const doc: Record<string, unknown> = { a: 1, b: 2, contentHash: "whatever", proof: { x: 1 } };
|
|
86
|
+
const withoutHashFields = { a: 1, b: 2 };
|
|
87
|
+
expect(computeAgentManifestContentHash(doc)).toBe(
|
|
88
|
+
computeAgentManifestContentHash({ ...withoutHashFields, contentHash: "other", proof: null }),
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("computeAgentManifestContentHash: is a 64-char lowercase hex sha256 digest", () => {
|
|
93
|
+
const hash = computeAgentManifestContentHash({ a: 1 });
|
|
94
|
+
expect(hash).toMatch(/^[0-9a-f]{64}$/);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("canonicalJson: sorts object keys deeply, preserves array order", () => {
|
|
98
|
+
expect(canonicalJson({ b: 1, a: { d: 2, c: 3 } })).toBe('{"a":{"c":3,"d":2},"b":1}');
|
|
99
|
+
expect(canonicalJson([3, 1, 2])).toBe("[3,1,2]");
|
|
100
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>
|
|
4
|
+
RFC-0613: Regression tests for parseMarkdownTwinFrontmatter null handling
|
|
5
|
+
and buildMarkdownTwinFrontmatter null serialization.
|
|
6
|
+
</purpose>
|
|
7
|
+
<keywords>RFC-0613, RFC-0602, markdown twin, provenance, null parsing, lastModified</keywords>
|
|
8
|
+
<responsibilities>
|
|
9
|
+
<item>Verify bare YAML null is parsed as JS null for lastModified.</item>
|
|
10
|
+
<item>Verify quoted "null" is also parsed as JS null (parser strips quotes before null check).</item>
|
|
11
|
+
<item>Verify valid date strings are parsed as strings.</item>
|
|
12
|
+
<item>Verify buildMarkdownTwinFrontmatter serializes null as bare YAML null.</item>
|
|
13
|
+
<item>Verify buildMarkdownTwinFrontmatter serializes date strings as quoted YAML.</item>
|
|
14
|
+
</responsibilities>
|
|
15
|
+
<non-goals>
|
|
16
|
+
<item>Do not test page.markdown.validate — that is covered in site-kernel-checks tests.</item>
|
|
17
|
+
</non-goals>
|
|
18
|
+
</MODULE_CONTRACT>
|
|
19
|
+
<MODULE_MAP>
|
|
20
|
+
<entry key="tests">Vitest cases for parseMarkdownTwinFrontmatter and buildMarkdownTwinFrontmatter null handling.</entry>
|
|
21
|
+
</MODULE_MAP>
|
|
22
|
+
<CHANGE_SUMMARY>
|
|
23
|
+
<item>RFC-0613: Added regression tests for null parsing and serialization in markdown twin provenance.</item>
|
|
24
|
+
</CHANGE_SUMMARY>
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { describe, it, expect } from "vitest";
|
|
28
|
+
import {
|
|
29
|
+
parseMarkdownTwinFrontmatter,
|
|
30
|
+
buildMarkdownTwinFrontmatter,
|
|
31
|
+
type MarkdownTwinProvenance,
|
|
32
|
+
} from "../semantic/markdown-twin-provenance.ts";
|
|
33
|
+
|
|
34
|
+
const baseProvenance: MarkdownTwinProvenance = {
|
|
35
|
+
canonical: "https://example.com/page/",
|
|
36
|
+
language: "de",
|
|
37
|
+
lastModified: null,
|
|
38
|
+
license: "https://example.com/ai.txt",
|
|
39
|
+
generator: "test-generator",
|
|
40
|
+
sourceKind: "test",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
describe("parseMarkdownTwinFrontmatter — null handling (RFC-0613)", () => {
|
|
44
|
+
it("parses bare YAML null as JS null for lastModified", () => {
|
|
45
|
+
const content = `---\nlastModified: null\ncanonical: "https://example.com/"\n---\n\nbody`;
|
|
46
|
+
const parsed = parseMarkdownTwinFrontmatter(content);
|
|
47
|
+
expect(parsed).not.toBeNull();
|
|
48
|
+
expect(parsed!.frontmatter.lastModified).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('parses quoted YAML "null" as JS null (parser strips quotes before null check)', () => {
|
|
52
|
+
const content = `---\nlastModified: "null"\ncanonical: "https://example.com/"\n---\n\nbody`;
|
|
53
|
+
const parsed = parseMarkdownTwinFrontmatter(content);
|
|
54
|
+
expect(parsed).not.toBeNull();
|
|
55
|
+
expect(parsed!.frontmatter.lastModified).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("parses valid date string as string", () => {
|
|
59
|
+
const content = `---\nlastModified: "2026-07-30"\ncanonical: "https://example.com/"\n---\n\nbody`;
|
|
60
|
+
const parsed = parseMarkdownTwinFrontmatter(content);
|
|
61
|
+
expect(parsed).not.toBeNull();
|
|
62
|
+
expect(parsed!.frontmatter.lastModified).toBe("2026-07-30");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("parses invalid date string as string (not null)", () => {
|
|
66
|
+
const content = `---\nlastModified: "2026-7-4"\ncanonical: "https://example.com/"\n---\n\nbody`;
|
|
67
|
+
const parsed = parseMarkdownTwinFrontmatter(content);
|
|
68
|
+
expect(parsed).not.toBeNull();
|
|
69
|
+
expect(parsed!.frontmatter.lastModified).toBe("2026-7-4");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("buildMarkdownTwinFrontmatter — null serialization (RFC-0613)", () => {
|
|
74
|
+
it("serializes null lastModified as bare YAML null", () => {
|
|
75
|
+
const provenance: MarkdownTwinProvenance = { ...baseProvenance, lastModified: null };
|
|
76
|
+
const fm = buildMarkdownTwinFrontmatter(provenance, "sha256:abc");
|
|
77
|
+
expect(fm).toContain("lastModified: null");
|
|
78
|
+
expect(fm).not.toContain('lastModified: "null"');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("serializes date string lastModified as quoted YAML", () => {
|
|
82
|
+
const provenance: MarkdownTwinProvenance = { ...baseProvenance, lastModified: "2026-07-30" };
|
|
83
|
+
const fm = buildMarkdownTwinFrontmatter(provenance, "sha256:abc");
|
|
84
|
+
expect(fm).toContain('lastModified: "2026-07-30"');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("round-trip: build → parse (RFC-0613)", () => {
|
|
89
|
+
it("null lastModified survives build → parse round-trip as JS null", () => {
|
|
90
|
+
const provenance: MarkdownTwinProvenance = { ...baseProvenance, lastModified: null };
|
|
91
|
+
const fm = buildMarkdownTwinFrontmatter(provenance, "sha256:abc");
|
|
92
|
+
const parsed = parseMarkdownTwinFrontmatter(
|
|
93
|
+
`${fm}## Summary\n\nTest.\n\n## Business context\n\nTest.`,
|
|
94
|
+
);
|
|
95
|
+
expect(parsed).not.toBeNull();
|
|
96
|
+
expect(parsed!.frontmatter.lastModified).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("date string lastModified survives build → parse round-trip as string", () => {
|
|
100
|
+
const provenance: MarkdownTwinProvenance = { ...baseProvenance, lastModified: "2026-07-30" };
|
|
101
|
+
const fm = buildMarkdownTwinFrontmatter(provenance, "sha256:abc");
|
|
102
|
+
const parsed = parseMarkdownTwinFrontmatter(
|
|
103
|
+
`${fm}## Summary\n\nTest.\n\n## Business context\n\nTest.`,
|
|
104
|
+
);
|
|
105
|
+
expect(parsed).not.toBeNull();
|
|
106
|
+
expect(parsed!.frontmatter.lastModified).toBe("2026-07-30");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>RFC-0783: determinism + shape tests for the MCP Server Card projection.</purpose>
|
|
4
|
+
<keywords>RFC-0783, agent surface, MCP Server Card, test</keywords>
|
|
5
|
+
</MODULE_CONTRACT>
|
|
6
|
+
<MODULE_MAP>
|
|
7
|
+
<entry key="tests">null mcp, mcp card fields, determinism.</entry>
|
|
8
|
+
</MODULE_MAP>
|
|
9
|
+
<CHANGE_SUMMARY>
|
|
10
|
+
<item>RFC-0783: initial MCP Server Card projection tests.</item>
|
|
11
|
+
</CHANGE_SUMMARY>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { test, expect } from "vitest";
|
|
15
|
+
import { buildMcpServerCard } from "../agent/mcp-card.ts";
|
|
16
|
+
import { buildAgentSurfaceManifest } from "../agent/manifest.ts";
|
|
17
|
+
|
|
18
|
+
test("buildMcpServerCard: null mcp → returns null", () => {
|
|
19
|
+
const manifest = buildAgentSurfaceManifest({
|
|
20
|
+
site: "s",
|
|
21
|
+
baseUrl: "https://s.example",
|
|
22
|
+
languages: { default: "de", supported: ["de"] },
|
|
23
|
+
});
|
|
24
|
+
expect(buildMcpServerCard(manifest)).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("buildMcpServerCard: mcp interface → card with correct fields", () => {
|
|
28
|
+
const manifest = buildAgentSurfaceManifest({
|
|
29
|
+
site: "warpgogol",
|
|
30
|
+
baseUrl: "https://warpgogol.com",
|
|
31
|
+
languages: { default: "de", supported: ["de"] },
|
|
32
|
+
mcp: { url: "/api/agent/mcp", protocolVersion: "2025-06-18" },
|
|
33
|
+
});
|
|
34
|
+
const card = buildMcpServerCard(manifest);
|
|
35
|
+
expect(card).not.toBeNull();
|
|
36
|
+
expect(card!.serverInfo.name).toBe("warpgogol-agent-gate");
|
|
37
|
+
expect(card!.serverInfo.version).toBe(manifest.surfaceVersion);
|
|
38
|
+
expect(card!.transport.type).toBe("streamable-http");
|
|
39
|
+
expect(card!.transport.url).toBe("/api/agent/mcp");
|
|
40
|
+
expect(card!.protocolVersion).toBe("2025-06-18");
|
|
41
|
+
expect(card!.capabilities.tools.listChanged).toBe(false);
|
|
42
|
+
expect(card!.capabilities.resources.listChanged).toBe(false);
|
|
43
|
+
expect(card!.capabilities.resources.subscribe).toBe(false);
|
|
44
|
+
expect(card!.capabilities.prompts.listChanged).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("buildMcpServerCard: determinism — same input produces identical output", () => {
|
|
48
|
+
const input = {
|
|
49
|
+
site: "s",
|
|
50
|
+
baseUrl: "https://s.example",
|
|
51
|
+
languages: { default: "de", supported: ["de"] },
|
|
52
|
+
mcp: { url: "/api/agent/mcp", protocolVersion: "2025-06-18" },
|
|
53
|
+
};
|
|
54
|
+
const a = buildMcpServerCard(buildAgentSurfaceManifest(input));
|
|
55
|
+
const b = buildMcpServerCard(buildAgentSurfaceManifest(input));
|
|
56
|
+
expect(JSON.stringify(a)).toBe(JSON.stringify(b));
|
|
57
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>
|
|
4
|
+
RFC-0082 regression tests for parseOnboardingArtifactHeader and
|
|
5
|
+
parseOnboardingArtifactPayload across the five contract shapes:
|
|
6
|
+
single-doc file, two-doc file, missing-header file, empty file,
|
|
7
|
+
doc-count > 2.
|
|
8
|
+
</purpose>
|
|
9
|
+
<responsibilities>
|
|
10
|
+
<item>Pin the "first doc is header, last doc is payload" rule.</item>
|
|
11
|
+
<item>Pin that single-doc payloads keep schema-declared keys (e.g. generatedAt) even when those overlap with RFC-0076 metadata.</item>
|
|
12
|
+
<item>Pin the > 2 docs rejection.</item>
|
|
13
|
+
</responsibilities>
|
|
14
|
+
<non-goals>
|
|
15
|
+
<item>Do not test specific content-discipline schemas — they own their own validation.</item>
|
|
16
|
+
</non-goals>
|
|
17
|
+
</MODULE_CONTRACT>
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { test, expect } from "vitest";
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import {
|
|
23
|
+
parseOnboardingArtifactHeader,
|
|
24
|
+
parseOnboardingArtifactPayload,
|
|
25
|
+
RFC_METADATA_KEYS,
|
|
26
|
+
} from "../onboarding-yaml/index.ts";
|
|
27
|
+
|
|
28
|
+
const HEADER_FIXTURE = `phase: 04-author
|
|
29
|
+
derivedFromInputHash: sha256:deadbeef
|
|
30
|
+
generatedAt: 2026-05-23T12:00:00.000Z
|
|
31
|
+
generator: agent`;
|
|
32
|
+
|
|
33
|
+
test("parseOnboardingArtifactHeader returns the metadata in a two-doc file", () => {
|
|
34
|
+
const source = `---\n${HEADER_FIXTURE}\n---\nclient: warpgogol-com\npayload: 42\n`;
|
|
35
|
+
const header = parseOnboardingArtifactHeader(source);
|
|
36
|
+
expect(header).toEqual({
|
|
37
|
+
phase: "04-author",
|
|
38
|
+
derivedFromInputHash: "sha256:deadbeef",
|
|
39
|
+
generatedAt: "2026-05-23T12:00:00.000Z",
|
|
40
|
+
generator: "agent",
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("parseOnboardingArtifactHeader reads the merged metadata in a single-doc file", () => {
|
|
45
|
+
const source = `${HEADER_FIXTURE}\nclient: warpgogol-com\npayload: 42\n`;
|
|
46
|
+
const header = parseOnboardingArtifactHeader(source);
|
|
47
|
+
expect(header?.phase).toBe("04-author");
|
|
48
|
+
expect(header?.derivedFromInputHash).toBe("sha256:deadbeef");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("parseOnboardingArtifactHeader returns null when the header is missing", () => {
|
|
52
|
+
const source = "client: warpgogol-com\nfoo: bar\n";
|
|
53
|
+
expect(parseOnboardingArtifactHeader(source)).toBe(null);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("parseOnboardingArtifactHeader returns null for an empty source", () => {
|
|
57
|
+
expect(parseOnboardingArtifactHeader("")).toBe(null);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("parseOnboardingArtifactPayload returns the second doc unchanged in a two-doc file", () => {
|
|
61
|
+
const source = `---\n${HEADER_FIXTURE}\n---\nclient: warpgogol-com\npayload: 42\n`;
|
|
62
|
+
const schema = z.object({ client: z.string(), payload: z.number() }).strict();
|
|
63
|
+
const data = parseOnboardingArtifactPayload(source, schema);
|
|
64
|
+
expect(data).toEqual({ client: "warpgogol-com", payload: 42 });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("parseOnboardingArtifactPayload strips RFC-0076 keys from a single-doc payload", () => {
|
|
68
|
+
const source = `${HEADER_FIXTURE}\nclient: warpgogol-com\npayload: 42\n`;
|
|
69
|
+
const schema = z.object({ client: z.string(), payload: z.number() }).strict();
|
|
70
|
+
const data = parseOnboardingArtifactPayload(source, schema);
|
|
71
|
+
expect(data).toEqual({ client: "warpgogol-com", payload: 42 });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("parseOnboardingArtifactPayload preserves a metadata-named key when the schema declares it", () => {
|
|
75
|
+
// RFC-0082 carve-out: contentAtomsFileSchema (and others) declare
|
|
76
|
+
// `generatedAt` as a strict payload field. The helper must NOT strip it
|
|
77
|
+
// from a single-doc payload when the schema's .shape introspects it.
|
|
78
|
+
const source = `${HEADER_FIXTURE}\nclient: warpgogol-com\n`;
|
|
79
|
+
const schema = z.object({ client: z.string(), generatedAt: z.string() }).strict();
|
|
80
|
+
const data = parseOnboardingArtifactPayload(source, schema);
|
|
81
|
+
expect(data).toEqual({
|
|
82
|
+
client: "warpgogol-com",
|
|
83
|
+
generatedAt: "2026-05-23T12:00:00.000Z",
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("parseOnboardingArtifactPayload throws on an empty source", () => {
|
|
88
|
+
expect(() => parseOnboardingArtifactPayload("", z.any())).toThrow(/no YAML documents/);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("parseOnboardingArtifactPayload rejects doc-count > 2", () => {
|
|
92
|
+
const source = `---\n${HEADER_FIXTURE}\n---\nclient: warpgogol-com\n---\nstray: doc\n`;
|
|
93
|
+
expect(() => parseOnboardingArtifactPayload(source, z.any())).toThrow(
|
|
94
|
+
/expected exactly 1 or 2 YAML documents/,
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("RFC_METADATA_KEYS pins the four header field names", () => {
|
|
99
|
+
expect([...RFC_METADATA_KEYS].sort()).toEqual([
|
|
100
|
+
"derivedFromInputHash",
|
|
101
|
+
"generatedAt",
|
|
102
|
+
"generator",
|
|
103
|
+
"phase",
|
|
104
|
+
]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("parseOnboardingArtifactPayload propagates Zod schema errors", () => {
|
|
108
|
+
const source = `---\n${HEADER_FIXTURE}\n---\nclient: 42\n`;
|
|
109
|
+
const schema = z.object({ client: z.string() }).strict();
|
|
110
|
+
expect(() => parseOnboardingArtifactPayload(source, schema)).toThrow();
|
|
111
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { roleByCosmicName } from "@warpgogol/werkstatt-shared/ontology/archetypes";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
<MODULE_CONTRACT>
|
|
6
|
+
<purpose>
|
|
7
|
+
RFC-0263: unit test for the roleByCosmicName re-export — the manifest-
|
|
8
|
+
authored `role` field, keyed by cosmicName, derived by
|
|
9
|
+
archetype.registry.build and re-exported from @warpgogol/werkstatt-shared/ontology/archetypes.
|
|
10
|
+
Guards the two concrete hero-role entries buildPage's hideSectionNumber
|
|
11
|
+
injection depends on (see hero-section-numbering-parity.test.ts).
|
|
12
|
+
</purpose>
|
|
13
|
+
</MODULE_CONTRACT>
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
test("roleByCosmicName is exported and non-empty", () => {
|
|
17
|
+
expect(typeof roleByCosmicName).toBe("object");
|
|
18
|
+
expect(Object.keys(roleByCosmicName).length > 0).toBeTruthy();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('roleByCosmicName: both hero-role planets map to "hero"', () => {
|
|
22
|
+
expect(roleByCosmicName["Europa"]).toBe("hero"); // cosmic-literals-ignore: fixture cosmicName asserting the real registry output
|
|
23
|
+
expect(roleByCosmicName["Phobos"]).toBe("hero"); // cosmic-literals-ignore: fixture cosmicName asserting the real registry output
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('roleByCosmicName: a non-hero planet does not map to "hero"', () => {
|
|
27
|
+
expect(roleByCosmicName["Callisto"]).not.toBe("hero"); // cosmic-literals-ignore: fixture cosmicName for the non-hero control assertion
|
|
28
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>RFC-0289: bijection + shape tests for the OpenAPI projection formatter.</purpose>
|
|
4
|
+
<keywords>RFC-0289, agent surface, OpenAPI, test</keywords>
|
|
5
|
+
</MODULE_CONTRACT>
|
|
6
|
+
<MODULE_MAP>
|
|
7
|
+
<entry key="tests">empty manifest, knowledge ref projection, action ref projection, mcp/proof omission.</entry>
|
|
8
|
+
</MODULE_MAP>
|
|
9
|
+
<CHANGE_SUMMARY>
|
|
10
|
+
<item>RFC-0289: initial OpenAPI formatter tests.</item>
|
|
11
|
+
</CHANGE_SUMMARY>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { test, expect } from "vitest";
|
|
15
|
+
import { formatAgentOpenApi } from "../agent/openapi.ts";
|
|
16
|
+
import { buildAgentSurfaceManifest } from "../agent/manifest.ts";
|
|
17
|
+
|
|
18
|
+
test("formatAgentOpenApi: empty manifest yields a valid document with no paths", () => {
|
|
19
|
+
const manifest = buildAgentSurfaceManifest({
|
|
20
|
+
site: "s",
|
|
21
|
+
baseUrl: "https://s.example",
|
|
22
|
+
languages: { default: "de", supported: ["de"] },
|
|
23
|
+
});
|
|
24
|
+
const doc = formatAgentOpenApi(manifest, []);
|
|
25
|
+
expect(doc.openapi).toBe("3.1.0");
|
|
26
|
+
expect(doc.info.title).toBe("s agent surface");
|
|
27
|
+
expect(doc.info["x-gogol-content-hash"]).toBe(manifest.contentHash);
|
|
28
|
+
expect(doc.paths).toEqual({});
|
|
29
|
+
expect("x-gogol-mcp" in doc).toBe(false);
|
|
30
|
+
expect("x-gogol-proof" in doc).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("formatAgentOpenApi: one knowledge ref → one GET path + one component schema", () => {
|
|
34
|
+
const manifest = buildAgentSurfaceManifest({
|
|
35
|
+
site: "s",
|
|
36
|
+
baseUrl: "https://s.example",
|
|
37
|
+
languages: { default: "de", supported: ["de"] },
|
|
38
|
+
knowledge: [
|
|
39
|
+
{ domain: "offer", url: "/api/agent/v1/offer.json", schema: "gogol.agent.knowledge/offer@1" },
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
const doc = formatAgentOpenApi(manifest, []);
|
|
43
|
+
const op = doc.paths["/api/agent/v1/offer.json"]?.get;
|
|
44
|
+
expect(op).toBeTruthy();
|
|
45
|
+
expect(op!.operationId).toBe("knowledge.offer.get");
|
|
46
|
+
expect(op!.tags).toEqual(["knowledge"]);
|
|
47
|
+
expect(doc.components.schemas["knowledge-offer"]).toBeTruthy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("formatAgentOpenApi: one action ref → one POST path with verbatim input/output schemas", () => {
|
|
51
|
+
const inputSchema = {
|
|
52
|
+
type: "object" as const,
|
|
53
|
+
additionalProperties: false as const,
|
|
54
|
+
required: ["message"],
|
|
55
|
+
properties: { message: { type: "string" as const } },
|
|
56
|
+
};
|
|
57
|
+
const outputSchema = {
|
|
58
|
+
type: "object" as const,
|
|
59
|
+
additionalProperties: false as const,
|
|
60
|
+
properties: { accepted: { type: "boolean" as const } },
|
|
61
|
+
};
|
|
62
|
+
const manifest = buildAgentSurfaceManifest({
|
|
63
|
+
site: "s",
|
|
64
|
+
baseUrl: "https://s.example",
|
|
65
|
+
languages: { default: "de", supported: ["de"] },
|
|
66
|
+
actions: [
|
|
67
|
+
{
|
|
68
|
+
id: "lead.submit",
|
|
69
|
+
url: "/api/agent/actions/lead.submit",
|
|
70
|
+
title: { de: "Anfrage senden" },
|
|
71
|
+
inputSchemaRef: "#/components/schemas/lead.submit-input",
|
|
72
|
+
entitlement: "agent.actions",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
const doc = formatAgentOpenApi(manifest, [
|
|
77
|
+
{ id: "lead.submit", input: inputSchema, output: outputSchema },
|
|
78
|
+
]);
|
|
79
|
+
const op = doc.paths["/api/agent/actions/lead.submit"]?.post;
|
|
80
|
+
expect(op).toBeTruthy();
|
|
81
|
+
expect(op!.operationId).toBe("action.lead.submit");
|
|
82
|
+
expect(op!.summary).toBe("Anfrage senden");
|
|
83
|
+
expect(doc.components.schemas["lead.submit-input"]).toEqual(inputSchema);
|
|
84
|
+
expect(doc.components.schemas["lead.submit-output"]).toEqual(outputSchema);
|
|
85
|
+
expect(op!.requestBody!.content["application/json"].schema).toEqual(inputSchema);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("formatAgentOpenApi: an action ref without a matching capability schema is skipped defensively", () => {
|
|
89
|
+
const manifest = buildAgentSurfaceManifest({
|
|
90
|
+
site: "s",
|
|
91
|
+
baseUrl: "https://s.example",
|
|
92
|
+
languages: { default: "de", supported: ["de"] },
|
|
93
|
+
actions: [
|
|
94
|
+
{
|
|
95
|
+
id: "lead.submit",
|
|
96
|
+
url: "/api/agent/actions/lead.submit",
|
|
97
|
+
title: { de: "x" },
|
|
98
|
+
inputSchemaRef: "#/components/schemas/lead.submit-input",
|
|
99
|
+
entitlement: "agent.actions",
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
});
|
|
103
|
+
const doc = formatAgentOpenApi(manifest, []);
|
|
104
|
+
expect(doc.paths["/api/agent/actions/lead.submit"]).toBe(undefined);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("formatAgentOpenApi: mcp interface present → x-gogol-mcp is set", () => {
|
|
108
|
+
const manifest = buildAgentSurfaceManifest({
|
|
109
|
+
site: "s",
|
|
110
|
+
baseUrl: "https://s.example",
|
|
111
|
+
languages: { default: "de", supported: ["de"] },
|
|
112
|
+
mcp: { url: "/api/agent/mcp", protocolVersion: "2025-06-18" },
|
|
113
|
+
});
|
|
114
|
+
const doc = formatAgentOpenApi(manifest, []);
|
|
115
|
+
expect(doc["x-gogol-mcp"]).toEqual({ url: "/api/agent/mcp", protocolVersion: "2025-06-18" });
|
|
116
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>RFC-0745: test that buildOrganizationNode emits priceCurrency in makesOffer Offer nodes when currency is available.</purpose>
|
|
4
|
+
</MODULE_CONTRACT>
|
|
5
|
+
<CHANGE_SUMMARY>
|
|
6
|
+
<item>RFC-0745: initial test for priceCurrency in makesOffer Offer nodes.</item>
|
|
7
|
+
</CHANGE_SUMMARY>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
import { buildOrganizationNode } from "../semantic/jsonld/organization.ts";
|
|
12
|
+
import { createJsonLdContext } from "../semantic/jsonld/context.ts";
|
|
13
|
+
import type { SemanticPageModel, SemanticOrganization } from "../semantic/models.ts";
|
|
14
|
+
|
|
15
|
+
function makeOrgWithPrices(
|
|
16
|
+
prices: Array<{ id: string; label: string; amount: string; currency?: string }>,
|
|
17
|
+
): SemanticOrganization {
|
|
18
|
+
return {
|
|
19
|
+
name: "Test Org",
|
|
20
|
+
description: "Test organization",
|
|
21
|
+
url: "https://example.com",
|
|
22
|
+
offer: { prices },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function makeModel(org: SemanticOrganization): SemanticPageModel {
|
|
27
|
+
return {
|
|
28
|
+
type: "home",
|
|
29
|
+
lang: "de",
|
|
30
|
+
url: "https://example.com/de",
|
|
31
|
+
title: "Test Page",
|
|
32
|
+
description: "Test description",
|
|
33
|
+
breadcrumbs: [],
|
|
34
|
+
blocks: [],
|
|
35
|
+
organization: org,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("RFC-0745: buildOrganizationNode makesOffer priceCurrency", () => {
|
|
40
|
+
it("emits priceCurrency when SemanticPrice has currency", () => {
|
|
41
|
+
const org = makeOrgWithPrices([
|
|
42
|
+
{ id: "monthly", label: "Monthly", amount: "70.00", currency: "EUR" },
|
|
43
|
+
]);
|
|
44
|
+
const context = createJsonLdContext(makeModel(org));
|
|
45
|
+
const node = buildOrganizationNode(context);
|
|
46
|
+
const makesOffer = node.makesOffer as Array<Record<string, unknown>>;
|
|
47
|
+
expect(makesOffer).toHaveLength(1);
|
|
48
|
+
expect(makesOffer[0].priceCurrency).toBe("EUR");
|
|
49
|
+
const priceSpec = makesOffer[0].priceSpecification as Record<string, unknown>;
|
|
50
|
+
expect(priceSpec.price).toBe("70.00");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("omits priceCurrency when SemanticPrice has no currency", () => {
|
|
54
|
+
const org = makeOrgWithPrices([{ id: "monthly", label: "Monthly", amount: "70.00" }]);
|
|
55
|
+
const context = createJsonLdContext(makeModel(org));
|
|
56
|
+
const node = buildOrganizationNode(context);
|
|
57
|
+
const makesOffer = node.makesOffer as Array<Record<string, unknown>>;
|
|
58
|
+
expect(makesOffer).toHaveLength(1);
|
|
59
|
+
expect(makesOffer[0].priceCurrency).toBeUndefined();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("emits priceCurrency for each offer when multiple prices have currency", () => {
|
|
63
|
+
const org = makeOrgWithPrices([
|
|
64
|
+
{ id: "monthly", label: "Monthly", amount: "70.00", currency: "EUR" },
|
|
65
|
+
{ id: "yearly", label: "Yearly", amount: "840.00", currency: "EUR" },
|
|
66
|
+
]);
|
|
67
|
+
const context = createJsonLdContext(makeModel(org));
|
|
68
|
+
const node = buildOrganizationNode(context);
|
|
69
|
+
const makesOffer = node.makesOffer as Array<Record<string, unknown>>;
|
|
70
|
+
expect(makesOffer).toHaveLength(2);
|
|
71
|
+
expect(makesOffer[0].priceCurrency).toBe("EUR");
|
|
72
|
+
expect(makesOffer[1].priceCurrency).toBe("EUR");
|
|
73
|
+
});
|
|
74
|
+
});
|