@warpgogol/werkstatt-shared 0.13.0 → 0.14.1
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/README.md +26 -16
- package/README.uk.md +24 -14
- package/package.json +27 -69
- package/src/checks/result-helpers.ts +21 -4
- package/src/checks/tests/remediation-auto-populate.test.ts +83 -0
- package/src/integration/funnel.ts +78 -1
- package/src/integration/index.ts +19 -2
- package/src/integration/lagebild-ingress.ts +169 -0
- package/src/integration/orchestration.ts +7 -13
- package/src/integration/port-barrel.ts +9 -28
- package/src/integration/tests/funnel-bridge.test.ts +7 -7
- package/src/integration/tests/lagebild-ingress.test.ts +118 -0
- package/src/integration/vitest.config.ts +7 -0
- package/src/observability/typed-refs.ts +1 -1
- package/src/ontology/analytics/matomo-fleet.registry.yaml +1 -1
- package/src/ontology/archetypes/index.json +12 -9
- package/src/ontology/archetypes/index.yaml +26 -10
- package/src/ontology/blueprints/website-local.yaml +11 -11
- package/src/ontology/blueprints/website-service.yaml +20 -20
- package/src/ontology/capabilities/lead.submit.yaml +2 -2
- package/src/ontology/enums.ts +2 -2
- package/src/ontology/external-surfaces/jsonld-types.yaml +14 -14
- package/src/ontology/external-surfaces/url-schema.yaml +1 -1
- package/src/ontology/index.ts +2 -0
- package/src/ontology/manifest.ts +19 -0
- package/src/ontology/schemas/index.ts +7 -2
- package/src/ontology/schemas/system/integrations.ts +1 -1
- package/src/ontology/schemas/system/manifest.ts +38 -1
- package/src/ontology/schemas/system/tests/growth.test.ts +22 -0
- package/src/ontology/schemas/system/tests/integrations.test.ts +12 -0
- package/src/ontology/schemas/system/tests/manifest.test.ts +22 -0
- package/src/ontology/schemas/system/tests/page-output.test.ts +13 -0
- package/src/ontology/schemas/system/tests/release.test.ts +22 -0
- package/src/ontology/schemas/system/tests/text.test.ts +18 -0
- package/src/ontology/schemas/system/tests/verification.test.ts +12 -0
- package/src/ontology/schemas/system.ts +7 -2
- package/src/ontology/schemas/tests/biome.test.ts +19 -0
- package/src/ontology/schemas/tests/capability.test.ts +22 -0
- package/src/ontology/schemas/tests/constellation.test.ts +22 -0
- package/src/ontology/schemas/tests/dns-records.test.ts +13 -0
- package/src/ontology/schemas/tests/manifest-resolver.test.ts +13 -0
- package/src/ontology/schemas/tests/page-entry.test.ts +22 -0
- package/src/ontology/schemas/tests/section-archetype.test.ts +12 -0
- package/src/ontology/schemas/tests/site-family.test.ts +18 -0
- package/src/ontology/schemas/tests/system.test.ts +20 -0
- package/src/ontology/shared-section-props/common.ts +11 -0
- package/src/ontology/shared-section-props/visual-header.ts +1 -1
- package/src/share/agent/api-catalog.ts +5 -0
- package/src/share/agent/ard-catalog.ts +14 -0
- package/src/share/agent/index.ts +2 -0
- package/src/share/agent/manifest.ts +25 -2
- package/src/share/agent/mcp-card.ts +4 -0
- package/src/share/agent/openapi.ts +78 -0
- package/src/share/agent/search.test.ts +188 -0
- package/src/share/agent/search.ts +164 -0
- package/src/share/agent/tests/api-catalog.test.ts +8 -0
- package/src/share/agent/tests/ard-catalog.test.ts +8 -0
- package/src/share/agent/tests/capability.test.ts +14 -0
- package/src/share/agent/tests/fleet-catalog.test.ts +15 -0
- package/src/share/agent/tests/knowledge.test.ts +20 -0
- package/src/share/agent/tests/manifest.test.ts +9 -0
- package/src/share/agent/tests/mcp-card.test.ts +8 -0
- package/src/share/agent/tests/omit-empty.test.ts +33 -0
- package/src/share/agent/tests/openapi.test.ts +8 -0
- package/src/share/agent/tests/proof.test.ts +15 -0
- package/src/share/env.d.ts +0 -4
- package/src/share/knowledge/tests/claim.test.ts +11 -0
- package/src/share/knowledge/tests/derivation.test.ts +30 -0
- package/src/share/knowledge/tests/freshness.test.ts +18 -0
- package/src/share/knowledge/tests/ledger.test.ts +35 -0
- package/src/share/knowledge/tests/plan.test.ts +19 -0
- package/src/share/knowledge/tests/source.test.ts +19 -0
- package/src/share/remediation/remediation-catalog.ts +196 -0
- package/src/share/schemas/effects.ts +16 -0
- package/src/share/schemas/media.ts +4 -0
- package/src/share/schemas/section-shell.ts +2 -1
- package/src/share/schemas/tests/claim-records.test.ts +52 -0
- package/src/share/schemas/tests/claims.test.ts +23 -0
- package/src/share/schemas/tests/effects.test.ts +116 -0
- package/src/share/schemas/tests/features.test.ts +61 -0
- package/src/share/schemas/tests/horizontal-align.test.ts +16 -0
- package/src/share/schemas/tests/icon-color.test.ts +16 -0
- package/src/share/schemas/tests/live-photo.test.ts +40 -0
- package/src/share/schemas/tests/material-credit.test.ts +51 -0
- package/src/share/schemas/tests/media.test.ts +26 -0
- package/src/share/schemas/tests/navigation.test.ts +58 -0
- package/src/share/schemas/tests/page-base.test.ts +19 -0
- package/src/share/schemas/tests/participant.test.ts +26 -0
- package/src/share/schemas/tests/person.test.ts +12 -0
- package/src/share/schemas/tests/print.test.ts +30 -0
- package/src/share/schemas/tests/section-background.test.ts +31 -0
- package/src/share/schemas/tests/section-body.test.ts +16 -0
- package/src/share/schemas/tests/section-cards.test.ts +17 -0
- package/src/share/schemas/tests/section-cta.test.ts +41 -0
- package/src/share/schemas/tests/section-header.test.ts +31 -0
- package/src/share/schemas/tests/section-image.test.ts +24 -0
- package/src/share/schemas/tests/section-motion.test.ts +29 -0
- package/src/share/schemas/tests/section-shell.test.ts +42 -0
- package/src/share/schemas/tests/section-stats.test.ts +17 -0
- package/src/share/schemas/tests/site-background.test.ts +33 -0
- package/src/share/schemas/tests/standard-list-item.test.ts +16 -0
- package/src/share/scripts/external-link-qr.ts +9 -1
- package/src/share/scripts/gsap-counter.ts +2 -0
- package/src/share/scripts/inline-number-animation.ts +2 -0
- package/src/share/scripts/live-photos.ts +2 -0
- package/src/share/scripts/tests/external-link-qr.test.ts +8 -0
- package/src/share/scripts/tests/external-links.test.ts +25 -0
- package/src/share/scripts/tests/gsap-counter.test.ts +8 -0
- package/src/share/scripts/tests/gsap-mountain-journey.test.ts +8 -0
- package/src/share/scripts/tests/gsap-parallax.test.ts +8 -0
- package/src/share/scripts/tests/gsap-reveal.test.ts +8 -0
- package/src/share/scripts/tests/gsap-stagger.test.ts +8 -0
- package/src/share/scripts/tests/inline-number-animation.test.ts +8 -0
- package/src/share/scripts/tests/lenis.test.ts +8 -0
- package/src/share/scripts/tests/live-photos.test.ts +8 -0
- package/src/share/scripts/tests/lordicon.test.ts +8 -0
- package/src/share/scripts/tests/orchestrator.test.ts +8 -0
- package/src/share/scripts/tests/scheduler.test.ts +23 -0
- package/src/share/scripts/video-player.test.ts +210 -0
- package/src/share/scripts/video-player.ts +73 -13
- package/src/share/semantic/extract.ts +25 -1
- package/src/share/semantic/jsonld/tests/article.test.ts +89 -0
- package/src/share/semantic/jsonld/tests/breadcrumb.test.ts +62 -0
- package/src/share/semantic/jsonld/tests/collection-list.test.ts +39 -0
- package/src/share/semantic/jsonld/tests/faq.test.ts +60 -0
- package/src/share/semantic/jsonld/tests/initiative.test.ts +56 -0
- package/src/share/semantic/jsonld/tests/organization.test.ts +123 -0
- package/src/share/semantic/jsonld/tests/person.test.ts +89 -0
- package/src/share/semantic/jsonld/tests/service.test.ts +65 -0
- package/src/share/semantic/jsonld/tests/shared.test.ts +41 -0
- package/src/share/semantic/jsonld/tests/video.test.ts +84 -0
- package/src/share/semantic/jsonld/tests/webpage.test.ts +93 -0
- package/src/share/semantic/jsonld/tests/website.test.ts +27 -0
- package/src/share/semantic/jsonld/types.ts +1 -0
- package/src/share/semantic/models.ts +1 -0
- package/src/share/semantic/tests/ai.test.ts +55 -0
- package/src/share/semantic/tests/block-extraction.test.ts +34 -0
- package/src/share/semantic/tests/breadcrumbs.test.ts +127 -0
- package/src/share/semantic/tests/build-page.test.ts +122 -0
- package/src/share/semantic/tests/business-projection.test.ts +188 -0
- package/src/share/semantic/tests/derived-prices-loader.test.ts +46 -0
- package/src/share/semantic/tests/extract.test.ts +126 -0
- package/src/share/semantic/tests/feed.test.ts +113 -0
- package/src/share/semantic/tests/helpers.ts +32 -0
- package/src/share/semantic/tests/ids.test.ts +118 -0
- package/src/share/semantic/tests/image-sitemap.test.ts +109 -0
- package/src/share/semantic/tests/jsonld.test.ts +61 -0
- package/src/share/semantic/tests/llms-policy.test.ts +60 -0
- package/src/share/semantic/tests/llms.test.ts +118 -0
- package/src/share/semantic/tests/markdown-hygiene.test.ts +72 -0
- package/src/share/semantic/tests/markdown-page.test.ts +97 -0
- package/src/share/semantic/tests/markdown-twin-provenance.test.ts +152 -0
- package/src/share/semantic/tests/organization-profile.test.ts +107 -0
- package/src/share/semantic/tests/output-projection.test.ts +77 -0
- package/src/share/semantic/tests/page-markdown.test.ts +98 -0
- package/src/share/semantic/tests/page-utils.test.ts +88 -0
- package/src/share/semantic/tests/price-marker-resolver.test.ts +88 -0
- package/src/share/semantic/tests/robots.test.ts +70 -0
- package/src/share/semantic/tests/split-sentences.test.ts +57 -0
- package/src/share/semantic/tests/update-stamp.test.ts +102 -0
- package/src/share/tests/manifest.test.ts +51 -0
- package/src/share/tests/openapi.test.ts +30 -0
- package/src/share/types/qrcode-browser.d.ts +18 -0
- package/src/share/utility-registry.yaml +16 -2
- package/src/integration/crm-buffer.ts +0 -491
- package/src/integration-adapter-supabase-crm/adapter.ts +0 -437
- package/src/integration-adapter-supabase-crm/client.ts +0 -605
- package/src/integration-adapter-supabase-crm/index.ts +0 -28
- package/src/integration-adapter-supabase-crm/pipedrive-sync-target.ts +0 -482
- package/src/integration-adapter-supabase-crm/supabase-rest.ts +0 -89
- package/src/integration-adapter-supabase-crm/tenant-registry.ts +0 -334
- package/src/integration-adapter-supabase-crm/tests/change-balance.pbt.test.ts +0 -83
- package/src/integration-adapter-supabase-crm/tests/funnel-persistence.test.ts +0 -409
- package/src/integration-adapter-supabase-crm/tests/lifecycle-sync.test.ts +0 -288
- package/src/integration-adapter-supabase-crm/tests/stage-map.test.ts +0 -80
- package/src/integration-adapter-supabase-crm/vitest.config.ts +0 -8
- package/src/integration-adapter-supabase-crm/worker.ts +0 -223
- package/src/ontology/archetypes/components/currency-selector.yaml +0 -19
|
@@ -95,8 +95,8 @@ levels:
|
|
|
95
95
|
de: "Welche Angaben helfen, den Betrieb einzuschätzen: Qualifikationen, Meisterbetrieb, Fotos, Bewertungen, Öffnungszeiten."
|
|
96
96
|
uk: "Які відомості допомагають оцінити бізнес: кваліфікації, майстерність, фото, відгуки, години роботи."
|
|
97
97
|
catalogHeading:
|
|
98
|
-
de:
|
|
99
|
-
uk:
|
|
98
|
+
de: Gewerbe auswählen
|
|
99
|
+
uk: Обрати галузь
|
|
100
100
|
productPrice:
|
|
101
101
|
heading:
|
|
102
102
|
de: "Gleiche Grundlage, angepasste Struktur"
|
|
@@ -104,7 +104,7 @@ levels:
|
|
|
104
104
|
body:
|
|
105
105
|
de: "Die Branche verändert nicht automatisch den Basispreis. Zusätzliche Seiten, Sprachen, Buchungsfunktionen oder Integrationen werden gesondert vereinbart."
|
|
106
106
|
uk: "Галузь не змінює автоматично базову ціну. Додаткові сторінки, мови, функції бронювання чи інтеграції узгоджуються окремо."
|
|
107
|
-
priceRef:
|
|
107
|
+
priceRef: business-profile.offerings/digital-foundation.presentation.price
|
|
108
108
|
finalCta:
|
|
109
109
|
heading:
|
|
110
110
|
de: Ihr Gewerbe ist noch nicht aufgeführt?
|
|
@@ -141,14 +141,14 @@ levels:
|
|
|
141
141
|
minModuleMappings: 3
|
|
142
142
|
minUniqueFaq: 5
|
|
143
143
|
claimRestrictions:
|
|
144
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
144
|
+
- mehr Anfragen
|
|
145
|
+
- mehr Termin-Anfragen
|
|
146
|
+
- echte Aufträge
|
|
147
|
+
- steigt die Wahrscheinlichkeit
|
|
148
|
+
- weniger Streuverluste
|
|
149
|
+
- höhere Conversion
|
|
150
|
+
- besser gefunden
|
|
151
|
+
- stärkstes Conversion-Signal
|
|
152
152
|
doorwayMaxFlaggedShare: 0.30
|
|
153
153
|
duplicateMaxSimilarity: 0.70
|
|
154
154
|
mode: warn
|
|
@@ -22,7 +22,7 @@ axes:
|
|
|
22
22
|
|
|
23
23
|
levels:
|
|
24
24
|
- depth: 0
|
|
25
|
-
slug: { de:
|
|
25
|
+
slug: { de: leistungen/website-service, uk: posluhy/sait-service }
|
|
26
26
|
constellation: website-service-root
|
|
27
27
|
geo: twin-only
|
|
28
28
|
semanticType: collection
|
|
@@ -51,25 +51,25 @@ levels:
|
|
|
51
51
|
minFaq: 5
|
|
52
52
|
minPageStructure: 1
|
|
53
53
|
claimRestrictions:
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
54
|
+
- mehr Anfragen
|
|
55
|
+
- mehr Termin-Anfragen
|
|
56
|
+
- mehr Buchungen
|
|
57
|
+
- echte Aufträge
|
|
58
|
+
- steigt die Wahrscheinlichkeit
|
|
59
|
+
- weniger Streuverluste
|
|
60
|
+
- höhere Conversion
|
|
61
|
+
- besser gefunden
|
|
62
|
+
- stärkstes Conversion-Signal
|
|
63
|
+
- garantierte Ergebnisse
|
|
64
|
+
- guaranteed results
|
|
65
|
+
- no. 1
|
|
66
|
+
- number one
|
|
67
|
+
- leading provider
|
|
68
|
+
- top rated
|
|
69
|
+
- beste Preis
|
|
70
|
+
- best price
|
|
71
|
+
- cheapest
|
|
72
|
+
- günstigste
|
|
73
73
|
mode: warn
|
|
74
74
|
|
|
75
75
|
policy:
|
|
@@ -2,8 +2,8 @@ id: lead.submit
|
|
|
2
2
|
version: 1
|
|
3
3
|
kind: action
|
|
4
4
|
title:
|
|
5
|
-
de:
|
|
6
|
-
en:
|
|
5
|
+
de: Anfrage senden
|
|
6
|
+
en: Submit a lead
|
|
7
7
|
description:
|
|
8
8
|
de: "Reicht eine Kontaktanfrage (Name, E-Mail, Nachricht) beim Gewerbe ein. Die Anfrage wird asynchron zugestellt — die Bestätigung signalisiert Annahme, nicht Zustellung."
|
|
9
9
|
en: "Submit a contact request (name, email, message) to the business. The request is delivered asynchronously — the confirmation signals acceptance, not delivery."
|
package/src/ontology/enums.ts
CHANGED
|
@@ -87,7 +87,7 @@ export type SemanticRole = string;
|
|
|
87
87
|
* section-cta | [RFC-0104] Single CTA / CTA group primitive
|
|
88
88
|
* section-image | [RFC-0104] Authored image primitive with fade masks
|
|
89
89
|
* site-background | [RFC-0105] Full-viewport background shell-layer component
|
|
90
|
-
*
|
|
90
|
+
* cycle-toggle | [RFC-0946] Generic cycle toggle button with localStorage persistence
|
|
91
91
|
* price-display | [RFC-0743] Currency-aware price display with pre-rendered variants
|
|
92
92
|
* scroll-to-top | [RFC-0768] Floating scroll-to-top button with Lenis smooth scrolling
|
|
93
93
|
*/
|
|
@@ -107,7 +107,7 @@ export const ComponentRoleValues = [
|
|
|
107
107
|
"section-cta",
|
|
108
108
|
"section-image",
|
|
109
109
|
"site-background",
|
|
110
|
-
"
|
|
110
|
+
"cycle-toggle",
|
|
111
111
|
"price-display",
|
|
112
112
|
"scroll-to-top",
|
|
113
113
|
] as const;
|
|
@@ -105,31 +105,31 @@ surfacePolicy:
|
|
|
105
105
|
# Enforced by surface.media-leakage.validate and surface.contract.validate.
|
|
106
106
|
mediaLeakagePolicy:
|
|
107
107
|
prohibitedStrings:
|
|
108
|
-
- pattern:
|
|
108
|
+
- pattern: Gemini
|
|
109
109
|
matchingStrategy: context-aware
|
|
110
110
|
contextSelector: "[data-credit-context], figcaption, details, dl"
|
|
111
111
|
reason: "AI model name is internal metadata, not visitor-facing"
|
|
112
|
-
- pattern:
|
|
112
|
+
- pattern: AIPlatform
|
|
113
113
|
matchingStrategy: whole-word
|
|
114
|
-
reason:
|
|
115
|
-
- pattern:
|
|
114
|
+
reason: Internal enum value (CreditPartyKind)
|
|
115
|
+
- pattern: Organization
|
|
116
116
|
matchingStrategy: context-aware
|
|
117
117
|
contextSelector: "[data-credit-context], figcaption, details, dl"
|
|
118
|
-
reason:
|
|
119
|
-
- pattern:
|
|
118
|
+
reason: Internal enum value (CreditPartyKind) — only as media author label
|
|
119
|
+
- pattern: commissioned-warpgogol-material
|
|
120
120
|
matchingStrategy: whole-word
|
|
121
|
-
reason:
|
|
122
|
-
- pattern:
|
|
121
|
+
reason: Internal enum value (MaterialSourceType)
|
|
122
|
+
- pattern: linked-public-source
|
|
123
123
|
matchingStrategy: whole-word
|
|
124
|
-
reason:
|
|
125
|
-
- pattern:
|
|
124
|
+
reason: Internal enum value
|
|
125
|
+
- pattern: Copyright © 2026 Warpgogol
|
|
126
126
|
matchingStrategy: exact
|
|
127
127
|
contextSelector: ":not(footer):not([data-footer])"
|
|
128
|
-
reason:
|
|
128
|
+
reason: Repetitive copyright boilerplate — per-material usage status is on /bildnachweise/
|
|
129
129
|
requiredLabels:
|
|
130
|
-
- label:
|
|
130
|
+
- label: Konzeptillustration
|
|
131
131
|
lang: de
|
|
132
|
-
- label:
|
|
132
|
+
- label: Концептуальна ілюстрація
|
|
133
133
|
lang: uk
|
|
134
134
|
requiredLinkPattern: "/bildnachweise/#"
|
|
135
|
-
aiImageAttribute:
|
|
135
|
+
aiImageAttribute: data-ai-generated
|
package/src/ontology/index.ts
CHANGED
|
@@ -81,6 +81,7 @@ export {
|
|
|
81
81
|
SiteFamilyContract,
|
|
82
82
|
sectionArchetypeSchema,
|
|
83
83
|
systemManifestSchema,
|
|
84
|
+
systemCollectionSchema,
|
|
84
85
|
} from "./schemas/index.ts";
|
|
85
86
|
export type {
|
|
86
87
|
Constellation,
|
|
@@ -106,6 +107,7 @@ export type {
|
|
|
106
107
|
SystemManifest,
|
|
107
108
|
SystemPagePin,
|
|
108
109
|
SystemPlanetPin,
|
|
110
|
+
SystemCollectionData,
|
|
109
111
|
} from "./schemas/index.ts";
|
|
110
112
|
|
|
111
113
|
// ---------------------------------------------------------------------------
|
package/src/ontology/manifest.ts
CHANGED
|
@@ -305,6 +305,25 @@ export const componentManifestSchema = manifestBaseSchema.extend({
|
|
|
305
305
|
* Do not use these five names for any other component manifest.
|
|
306
306
|
*/
|
|
307
307
|
cosmicName: moonNameSchema,
|
|
308
|
+
/**
|
|
309
|
+
* RFC-1023: JSON Schema (draft-07 compatible) describing the shape of
|
|
310
|
+
* resolved content returned by getResolvedComponentContent. This is the
|
|
311
|
+
* flat, merged content (after pageOverride merge), NOT the prose .md
|
|
312
|
+
* frontmatter schema. Used by props.types.generate to emit
|
|
313
|
+
* XxxComponentContent interfaces. Required for content-driven components
|
|
314
|
+
* (those that call getResolvedComponentContent). Optional for structural
|
|
315
|
+
* components that consume no content.
|
|
316
|
+
*/
|
|
317
|
+
contentSchema: z.record(z.string(), z.unknown()).optional(),
|
|
318
|
+
/**
|
|
319
|
+
* RFC-1023: JSON Schema (draft-07 compatible) describing the shape of
|
|
320
|
+
* Astro.props accepted by the component — caller-supplied props such as
|
|
321
|
+
* lang, defaultLang, pageOverride, etc. Used by props.types.generate to
|
|
322
|
+
* emit XxxComponentProps interfaces. Distinct from contentSchema: propsSchema
|
|
323
|
+
* describes what the caller passes, contentSchema describes what the
|
|
324
|
+
* component resolves from content files.
|
|
325
|
+
*/
|
|
326
|
+
propsSchema: z.record(z.string(), z.unknown()).optional(),
|
|
308
327
|
});
|
|
309
328
|
|
|
310
329
|
/**
|
|
@@ -63,8 +63,13 @@ export type {
|
|
|
63
63
|
SectionArchetypeLayoutHint,
|
|
64
64
|
} from "./section-archetype.ts";
|
|
65
65
|
|
|
66
|
-
export { systemManifestSchema } from "./system.ts";
|
|
67
|
-
export type {
|
|
66
|
+
export { systemManifestSchema, systemCollectionSchema } from "./system.ts";
|
|
67
|
+
export type {
|
|
68
|
+
SystemManifest,
|
|
69
|
+
SystemPagePin,
|
|
70
|
+
SystemPlanetPin,
|
|
71
|
+
SystemCollectionData,
|
|
72
|
+
} from "./system.ts";
|
|
68
73
|
|
|
69
74
|
// Architecture review 2026-07-10: Re-export growthVendorSchema for @warpgogol/werkstatt-site/growth/config.ts.
|
|
70
75
|
export { growthVendorSchema } from "./system.ts";
|
|
@@ -128,7 +128,7 @@ export const systemIntegrationsSchema = z.object({
|
|
|
128
128
|
* (e.g. uchat, stripe, operator), and whether the pilot is `enabled`. UChat is the
|
|
129
129
|
* conversation runtime — it renders the funnel and requests transitions; it never
|
|
130
130
|
* owns the graph, pricing, or canonical state. Make.com is never a source. Validated
|
|
131
|
-
* by `funnel.contract.validate` / `funnel.stage.validate` / `funnel.
|
|
131
|
+
* by `funnel.contract.validate` / `funnel.stage.validate` / `funnel.crm.validate`.
|
|
132
132
|
* Absent ⇒ the funnel validators are a no-op pass (funnel not yet enabled for the app).
|
|
133
133
|
*/
|
|
134
134
|
funnel: z
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<CHANGE_SUMMARY>
|
|
9
9
|
<item>RFC-0303 Phase 3: extracted from schemas/system.ts as part of the domain split.</item>
|
|
10
10
|
<item>RFC-0377: added optional `audience` field to the per-page pin schema.</item>
|
|
11
|
+
<item>ADR-0062: added `ctaTarget` to identity, `sectionNav` + `ctaTarget` to page pins, created `systemCollectionSchema` for content collection typing.</item>
|
|
11
12
|
</CHANGE_SUMMARY>
|
|
12
13
|
*/
|
|
13
14
|
|
|
@@ -79,6 +80,13 @@ export const systemManifestSchema = z.object({
|
|
|
79
80
|
* brief.validate can cross-check the brief against the running app identity.
|
|
80
81
|
*/
|
|
81
82
|
domain: z.string().min(1).optional(),
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* ADR-0062: App-level default CTA target — the pageId of the contact/CTA page.
|
|
86
|
+
* Per-page `ctaTarget` in pages[] overrides this app-level default.
|
|
87
|
+
* Used by resolve-route.ts to populate `ctaTarget` in PageRouteData.
|
|
88
|
+
*/
|
|
89
|
+
ctaTarget: z.string().min(1).optional(),
|
|
82
90
|
}),
|
|
83
91
|
|
|
84
92
|
/**
|
|
@@ -222,7 +230,7 @@ export const systemManifestSchema = z.object({
|
|
|
222
230
|
enabled: z.boolean(),
|
|
223
231
|
cosmicMoon: z.string().min(1),
|
|
224
232
|
pin: z.string().min(1),
|
|
225
|
-
props: z.record(z.string(), z.
|
|
233
|
+
props: z.record(z.string(), z.unknown()).optional(),
|
|
226
234
|
})
|
|
227
235
|
.optional(),
|
|
228
236
|
})
|
|
@@ -247,6 +255,19 @@ export const systemManifestSchema = z.object({
|
|
|
247
255
|
)
|
|
248
256
|
.optional()
|
|
249
257
|
.default([]),
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* RFC-0922 / ADR-0062: per-page section nav toggle. When false, the
|
|
261
|
+
* page template skips extractSectionNavItems and the Header secondary
|
|
262
|
+
* nav strip is omitted. Defaults to true when absent.
|
|
263
|
+
*/
|
|
264
|
+
sectionNav: z.boolean().optional(),
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* ADR-0062: per-page CTA target override. When present, overrides the
|
|
268
|
+
* app-level `identity.ctaTarget` for this page.
|
|
269
|
+
*/
|
|
270
|
+
ctaTarget: z.string().min(1).optional(),
|
|
250
271
|
}),
|
|
251
272
|
)
|
|
252
273
|
.optional()
|
|
@@ -498,3 +519,19 @@ export type SystemManifest = z.infer<typeof systemManifestSchema>;
|
|
|
498
519
|
export type SystemPagePin = NonNullable<SystemManifest["pages"]>[number];
|
|
499
520
|
/** A single planet pin within a page-route entry. */
|
|
500
521
|
export type SystemPlanetPin = NonNullable<SystemManifest["pages"][number]["planets"]>[number];
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* ADR-0062: Lenient schema for the `system` Astro content collection.
|
|
525
|
+
*
|
|
526
|
+
* `systemManifestSchema` is the strict validation schema used by `system.manifest.validate`.
|
|
527
|
+
* The content collection schema needs to be more lenient:
|
|
528
|
+
* - `.partial()` — all top-level fields are optional (system.md content varies per site)
|
|
529
|
+
* - `.loose()` — unknown top-level keys pass through (e.g. `policy`, `seo`)
|
|
530
|
+
*
|
|
531
|
+
* This schema is used in `src/content/config.ts` via `defineCollection({ schema: systemCollectionSchema })`.
|
|
532
|
+
* It provides compile-time typing for `getCollection("system")` consumers, eliminating `as any` casts.
|
|
533
|
+
*/
|
|
534
|
+
export const systemCollectionSchema = systemManifestSchema.partial().loose();
|
|
535
|
+
|
|
536
|
+
/** Inferred type for the `system` content collection data. */
|
|
537
|
+
export type SystemCollectionData = z.infer<typeof systemCollectionSchema>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemGrowthSchema, growthVendorSchema } from "../growth.ts";
|
|
3
|
+
|
|
4
|
+
describe("growthVendorSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(growthVendorSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => growthVendorSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("systemGrowthSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(systemGrowthSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => systemGrowthSchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemIntegrationsSchema } from "../integrations.ts";
|
|
3
|
+
|
|
4
|
+
describe("systemIntegrationsSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(systemIntegrationsSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => systemIntegrationsSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemManifestSchema, systemCollectionSchema } from "../manifest.ts";
|
|
3
|
+
|
|
4
|
+
describe("systemManifestSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(systemManifestSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => systemManifestSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("systemCollectionSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(systemCollectionSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => systemCollectionSchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { semanticPageTypeSchema } from "../page-output.ts";
|
|
3
|
+
|
|
4
|
+
describe("semanticPageTypeSchema", () => {
|
|
5
|
+
it("accepts valid page types", () => {
|
|
6
|
+
const result = semanticPageTypeSchema.safeParse("home");
|
|
7
|
+
expect(result.success).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("rejects invalid page type", () => {
|
|
11
|
+
expect(() => semanticPageTypeSchema.parse("invalid-type")).toThrow();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemPassportSchema, systemReleaseSchema } from "../release.ts";
|
|
3
|
+
|
|
4
|
+
describe("systemPassportSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(systemPassportSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => systemPassportSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("systemReleaseSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(systemReleaseSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => systemReleaseSchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemTextSchema, systemTextNormalizeSchema } from "../text.ts";
|
|
3
|
+
|
|
4
|
+
describe("systemTextSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(systemTextSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => systemTextSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("systemTextNormalizeSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(systemTextNormalizeSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { systemVerificationSchema } from "../verification.ts";
|
|
3
|
+
|
|
4
|
+
describe("systemVerificationSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(systemVerificationSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => systemVerificationSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -49,5 +49,10 @@ export {
|
|
|
49
49
|
pageOutputSchema,
|
|
50
50
|
} from "./system/page-output.ts";
|
|
51
51
|
|
|
52
|
-
export { systemManifestSchema } from "./system/manifest.ts";
|
|
53
|
-
export type {
|
|
52
|
+
export { systemManifestSchema, systemCollectionSchema } from "./system/manifest.ts";
|
|
53
|
+
export type {
|
|
54
|
+
SystemManifest,
|
|
55
|
+
SystemPagePin,
|
|
56
|
+
SystemPlanetPin,
|
|
57
|
+
SystemCollectionData,
|
|
58
|
+
} from "./system/manifest.ts";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { biomeProvenanceSchema, biomeAxesSchema } from "../biome.ts";
|
|
3
|
+
|
|
4
|
+
describe("biomeProvenanceSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(biomeProvenanceSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => biomeProvenanceSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("biomeAxesSchema", () => {
|
|
15
|
+
it("is defined and parseable", () => {
|
|
16
|
+
expect(biomeAxesSchema).toBeDefined();
|
|
17
|
+
expect(() => biomeAxesSchema.parse(null)).toThrow();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { capabilityInputOutputSchema, capabilityRecordSchema } from "../capability.ts";
|
|
3
|
+
|
|
4
|
+
describe("capabilityInputOutputSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(capabilityInputOutputSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => capabilityInputOutputSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("capabilityRecordSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(capabilityRecordSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => capabilityRecordSchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { constellationSlotSchema, constellationSchema } from "../constellation.ts";
|
|
3
|
+
|
|
4
|
+
describe("constellationSlotSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(constellationSlotSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => constellationSlotSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("constellationSchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(constellationSchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => constellationSchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { dnsRecordTypeSchema } from "../dns-records.ts";
|
|
3
|
+
|
|
4
|
+
describe("dnsRecordTypeSchema", () => {
|
|
5
|
+
it("accepts valid DNS record types", () => {
|
|
6
|
+
const result = dnsRecordTypeSchema.safeParse("A");
|
|
7
|
+
expect(result.success).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("rejects invalid type", () => {
|
|
11
|
+
expect(() => dnsRecordTypeSchema.parse("INVALID")).toThrow();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { getSectionPropsSchema } from "../manifest-resolver.ts";
|
|
3
|
+
|
|
4
|
+
describe("getSectionPropsSchema", () => {
|
|
5
|
+
it("is an async function", () => {
|
|
6
|
+
expect(typeof getSectionPropsSchema).toBe("function");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("returns null for unknown archetype", async () => {
|
|
10
|
+
const result = await getSectionPropsSchema("nonexistent-archetype", "/nonexistent");
|
|
11
|
+
expect(result).toBeNull();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { BlockEntrySchema, PageEntrySchema } from "../page-entry.ts";
|
|
3
|
+
|
|
4
|
+
describe("BlockEntrySchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(BlockEntrySchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => BlockEntrySchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("PageEntrySchema", () => {
|
|
15
|
+
it("is defined", () => {
|
|
16
|
+
expect(PageEntrySchema).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("rejects null", () => {
|
|
20
|
+
expect(() => PageEntrySchema.parse(null)).toThrow();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { sectionArchetypeSchema } from "../section-archetype.ts";
|
|
3
|
+
|
|
4
|
+
describe("sectionArchetypeSchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(sectionArchetypeSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => sectionArchetypeSchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { siteFamilySchema, SiteFamilyContract } from "../site-family.ts";
|
|
3
|
+
|
|
4
|
+
describe("siteFamilySchema", () => {
|
|
5
|
+
it("is defined", () => {
|
|
6
|
+
expect(siteFamilySchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rejects null", () => {
|
|
10
|
+
expect(() => siteFamilySchema.parse(null)).toThrow();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("SiteFamilyContract", () => {
|
|
15
|
+
it("is the same schema as siteFamilySchema", () => {
|
|
16
|
+
expect(SiteFamilyContract).toBe(siteFamilySchema);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import * as systemModule from "../system.ts";
|
|
3
|
+
|
|
4
|
+
describe("system.ts barrel re-exports", () => {
|
|
5
|
+
it("re-exports systemManifestSchema", () => {
|
|
6
|
+
expect(systemModule.systemManifestSchema).toBeDefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("re-exports systemIntegrationsSchema", () => {
|
|
10
|
+
expect(systemModule.systemIntegrationsSchema).toBeDefined();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("re-exports systemPassportSchema", () => {
|
|
14
|
+
expect(systemModule.systemPassportSchema).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("re-exports systemReleaseSchema", () => {
|
|
18
|
+
expect(systemModule.systemReleaseSchema).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
});
|