@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.
Files changed (403) hide show
  1. package/package.json +352 -0
  2. package/src/checks/index.ts +24 -0
  3. package/src/checks/lib/astro-site-url.ts +30 -0
  4. package/src/checks/lib/i18n.ts +30 -0
  5. package/src/checks/result-helpers.ts +102 -0
  6. package/src/checks/suppressions-config.ts +195 -0
  7. package/src/index.ts +14 -0
  8. package/src/integration/README.md +38 -0
  9. package/src/integration/adapters.ts +143 -0
  10. package/src/integration/crm-buffer.ts +491 -0
  11. package/src/integration/dispatch.ts +106 -0
  12. package/src/integration/funnel.ts +379 -0
  13. package/src/integration/index.ts +56 -0
  14. package/src/integration/lifecycle.ts +155 -0
  15. package/src/integration/orchestration.ts +439 -0
  16. package/src/integration/port-barrel.ts +124 -0
  17. package/src/integration/port.ts +143 -0
  18. package/src/integration/qstash.ts +134 -0
  19. package/src/integration/sharding.ts +133 -0
  20. package/src/integration/tests/deliver-event.test.ts +52 -0
  21. package/src/integration/tests/dispatch.test.ts +88 -0
  22. package/src/integration/tests/funnel-bridge.test.ts +46 -0
  23. package/src/integration/tests/hub-runtime.test.ts +128 -0
  24. package/src/integration/tests/lifecycle.test.ts +69 -0
  25. package/src/integration/tests/qstash.test.ts +83 -0
  26. package/src/integration/tests/sharding.test.ts +64 -0
  27. package/src/integration/vitest.config.ts +8 -0
  28. package/src/integration-adapter-supabase-crm/adapter.ts +437 -0
  29. package/src/integration-adapter-supabase-crm/client.ts +605 -0
  30. package/src/integration-adapter-supabase-crm/index.ts +28 -0
  31. package/src/integration-adapter-supabase-crm/pipedrive-sync-target.ts +482 -0
  32. package/src/integration-adapter-supabase-crm/supabase-rest.ts +89 -0
  33. package/src/integration-adapter-supabase-crm/tenant-registry.ts +334 -0
  34. package/src/integration-adapter-supabase-crm/tests/change-balance.pbt.test.ts +83 -0
  35. package/src/integration-adapter-supabase-crm/tests/funnel-persistence.test.ts +409 -0
  36. package/src/integration-adapter-supabase-crm/tests/lifecycle-sync.test.ts +288 -0
  37. package/src/integration-adapter-supabase-crm/tests/stage-map.test.ts +80 -0
  38. package/src/integration-adapter-supabase-crm/vitest.config.ts +8 -0
  39. package/src/integration-adapter-supabase-crm/worker.ts +223 -0
  40. package/src/observability/conventions.ts +93 -0
  41. package/src/observability/env-resolver.ts +57 -0
  42. package/src/observability/index.ts +57 -0
  43. package/src/observability/metric-registry.ts +184 -0
  44. package/src/observability/otlp-converter.ts +125 -0
  45. package/src/observability/otlp-json.ts +135 -0
  46. package/src/observability/otlp-transport.ts +68 -0
  47. package/src/observability/pusher.ts +142 -0
  48. package/src/observability/redact.ts +27 -0
  49. package/src/observability/tests/conventions.test.ts +100 -0
  50. package/src/observability/tests/metric-registry.test.ts +117 -0
  51. package/src/observability/tests/otlp-converter.pbt.test.ts +77 -0
  52. package/src/observability/tests/otlp-converter.test.ts +157 -0
  53. package/src/observability/tests/otlp-json.test.ts +120 -0
  54. package/src/observability/tests/pusher.test.ts +75 -0
  55. package/src/observability/tests/redact.pbt.test.ts +71 -0
  56. package/src/observability/tests/redact.test.ts +37 -0
  57. package/src/observability/typed-refs.ts +137 -0
  58. package/src/observability/vitest.config.ts +8 -0
  59. package/src/ontology/analytics/matomo-binding.yaml +172 -0
  60. package/src/ontology/analytics/matomo-fleet.registry.yaml +26 -0
  61. package/src/ontology/analytics/messkanon.yaml +151 -0
  62. package/src/ontology/archetype-registry.ts +61 -0
  63. package/src/ontology/archetypes/components/brand-label.yaml +19 -0
  64. package/src/ontology/archetypes/components/copyright.yaml +19 -0
  65. package/src/ontology/archetypes/components/currency-aware-price-display.yaml +19 -0
  66. package/src/ontology/archetypes/components/currency-selector.yaml +19 -0
  67. package/src/ontology/archetypes/components/footer-promo.yaml +19 -0
  68. package/src/ontology/archetypes/components/lang-switcher.yaml +19 -0
  69. package/src/ontology/archetypes/components/layout.yaml +19 -0
  70. package/src/ontology/archetypes/components/live-photo.yaml +20 -0
  71. package/src/ontology/archetypes/components/material-credit.yaml +20 -0
  72. package/src/ontology/archetypes/components/media.yaml +21 -0
  73. package/src/ontology/archetypes/components/nachweis-card.yaml +34 -0
  74. package/src/ontology/archetypes/components/nachweis-detail.yaml +43 -0
  75. package/src/ontology/archetypes/components/nachweis-list.yaml +37 -0
  76. package/src/ontology/archetypes/components/nachweis-verify.yaml +31 -0
  77. package/src/ontology/archetypes/components/not-found.yaml +22 -0
  78. package/src/ontology/archetypes/components/offer-capacity.yaml +21 -0
  79. package/src/ontology/archetypes/components/passport-header.yaml +19 -0
  80. package/src/ontology/archetypes/components/passport-provenance.yaml +20 -0
  81. package/src/ontology/archetypes/components/passport-score-grid.yaml +20 -0
  82. package/src/ontology/archetypes/components/passport-star-map.yaml +20 -0
  83. package/src/ontology/archetypes/components/person-profile.yaml +20 -0
  84. package/src/ontology/archetypes/components/pulsar.yaml +20 -0
  85. package/src/ontology/archetypes/components/responsive-image.yaml +19 -0
  86. package/src/ontology/archetypes/components/scroll-to-top.yaml +22 -0
  87. package/src/ontology/archetypes/components/social-meta.yaml +20 -0
  88. package/src/ontology/archetypes/components/structured-data.yaml +19 -0
  89. package/src/ontology/archetypes/index.json +1003 -0
  90. package/src/ontology/archetypes/index.yaml +821 -0
  91. package/src/ontology/archetypes/sections/approach.yaml +23 -0
  92. package/src/ontology/archetypes/sections/article-list.yaml +30 -0
  93. package/src/ontology/archetypes/sections/audience-cards.yaml +30 -0
  94. package/src/ontology/archetypes/sections/breadcrumbs.yaml +21 -0
  95. package/src/ontology/archetypes/sections/chat-widget.yaml +37 -0
  96. package/src/ontology/archetypes/sections/comparison-cards.yaml +31 -0
  97. package/src/ontology/archetypes/sections/controlled-responsibility-block.yaml +34 -0
  98. package/src/ontology/archetypes/sections/credits.yaml +29 -0
  99. package/src/ontology/archetypes/sections/donation-card.yaml +53 -0
  100. package/src/ontology/archetypes/sections/donation-use.yaml +23 -0
  101. package/src/ontology/archetypes/sections/dynamic-status-block.yaml +35 -0
  102. package/src/ontology/archetypes/sections/faq-list.yaml +26 -0
  103. package/src/ontology/archetypes/sections/final-cta.yaml +53 -0
  104. package/src/ontology/archetypes/sections/hero-decision-card.yaml +65 -0
  105. package/src/ontology/archetypes/sections/hero.yaml +50 -0
  106. package/src/ontology/archetypes/sections/impact.yaml +23 -0
  107. package/src/ontology/archetypes/sections/markdown.yaml +43 -0
  108. package/src/ontology/archetypes/sections/mountain-journey.yaml +43 -0
  109. package/src/ontology/archetypes/sections/navigation.yaml +20 -0
  110. package/src/ontology/archetypes/sections/notausgang-block.yaml +41 -0
  111. package/src/ontology/archetypes/sections/open-source-registry.yaml +26 -0
  112. package/src/ontology/archetypes/sections/ownership-block.yaml +57 -0
  113. package/src/ontology/archetypes/sections/people.yaml +48 -0
  114. package/src/ontology/archetypes/sections/price-card.yaml +50 -0
  115. package/src/ontology/archetypes/sections/problem.yaml +23 -0
  116. package/src/ontology/archetypes/sections/send-message.yaml +63 -0
  117. package/src/ontology/archetypes/sections/service-metadata-block.yaml +40 -0
  118. package/src/ontology/archetypes/sections/social-proof.yaml +27 -0
  119. package/src/ontology/archetypes/sections/transparency.yaml +32 -0
  120. package/src/ontology/archetypes/sections/trust-strip.yaml +42 -0
  121. package/src/ontology/archetypes/sections/video-section.yaml +27 -0
  122. package/src/ontology/archetypes/sections/women.yaml +29 -0
  123. package/src/ontology/biome-token-projection.ts +229 -0
  124. package/src/ontology/biomes/check-concrete-blueprint.yaml +118 -0
  125. package/src/ontology/biomes/handwerk-material-warm.yaml +135 -0
  126. package/src/ontology/biomes/nonprofit-trust.yaml +123 -0
  127. package/src/ontology/blueprints/offer.yaml +39 -0
  128. package/src/ontology/blueprints/prompts/local-market-signal.md +13 -0
  129. package/src/ontology/blueprints/prompts/website-local-narrative.md +24 -0
  130. package/src/ontology/blueprints/ratgeber.yaml +62 -0
  131. package/src/ontology/blueprints/website-local.yaml +309 -0
  132. package/src/ontology/blueprints/website-service.yaml +84 -0
  133. package/src/ontology/capabilities/lead.submit.yaml +44 -0
  134. package/src/ontology/cosmic/index.ts +48 -0
  135. package/src/ontology/cosmic/moon-catalog.ts +173 -0
  136. package/src/ontology/cosmic/planet-catalog.ts +82 -0
  137. package/src/ontology/cosmic/star-catalog.ts +337 -0
  138. package/src/ontology/enums.ts +159 -0
  139. package/src/ontology/external-surfaces/index.ts +158 -0
  140. package/src/ontology/external-surfaces/jsonld-types.yaml +135 -0
  141. package/src/ontology/external-surfaces/sitemap-shape.yaml +6 -0
  142. package/src/ontology/external-surfaces/url-schema.yaml +95 -0
  143. package/src/ontology/growth/events/contact-email-click.yaml +21 -0
  144. package/src/ontology/growth/events/contact-form-submit.yaml +25 -0
  145. package/src/ontology/growth/events/contact-phone-click.yaml +21 -0
  146. package/src/ontology/growth/events/contact-route-click.yaml +21 -0
  147. package/src/ontology/growth/events/contact-submit.yaml +28 -0
  148. package/src/ontology/growth/events/contact-whatsapp-click.yaml +21 -0
  149. package/src/ontology/growth/events/cta-click.yaml +30 -0
  150. package/src/ontology/growth/events/donation-confirmed.yaml +32 -0
  151. package/src/ontology/growth/events/donation-form-start.yaml +21 -0
  152. package/src/ontology/growth/events/donation-form-submit.yaml +29 -0
  153. package/src/ontology/growth/events/donation-intent.yaml +29 -0
  154. package/src/ontology/growth/events/form-error.yaml +27 -0
  155. package/src/ontology/growth/events/form-start.yaml +21 -0
  156. package/src/ontology/growth/events/form-submit.yaml +21 -0
  157. package/src/ontology/growth/events/outbound-click.yaml +25 -0
  158. package/src/ontology/growth/events/page-view.yaml +24 -0
  159. package/src/ontology/growth/events/passport-view.yaml +28 -0
  160. package/src/ontology/growth/events/star-map-navigate.yaml +30 -0
  161. package/src/ontology/index.ts +165 -0
  162. package/src/ontology/manifest.ts +344 -0
  163. package/src/ontology/operations/index.ts +1 -0
  164. package/src/ontology/schemas/biome.ts +303 -0
  165. package/src/ontology/schemas/capability.ts +104 -0
  166. package/src/ontology/schemas/constellation.ts +114 -0
  167. package/src/ontology/schemas/dns-records.ts +53 -0
  168. package/src/ontology/schemas/index.ts +95 -0
  169. package/src/ontology/schemas/manifest-resolver.ts +123 -0
  170. package/src/ontology/schemas/page-entry.ts +213 -0
  171. package/src/ontology/schemas/section-archetype.ts +109 -0
  172. package/src/ontology/schemas/site-family.ts +98 -0
  173. package/src/ontology/schemas/system/growth.ts +80 -0
  174. package/src/ontology/schemas/system/integrations.ts +143 -0
  175. package/src/ontology/schemas/system/manifest.ts +492 -0
  176. package/src/ontology/schemas/system/page-output.ts +99 -0
  177. package/src/ontology/schemas/system/release.ts +58 -0
  178. package/src/ontology/schemas/system/text.ts +58 -0
  179. package/src/ontology/schemas/system.ts +53 -0
  180. package/src/ontology/shared-section-props/body-fragments.ts +182 -0
  181. package/src/ontology/shared-section-props/catalog.ts +195 -0
  182. package/src/ontology/shared-section-props/common.ts +178 -0
  183. package/src/ontology/shared-section-props/index.ts +34 -0
  184. package/src/ontology/shared-section-props/visual-header.ts +163 -0
  185. package/src/ontology/site-families/charity-donation-trust/cultural-rules.yaml +6 -0
  186. package/src/ontology/site-families/charity-donation-trust/family.yaml +44 -0
  187. package/src/ontology/site-families/charity-donation-trust/linguistic-rules.yaml +6 -0
  188. package/src/ontology/site-families/check-quality-operator/cultural-rules.yaml +6 -0
  189. package/src/ontology/site-families/check-quality-operator/family.yaml +40 -0
  190. package/src/ontology/site-families/check-quality-operator/linguistic-rules.yaml +6 -0
  191. package/src/ontology/site-families/handwerk-trust-engineering/cultural-rules.yaml +6 -0
  192. package/src/ontology/site-families/handwerk-trust-engineering/family.yaml +53 -0
  193. package/src/ontology/site-families/handwerk-trust-engineering/linguistic-rules.yaml +6 -0
  194. package/src/ontology/tests/catalogs.pbt.test.ts +89 -0
  195. package/src/ontology/tests/enums.test.ts +203 -0
  196. package/src/ontology/tests/sternsystem-owner.test.ts +63 -0
  197. package/src/ontology/vitest.config.ts +8 -0
  198. package/src/passport/dht-sign.test.ts +99 -0
  199. package/src/passport/dht-sign.ts +73 -0
  200. package/src/passport/identity-sign.test.ts +134 -0
  201. package/src/passport/identity-sign.ts +85 -0
  202. package/src/passport/index.ts +53 -0
  203. package/src/passport/key-rotate.ts +133 -0
  204. package/src/passport/schema.ts +198 -0
  205. package/src/passport/sign.ts +225 -0
  206. package/src/passport/tests/schema.pbt.test.ts +93 -0
  207. package/src/passport/tests/schema.test.ts +222 -0
  208. package/src/passport/vitest.config.ts +8 -0
  209. package/src/share/agent/api-catalog.ts +77 -0
  210. package/src/share/agent/capability.ts +68 -0
  211. package/src/share/agent/dns-aid.test.ts +74 -0
  212. package/src/share/agent/dns-aid.ts +53 -0
  213. package/src/share/agent/fleet-catalog.ts +149 -0
  214. package/src/share/agent/index.ts +29 -0
  215. package/src/share/agent/knowledge.ts +96 -0
  216. package/src/share/agent/manifest.ts +126 -0
  217. package/src/share/agent/mcp-card.ts +63 -0
  218. package/src/share/agent/omit-empty.ts +77 -0
  219. package/src/share/agent/openapi.ts +157 -0
  220. package/src/share/agent/proof.ts +61 -0
  221. package/src/share/attribution-display.ts +86 -0
  222. package/src/share/check-hints.ts +38 -0
  223. package/src/share/content/entity-id.ts +65 -0
  224. package/src/share/content/index.ts +16 -0
  225. package/src/share/content/merge.ts +86 -0
  226. package/src/share/content/resolve-field-path.ts +39 -0
  227. package/src/share/content/substitute-deep.ts +47 -0
  228. package/src/share/content-discipline/index.ts +14 -0
  229. package/src/share/content-discipline/parsers.ts +66 -0
  230. package/src/share/content-discipline/types.ts +118 -0
  231. package/src/share/content-reference.ts +333 -0
  232. package/src/share/counter-utils.ts +75 -0
  233. package/src/share/css-value-normalize.ts +48 -0
  234. package/src/share/dev-props-validator.ts +131 -0
  235. package/src/share/entitlement.ts +172 -0
  236. package/src/share/env.d.ts +73 -0
  237. package/src/share/feature-policy.ts +367 -0
  238. package/src/share/formula-eval.ts +364 -0
  239. package/src/share/fs/index.ts +96 -0
  240. package/src/share/i18n/localization.ts +57 -0
  241. package/src/share/image-provider.ts +314 -0
  242. package/src/share/index.ts +86 -0
  243. package/src/share/knowledge/claim.ts +129 -0
  244. package/src/share/knowledge/derivation.ts +55 -0
  245. package/src/share/knowledge/freshness.ts +127 -0
  246. package/src/share/knowledge/index.ts +23 -0
  247. package/src/share/knowledge/ledger.ts +222 -0
  248. package/src/share/knowledge/plan.ts +122 -0
  249. package/src/share/knowledge/source.ts +170 -0
  250. package/src/share/legal/translation-policy.ts +133 -0
  251. package/src/share/material-credits.ts +181 -0
  252. package/src/share/middleware/language-redirect.ts +49 -0
  253. package/src/share/offer-capacity.ts +149 -0
  254. package/src/share/onboarding-yaml/index.ts +162 -0
  255. package/src/share/page.ts +351 -0
  256. package/src/share/redirects.test.ts +62 -0
  257. package/src/share/redirects.ts +54 -0
  258. package/src/share/rfc0042-utils.ts +95 -0
  259. package/src/share/runtime-context.ts +70 -0
  260. package/src/share/schemas/claim-records.ts +69 -0
  261. package/src/share/schemas/claims.ts +150 -0
  262. package/src/share/schemas/effects.ts +212 -0
  263. package/src/share/schemas/features.ts +147 -0
  264. package/src/share/schemas/horizontal-align.ts +22 -0
  265. package/src/share/schemas/icon-color.ts +27 -0
  266. package/src/share/schemas/index.ts +43 -0
  267. package/src/share/schemas/live-photo.ts +53 -0
  268. package/src/share/schemas/material-credit.ts +292 -0
  269. package/src/share/schemas/media.ts +220 -0
  270. package/src/share/schemas/navigation.ts +74 -0
  271. package/src/share/schemas/page-base.ts +33 -0
  272. package/src/share/schemas/participant.ts +247 -0
  273. package/src/share/schemas/person.ts +24 -0
  274. package/src/share/schemas/print.ts +93 -0
  275. package/src/share/schemas/section-background.ts +106 -0
  276. package/src/share/schemas/section-body.ts +138 -0
  277. package/src/share/schemas/section-cards.ts +37 -0
  278. package/src/share/schemas/section-cta.ts +74 -0
  279. package/src/share/schemas/section-header.ts +77 -0
  280. package/src/share/schemas/section-image.ts +77 -0
  281. package/src/share/schemas/section-motion.ts +52 -0
  282. package/src/share/schemas/section-shell.ts +63 -0
  283. package/src/share/schemas/section-stats.ts +37 -0
  284. package/src/share/schemas/site-background.ts +78 -0
  285. package/src/share/schemas/standard-list-item.ts +38 -0
  286. package/src/share/scripts/external-links.ts +45 -0
  287. package/src/share/scripts/gsap-counter.ts +168 -0
  288. package/src/share/scripts/gsap-mountain-journey.ts +236 -0
  289. package/src/share/scripts/gsap-parallax.ts +50 -0
  290. package/src/share/scripts/gsap-reveal.ts +65 -0
  291. package/src/share/scripts/gsap-stagger.ts +54 -0
  292. package/src/share/scripts/index.ts +25 -0
  293. package/src/share/scripts/inline-number-animation.ts +120 -0
  294. package/src/share/scripts/lenis.ts +109 -0
  295. package/src/share/scripts/live-photos.ts +250 -0
  296. package/src/share/scripts/lordicon.ts +94 -0
  297. package/src/share/scripts/orchestrator.ts +138 -0
  298. package/src/share/scripts/scheduler.ts +53 -0
  299. package/src/share/scripts/video-player.ts +116 -0
  300. package/src/share/semantic/ai.ts +140 -0
  301. package/src/share/semantic/block-extraction.ts +52 -0
  302. package/src/share/semantic/block-extractors/index.ts +502 -0
  303. package/src/share/semantic/breadcrumbs.ts +120 -0
  304. package/src/share/semantic/build-page.ts +309 -0
  305. package/src/share/semantic/business-projection.ts +278 -0
  306. package/src/share/semantic/derived-prices-loader.ts +36 -0
  307. package/src/share/semantic/extract.ts +118 -0
  308. package/src/share/semantic/feed.ts +124 -0
  309. package/src/share/semantic/ids.ts +76 -0
  310. package/src/share/semantic/image-sitemap.ts +153 -0
  311. package/src/share/semantic/index.ts +36 -0
  312. package/src/share/semantic/jsonld/article.ts +47 -0
  313. package/src/share/semantic/jsonld/breadcrumb.ts +47 -0
  314. package/src/share/semantic/jsonld/collection-list.ts +30 -0
  315. package/src/share/semantic/jsonld/context.ts +46 -0
  316. package/src/share/semantic/jsonld/faq.ts +49 -0
  317. package/src/share/semantic/jsonld/initiative.ts +53 -0
  318. package/src/share/semantic/jsonld/organization.ts +101 -0
  319. package/src/share/semantic/jsonld/person.ts +71 -0
  320. package/src/share/semantic/jsonld/service.ts +80 -0
  321. package/src/share/semantic/jsonld/shared.ts +31 -0
  322. package/src/share/semantic/jsonld/types.ts +18 -0
  323. package/src/share/semantic/jsonld/webpage.ts +98 -0
  324. package/src/share/semantic/jsonld/website.ts +27 -0
  325. package/src/share/semantic/jsonld.ts +75 -0
  326. package/src/share/semantic/llms-policy.ts +74 -0
  327. package/src/share/semantic/llms.ts +394 -0
  328. package/src/share/semantic/markdown-hygiene.ts +68 -0
  329. package/src/share/semantic/markdown-twin-provenance.ts +242 -0
  330. package/src/share/semantic/models.ts +402 -0
  331. package/src/share/semantic/organization-profile.ts +160 -0
  332. package/src/share/semantic/output-projection.ts +131 -0
  333. package/src/share/semantic/page-builders/markdown-page.ts +84 -0
  334. package/src/share/semantic/page-markdown.ts +234 -0
  335. package/src/share/semantic/page-utils.ts +125 -0
  336. package/src/share/semantic/price-marker-resolver.ts +92 -0
  337. package/src/share/semantic/robots.ts +127 -0
  338. package/src/share/semantic/update-stamp.ts +136 -0
  339. package/src/share/shared-context.ts +177 -0
  340. package/src/share/string-utils.ts +19 -0
  341. package/src/share/tests/api-catalog.test.ts +97 -0
  342. package/src/share/tests/breadcrumbs.test.ts +126 -0
  343. package/src/share/tests/build-page-price-markers.test.ts +160 -0
  344. package/src/share/tests/capability.test.ts +107 -0
  345. package/src/share/tests/claim.test.ts +90 -0
  346. package/src/share/tests/content-ref-index.test.ts +328 -0
  347. package/src/share/tests/create-dev-props-validator.test.ts +38 -0
  348. package/src/share/tests/derivation.test.ts +39 -0
  349. package/src/share/tests/dev-props-validator.test.ts +88 -0
  350. package/src/share/tests/fleet-catalog.test.ts +134 -0
  351. package/src/share/tests/formula-eval.test.ts +619 -0
  352. package/src/share/tests/freshness.test.ts +60 -0
  353. package/src/share/tests/hero-section-numbering-parity.test.ts +51 -0
  354. package/src/share/tests/image-sitemap.test.ts +101 -0
  355. package/src/share/tests/jsonld-service.test.ts +282 -0
  356. package/src/share/tests/knowledge.test.ts +86 -0
  357. package/src/share/tests/ledger.test.ts +125 -0
  358. package/src/share/tests/llms-0789.test.ts +63 -0
  359. package/src/share/tests/manifest.test.ts +100 -0
  360. package/src/share/tests/markdown-twin-provenance.test.ts +108 -0
  361. package/src/share/tests/mcp-card.test.ts +57 -0
  362. package/src/share/tests/onboarding-yaml.test.ts +111 -0
  363. package/src/share/tests/ontology-role-by-cosmic-name.test.ts +28 -0
  364. package/src/share/tests/openapi.test.ts +116 -0
  365. package/src/share/tests/organization-jsonld.test.ts +74 -0
  366. package/src/share/tests/output-projection.test.ts +61 -0
  367. package/src/share/tests/plan.test.ts +97 -0
  368. package/src/share/tests/price-marker-resolver.test.ts +141 -0
  369. package/src/share/tests/proof.test.ts +72 -0
  370. package/src/share/tests/resolve-field-path.test.ts +52 -0
  371. package/src/share/tests/source.test.ts +81 -0
  372. package/src/share/tests/substitute-deep.test.ts +65 -0
  373. package/src/share/tests/text-normalize.pbt.test.ts +143 -0
  374. package/src/share/tests/text-normalize.test.ts +285 -0
  375. package/src/share/tests/twin-path.test.ts +43 -0
  376. package/src/share/text-normalize.ts +548 -0
  377. package/src/share/text-position.ts +19 -0
  378. package/src/share/types/hls-js-light.d.ts +16 -0
  379. package/src/share/visibility.ts +167 -0
  380. package/src/share/vitest.config.ts +8 -0
  381. package/src/share/wrap-inline-numbers.ts +139 -0
  382. package/src/surface/blueprint-schema.ts +314 -0
  383. package/src/surface/blueprint-types.ts +256 -0
  384. package/src/surface/blueprint.ts +300 -0
  385. package/src/surface/breaker.ts +57 -0
  386. package/src/surface/decision-composer.ts +156 -0
  387. package/src/surface/eligibility.ts +372 -0
  388. package/src/surface/evidence-records.ts +97 -0
  389. package/src/surface/fleet.ts +60 -0
  390. package/src/surface/geo.ts +170 -0
  391. package/src/surface/governance.ts +146 -0
  392. package/src/surface/index.ts +216 -0
  393. package/src/surface/io/index.ts +18 -0
  394. package/src/surface/io/surface-module-context-io.ts +60 -0
  395. package/src/surface/io/visibility-outcomes-io.ts +46 -0
  396. package/src/surface/module-context.ts +120 -0
  397. package/src/surface/substance.ts +161 -0
  398. package/src/surface/tests/eligibility.pbt.test.ts +137 -0
  399. package/src/surface/tests/eligibility.test.ts +302 -0
  400. package/src/surface/types.ts +289 -0
  401. package/src/surface/visibility.ts +57 -0
  402. package/src/surface/vitest.config.ts +8 -0
  403. package/tsconfig.json +17 -0
@@ -0,0 +1,242 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-0320: portable provenance frontmatter for generated Markdown twins.
5
+ Builds YAML frontmatter with canonical URL, language, lastModified, contentHash,
6
+ license, generator, and sourceKind. The contentHash is a deterministic sha256
7
+ over the normalized Markdown body (excluding frontmatter).
8
+ </purpose>
9
+ <non-goals>
10
+ <item>Do not hash the frontmatter — only the body is hashed.</item>
11
+ <item>Do not use build date or mtime for lastModified.</item>
12
+ </non-goals>
13
+ </MODULE_CONTRACT>
14
+ <CHANGE_SUMMARY>
15
+ <item>RFC-0320: initial implementation.</item>
16
+ <item>RFC-0377: extended provenance with MarkdownTwinSemanticMeta, derivation maps, and bumped schema to gogol.markdown-twin@2.</item>
17
+ <item>RFC-0602: allow null lastModified for person-slug twins without source-backed stamps.</item>
18
+ </CHANGE_SUMMARY>
19
+ */
20
+
21
+ import { createHash } from "node:crypto";
22
+ import type { SemanticPageType } from "./models.ts";
23
+
24
+ export interface MarkdownTwinSemanticMeta {
25
+ id: string;
26
+ route: string;
27
+ title: string;
28
+ type: SemanticPageType;
29
+ domain: string;
30
+ audience: string;
31
+ lang: string;
32
+ metaDescription: string;
33
+ priority: number;
34
+ tags: string[];
35
+ agentRoles?: string[];
36
+ visibility?: "public" | "internal" | "experimental";
37
+ }
38
+
39
+ export interface MarkdownTwinProvenance {
40
+ canonical: string;
41
+ language: string;
42
+ lastModified: string | null;
43
+ license: string;
44
+ generator: string;
45
+ sourceKind: string;
46
+ pageId?: string;
47
+ sourceInputs?: string[];
48
+ schema?: string;
49
+ semantic?: MarkdownTwinSemanticMeta;
50
+ }
51
+
52
+ export const AUDIENCE_BY_PAGE_TYPE: Record<SemanticPageType, string> = {
53
+ home: "general",
54
+ about: "general",
55
+ projects: "developer",
56
+ donationContact: "general",
57
+ openSource: "developer",
58
+ content: "general",
59
+ article: "general",
60
+ person: "general",
61
+ participant: "general",
62
+ legal: "business_owner",
63
+ collection: "general",
64
+ };
65
+
66
+ export const PRIORITY_BY_PAGE_TYPE: Record<SemanticPageType, number> = {
67
+ home: 1.0,
68
+ about: 0.6,
69
+ projects: 0.5,
70
+ donationContact: 0.3,
71
+ openSource: 0.4,
72
+ content: 0.7,
73
+ article: 0.8,
74
+ person: 0.3,
75
+ participant: 0.3,
76
+ legal: 0.5,
77
+ collection: 0.8,
78
+ };
79
+
80
+ export const DOMAIN_BY_PAGE_TYPE: Record<SemanticPageType, string> = {
81
+ home: "site",
82
+ about: "site",
83
+ projects: "projects",
84
+ donationContact: "contact",
85
+ openSource: "projects",
86
+ content: "content",
87
+ article: "content",
88
+ person: "team",
89
+ participant: "team",
90
+ legal: "legal",
91
+ collection: "content",
92
+ };
93
+
94
+ const DEFAULT_SCHEMA = "gogol.markdown-twin@2";
95
+
96
+ /**
97
+ * RFC-0320: Normalize body for hashing.
98
+ * - Line endings to LF
99
+ * - Trim exactly one trailing newline
100
+ */
101
+ function normalizeBody(body: string): string {
102
+ const lf = body.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
103
+ return `${lf.trimEnd()}\n`;
104
+ }
105
+
106
+ /**
107
+ * RFC-0320: Compute deterministic sha256 hash over normalized body bytes.
108
+ * Returns `sha256:<hex>`.
109
+ */
110
+ export function computeContentHash(body: string): string {
111
+ const normalized = normalizeBody(body);
112
+ const hash = createHash("sha256").update(normalized, "utf-8").digest("hex");
113
+ return `sha256:${hash}`;
114
+ }
115
+
116
+ /**
117
+ * RFC-0320: Build YAML frontmatter for a Markdown twin.
118
+ */
119
+ function buildYamlListField(name: string, items: string[]): string {
120
+ if (items.length === 0) {
121
+ return `${name}: []`;
122
+ }
123
+ const lines = items.map((item) => ` - "${item}"`).join("\n");
124
+ return `${name}:\n${lines}`;
125
+ }
126
+
127
+ export function buildMarkdownTwinFrontmatter(
128
+ provenance: MarkdownTwinProvenance,
129
+ contentHash: string,
130
+ ): string {
131
+ const fields: string[] = [
132
+ `canonical: "${provenance.canonical}"`,
133
+ `language: "${provenance.language}"`,
134
+ `lastModified: ${provenance.lastModified === null ? "null" : `"${provenance.lastModified}"`}`,
135
+ `contentHash: "${contentHash}"`,
136
+ `license: "${provenance.license}"`,
137
+ `generator: "${provenance.generator}"`,
138
+ `sourceKind: "${provenance.sourceKind}"`,
139
+ ];
140
+
141
+ if (provenance.pageId) {
142
+ fields.push(`pageId: "${provenance.pageId}"`);
143
+ }
144
+
145
+ if (provenance.sourceInputs && provenance.sourceInputs.length > 0) {
146
+ fields.push(buildYamlListField("sourceInputs", provenance.sourceInputs));
147
+ }
148
+
149
+ if (provenance.semantic) {
150
+ const s = provenance.semantic;
151
+ fields.push(`id: "${s.id}"`);
152
+ fields.push(`route: "${s.route}"`);
153
+ fields.push(`title: "${s.title}"`);
154
+ fields.push(`type: "${s.type}"`);
155
+ fields.push(`domain: "${s.domain}"`);
156
+ fields.push(`audience: "${s.audience}"`);
157
+ fields.push(`lang: "${s.lang}"`);
158
+ fields.push(`metaDescription: "${s.metaDescription}"`);
159
+ fields.push(`priority: ${s.priority}`);
160
+ fields.push(buildYamlListField("tags", s.tags));
161
+ if (s.agentRoles && s.agentRoles.length > 0) {
162
+ fields.push(buildYamlListField("agentRoles", s.agentRoles));
163
+ }
164
+ if (s.visibility) {
165
+ fields.push(`visibility: "${s.visibility}"`);
166
+ }
167
+ }
168
+
169
+ fields.push(`schema: "${provenance.schema ?? DEFAULT_SCHEMA}"`);
170
+
171
+ return `---\n${fields.join("\n")}\n---\n\n`;
172
+ }
173
+
174
+ /**
175
+ * RFC-0320: Build a complete Markdown twin with frontmatter + body.
176
+ * The contentHash is computed over the normalized body.
177
+ */
178
+ export function buildMarkdownTwin(body: string, provenance: MarkdownTwinProvenance): string {
179
+ const normalizedBody = normalizeBody(body);
180
+ const contentHash = computeContentHash(normalizedBody);
181
+ const frontmatter = buildMarkdownTwinFrontmatter(provenance, contentHash);
182
+ return `${frontmatter}${normalizedBody}`;
183
+ }
184
+
185
+ /**
186
+ * RFC-0320: Parse frontmatter from a Markdown twin document.
187
+ * Returns { frontmatter, body } or null if no frontmatter found.
188
+ */
189
+ export function parseMarkdownTwinFrontmatter(
190
+ content: string,
191
+ ): { frontmatter: Record<string, unknown>; body: string } | null {
192
+ if (!content.startsWith("---\n")) return null;
193
+ const endIdx = content.indexOf("\n---\n", 4);
194
+ if (endIdx === -1) return null;
195
+ const yamlBlock = content.slice(4, endIdx);
196
+ // buildMarkdownTwinFrontmatter() closes with "---\n\n" (a blank separator line before the
197
+ // body). Skipping only "\n---\n" leaves that blank line's newline as a stray leading
198
+ // character in `body`, which then hashes differently than the body that was actually
199
+ // written — every twin's contentHash mismatched on validate. Consume the separator too.
200
+ const body = content.slice(endIdx + 5).replace(/^\n/, "");
201
+
202
+ const frontmatter: Record<string, unknown> = {};
203
+ let _currentKey = "";
204
+ let currentList: string[] | null = null;
205
+
206
+ for (const line of yamlBlock.split("\n")) {
207
+ if (line.startsWith(" - ")) {
208
+ if (currentList) {
209
+ currentList.push(line.slice(4).replace(/^["']|["']$/g, ""));
210
+ }
211
+ continue;
212
+ }
213
+ const match = line.match(/^(\w+):\s*(.*)$/);
214
+ if (match) {
215
+ const [, key, value] = match;
216
+ if (value === "") {
217
+ _currentKey = key;
218
+ currentList = [];
219
+ frontmatter[key] = currentList;
220
+ } else {
221
+ _currentKey = "";
222
+ currentList = null;
223
+ const stripped = value.replace(/^["']|["']$/g, "");
224
+ frontmatter[key] = stripped === "null" ? null : stripped;
225
+ }
226
+ }
227
+ }
228
+
229
+ return { frontmatter, body };
230
+ }
231
+
232
+ /**
233
+ * RFC-0320: Verify that the contentHash in frontmatter matches the body.
234
+ */
235
+ export function verifyMarkdownTwinHash(content: string): boolean {
236
+ const parsed = parseMarkdownTwinFrontmatter(content);
237
+ if (!parsed) return false;
238
+ const declared = parsed.frontmatter.contentHash;
239
+ if (typeof declared !== "string") return false;
240
+ const actual = computeContentHash(parsed.body);
241
+ return declared === actual;
242
+ }
@@ -0,0 +1,402 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>Defines types for semantic data structures used throughout the Warpgogol ecosystem.</purpose>
4
+ <non-goals>
5
+ <item>Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.</item>
6
+ </non-goals>
7
+ </MODULE_CONTRACT>
8
+ <CHANGE_SUMMARY>
9
+ <item>RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.</item>
10
+ <item>RFC-0165/0167: SemanticImage.contentImage flag + PageOutputProjection.image (author-declared per-page content illustration, single source for image:image + top-precedence og:image).</item>
11
+ <item>RFC-0328: Added "legal" to the SemanticPageType closed enum.</item>
12
+ <item>RFC-0490: Added "collection" to the SemanticPageType closed enum.</item>
13
+ <item>RFC-0508: Added "participant" to the SemanticPageType closed enum.</item>
14
+ <item>RFC-0372: Unified SemanticBlock type replaces SemanticAnswerBlock + SemanticContentBlock; SemanticPageModel.blocks replaces answerBlocks/contentBlocks/bodyText.</item>
15
+ </CHANGE_SUMMARY>
16
+ */
17
+
18
+ // NOTE: This closed union is mirrored by `semanticPageTypeSchema` in
19
+ // `@warpgogol/werkstatt-shared/ontology/src/schemas/system.ts`. `share` owns the compile-time
20
+ // contract used by lightweight consumers; `ontology` owns the runtime Zod
21
+ // validator for `system.md`. They are kept in sync manually because deriving
22
+ // one from the other would create a circular dependency between the two
23
+ // packages.
24
+ export type SemanticPageType =
25
+ | "home"
26
+ | "about"
27
+ | "projects"
28
+ | "donationContact"
29
+ | "openSource"
30
+ | "content"
31
+ | "article"
32
+ | "person"
33
+ | "participant"
34
+ | "legal"
35
+ | "collection";
36
+
37
+ /** Runtime counterpart to the `SemanticPageType` closed union. Keep in sync manually. */
38
+ export const SEMANTIC_PAGE_TYPES: readonly SemanticPageType[] = [
39
+ "home",
40
+ "about",
41
+ "projects",
42
+ "donationContact",
43
+ "openSource",
44
+ "content",
45
+ "article",
46
+ "person",
47
+ "participant",
48
+ "legal",
49
+ "collection",
50
+ ];
51
+
52
+ export type SemanticBreadcrumb = {
53
+ name: string;
54
+ url: string;
55
+ };
56
+
57
+ /**
58
+ * RFC-0372: Unified semantic block — replaces the former SemanticAnswerBlock and SemanticContentBlock.
59
+ * Every block in a SemanticPageModel is represented by this single type, regardless of
60
+ * whether it was derived from prose parsing or frontmatter block extraction.
61
+ */
62
+ export type SemanticBlock = {
63
+ /** Stable id from frontmatter block.id (required) or slugified heading for prose-derived blocks. */
64
+ id: string;
65
+ /** Block type from frontmatter (e.g. "hero-decision-card", "markdown") or "prose" for prose-derived blocks. */
66
+ blockType?: string;
67
+ /** Section heading (H2 in markdown twin). Empty string for no-op blocks; rendering checks `if (block.heading)`. */
68
+ heading: string;
69
+ /** Lead / subheading text. Counts as substantive content for ART-DEPTH-03. */
70
+ summary?: string;
71
+ /** Free-form body text (prose paragraphs, descriptions). */
72
+ body?: string;
73
+ /** Bullet-list facts (from markdown answer blocks). */
74
+ facts?: string[];
75
+ /** Structured items (from block extractors: cards, comparison rows, etc.). */
76
+ items?: Array<{ title: string; description?: string }>;
77
+ /** Extractor metadata (absent for prose-derived blocks). */
78
+ extractedAt?: string;
79
+ extractorVersion?: string;
80
+ };
81
+
82
+ /* RFC-0142: per-page llms inclusion depth. */
83
+ export type SemanticLlmsDepth = "full" | "summary" | "index-only" | "exclude";
84
+
85
+ export type SemanticLlmsPolicy = {
86
+ depth: SemanticLlmsDepth;
87
+ sections?: { exclude?: string[] };
88
+ };
89
+
90
+ /* RFC-0143: per-page sitemap projection (resolved). */
91
+ export type SitemapProjection = {
92
+ include: boolean;
93
+ category: string;
94
+ lastmod?: string;
95
+ includeLastmod: boolean;
96
+ };
97
+
98
+ /* RFC-0165: resolved per-page robots/indexability directive. */
99
+ export type RobotsProjection = {
100
+ index: boolean;
101
+ follow: boolean;
102
+ };
103
+
104
+ /* RFC-0143: resolved per-page `output` projection container. */
105
+ export type PageOutputProjection = {
106
+ sitemap: SitemapProjection;
107
+ llms: SemanticLlmsPolicy;
108
+ /* RFC-0165: indexability — drives the robots meta tag and sitemap inclusion. */
109
+ robots: RobotsProjection;
110
+ /**
111
+ * RFC-0165/0167: author-declared per-page content illustration (absolute
112
+ * https url). This is the single CLI-knowable source for the image sitemap
113
+ * (`image:image`) and the highest-precedence source for `og:image`. When
114
+ * present it carries `contentImage: true`. Absent when the page has no
115
+ * author-declared illustration.
116
+ */
117
+ image?: SemanticImage;
118
+ };
119
+
120
+ /* RFC-0162: a resolved social/OG image (absolute https url + intrinsic size). */
121
+ export type SemanticImage = {
122
+ url: string;
123
+ width?: number;
124
+ height?: number;
125
+ alt?: string;
126
+ /**
127
+ * RFC-0165/0167: marks a genuine content illustration (author-declared or
128
+ * hero `leadImage`) as opposed to a synthetic fallback (RFC-0150 preview
129
+ * screenshot, business logo). Only `contentImage: true` images are eligible
130
+ * for the image sitemap (`image:image`); all images may serve `og:image`.
131
+ */
132
+ contentImage?: boolean;
133
+ };
134
+
135
+ /* RFC-0162: Open Graph `og:type` discriminator. Defaults to "website"; "article" set by RFC-0167. */
136
+ export type OgType = "website" | "article" | "profile";
137
+
138
+ export type SemanticPostalAddress = {
139
+ streetAddress?: string;
140
+ postalCode?: string;
141
+ addressLocality?: string;
142
+ addressCountry?: string;
143
+ };
144
+
145
+ export type SemanticPerson = {
146
+ name: string;
147
+ role?: string;
148
+ description?: string;
149
+ isDeceased?: boolean;
150
+ /* RFC-0200: governance/presentational affiliations (founder | board | team | patron | author). */
151
+ affiliations?: string[];
152
+ /* RFC-0200: lifespan → schema.org Person.birthDate / deathDate (ISO or year). */
153
+ birthDate?: string;
154
+ deathDate?: string;
155
+ /* RFC-0200: representative portrait (absolute https url) → Person.image. */
156
+ image?: string;
157
+ /* RFC-0200: social/profile URLs → Person.sameAs (entity grounding). */
158
+ sameAs?: string[];
159
+ /* RFC-0200: absolute URL of this person's profile page, when one is live. */
160
+ profileUrl?: string;
161
+ /* RFC-0512: city-level address for Person JSON-LD (consent-gated at emission). */
162
+ address?: { addressLocality: string; addressRegion?: string; addressCountry: string };
163
+ /* RFC-0512: professional expertise areas → Person.knowsAbout. */
164
+ knowsAbout?: string[];
165
+ /* RFC-0512: organization affiliation → Person.affiliation. */
166
+ affiliation?: { name: string; url?: string };
167
+ };
168
+
169
+ export type SemanticContactPoint = {
170
+ contactType: string;
171
+ email?: string;
172
+ };
173
+
174
+ export type SemanticDonationAccount = {
175
+ accountHolder?: string;
176
+ bankName?: string;
177
+ iban?: string;
178
+ bic?: string;
179
+ accountNumber?: string;
180
+ bankCode?: string;
181
+ };
182
+
183
+ export type SemanticInitiative = {
184
+ id: string;
185
+ name: string;
186
+ summary: string;
187
+ facts?: string[];
188
+ };
189
+
190
+ export type SemanticService = {
191
+ id: string;
192
+ name: string;
193
+ description?: string;
194
+ };
195
+
196
+ /* RFC-0147/RFC-0148: business offer projection (prices + written guarantees + growth modules + terms). */
197
+ export type SemanticGuarantee = {
198
+ id: string;
199
+ label: string;
200
+ detail?: string;
201
+ };
202
+
203
+ export type SemanticPrice = {
204
+ id: string;
205
+ label: string;
206
+ amount: string;
207
+ currency?: string;
208
+ };
209
+
210
+ export type SemanticGrowthModule = {
211
+ id: string;
212
+ label: string;
213
+ description?: string;
214
+ price?: string;
215
+ };
216
+
217
+ export type SemanticOfferCapacity = {
218
+ enabled: boolean;
219
+ timezone: string;
220
+ startsAt: string;
221
+ cadence: "monthly" | "fixed-days";
222
+ cadenceDays?: number;
223
+ slotRange: { min: number; max: number };
224
+ maxSlotsPerWave: number;
225
+ availabilityStatus: "unknown";
226
+ };
227
+
228
+ export type SemanticOffer = {
229
+ prices?: SemanticPrice[];
230
+ guarantees?: SemanticGuarantee[];
231
+ growthModules?: SemanticGrowthModule[];
232
+ capacity?: SemanticOfferCapacity;
233
+ changePrice?: string;
234
+ hourlyRate?: string;
235
+ billingDay?: string;
236
+ };
237
+
238
+ /* RFC-0148: business location projection (NAP + service area). */
239
+ export type SemanticLocation = {
240
+ locality?: string;
241
+ region?: string;
242
+ country?: string;
243
+ serviceArea?: string[];
244
+ };
245
+
246
+ /* RFC-0287: business web/domain identity projection (business/{lang}/web.md). */
247
+ export type SemanticWeb = {
248
+ primaryUrl?: string;
249
+ statusUrl?: string;
250
+ domains?: { primary?: string; german?: string };
251
+ };
252
+
253
+ export type SemanticFaqEntry = {
254
+ id: string;
255
+ question: string;
256
+ answer: string;
257
+ tags?: string[];
258
+ serviceSlug?: string;
259
+ };
260
+
261
+ export type SemanticOrganization = {
262
+ name: string;
263
+ legalName?: string;
264
+ description: string;
265
+ url: string;
266
+ foundingYear?: string;
267
+ email?: string;
268
+ registration?: string;
269
+ representative?: string;
270
+ address?: SemanticPostalAddress;
271
+ areaServed?: string[];
272
+ founders?: SemanticPerson[];
273
+ boardMembers?: SemanticPerson[];
274
+ contactPoints?: SemanticContactPoint[];
275
+ donationAccount?: SemanticDonationAccount;
276
+ /* RFC-0147/RFC-0148: projected business catalog (public-visibility schemas). */
277
+ offer?: SemanticOffer;
278
+ services?: SemanticService[];
279
+ location?: SemanticLocation;
280
+ sameAs?: string[];
281
+ /* RFC-0163: organization logo (absolute https url) → schema.org ImageObject. */
282
+ logo?: string;
283
+ /* RFC-0163: representative organization image (absolute https url). */
284
+ image?: string;
285
+ /* RFC-0148: public team members (distinct from governance founders/board). */
286
+ team?: SemanticPerson[];
287
+ /**
288
+ * RFC-0242: explicit schema.org @type override (e.g. `["Organization", "ProfessionalService"]`
289
+ * for a Bodenstation studio deployment). Defaults to `["Organization", "NGO"]` when absent.
290
+ */
291
+ schemaType?: string[];
292
+ };
293
+
294
+ export type SemanticPageModel = {
295
+ type: SemanticPageType;
296
+ lang: string;
297
+ defaultLanguage?: string;
298
+ url: string;
299
+ title: string;
300
+ description: string;
301
+ /** RFC-0377: optional audience override (falls back to SemanticPageType derivation map). */
302
+ audience?: string;
303
+ heading?: string;
304
+ lead?: string;
305
+ breadcrumbs: SemanticBreadcrumb[];
306
+ /** RFC-0372: unified block array — replaces answerBlocks, contentBlocks, and bodyText. */
307
+ blocks: SemanticBlock[];
308
+ organization: SemanticOrganization;
309
+ people?: SemanticPerson[];
310
+ initiatives?: SemanticInitiative[];
311
+ faqEntries?: SemanticFaqEntry[];
312
+ /**
313
+ * RFC-0143/RFC-0142: resolved per-page output projection. Set by the
314
+ * semantic loaders via resolvePageOutput(); read by the llms formatters.
315
+ * Always resolved (never undefined) once a model leaves the loader.
316
+ */
317
+ output?: PageOutputProjection;
318
+ /**
319
+ * RFC-0162: per-page social preview image (resolved from the RFC-0150
320
+ * preview pipeline, with a business-logo fallback). Consumed by <SocialMeta>
321
+ * for og:image / twitter:image and by RFC-0163 for primaryImageOfPage.
322
+ */
323
+ primaryImage?: SemanticImage;
324
+ /**
325
+ * RFC-0209: unresolved hero `leadImage` token ({src, alt}) carried from the
326
+ * framework-free page handler to the asset-aware render layer. Set only when
327
+ * the page declares a hero `leadImage` and no explicit `output.image`. The
328
+ * layout resolves it through the Image Provider Port and promotes it to
329
+ * `primaryImage` (ahead of the RFC-0150 preview-screenshot fallback). The
330
+ * page handler cannot resolve the token to a URL (Astro content-hashing /
331
+ * Image Provider Port run in the render layer), so it ships the raw token.
332
+ */
333
+ leadImageToken?: { src: string; alt: string };
334
+ /** RFC-0162: Open Graph type. Defaults to "website" when unset. */
335
+ ogType?: OgType;
336
+ /** RFC-0162: Open Graph locale in `xx_XX` form (from system.md i18n hreflang). */
337
+ ogLocale?: string;
338
+ /** RFC-0162: Open Graph alternate locales in `xx_XX` form (other supported languages). */
339
+ ogLocaleAlternates?: string[];
340
+ /* RFC-0167: article metadata — when present, the page emits an Article/BlogPosting node. */
341
+ datePublished?: string;
342
+ dateModified?: string;
343
+ author?: string;
344
+ keywords?: string[];
345
+ /**
346
+ * RFC-0506: author record reference for ratgeber depth-1 pages. When present,
347
+ * buildArticleNode emits a structured Person node with name and optional url
348
+ * instead of a plain string author.
349
+ */
350
+ authorRecord?: {
351
+ name: string;
352
+ contactUrl?: string;
353
+ };
354
+ /** RFC-0506: latest reviewedAt date from article frontmatter, used for dateModified computation. */
355
+ reviewedAt?: string;
356
+ /** RFC-0506: changelog entries from article frontmatter (RFC-0504), used for dateModified computation. */
357
+ changelog?: Array<{ date: string; summary: string; authorId: string }>;
358
+ /**
359
+ * RFC-0227: stable @id values for all material credit nodes that appear on this page.
360
+ * When set, the WebPage node emits associatedMedia references so search engines can link
361
+ * disclosed credits to the page entity. Populated by page templates that load credit records.
362
+ */
363
+ materialCreditAtIds?: string[];
364
+ /**
365
+ * RFC-0490: collection items for "collection"-typed pages (e.g. industry links on a pillar hub).
366
+ * Each item is a { url, name } pair emitted as a ListItem in the JSON-LD ItemList node.
367
+ */
368
+ collectionItems?: Array<{ url: string; name: string }>;
369
+ /** RFC-0492: surface identity for depth-gated JSON-LD corrections. */
370
+ surfaceId?: string;
371
+ /** RFC-0492: surface depth for depth-gated JSON-LD corrections. */
372
+ depth?: number;
373
+ /**
374
+ * RFC-0492/RFC-0498: industry-specific Service node metadata for surface pages where Service is required.
375
+ * When present, `buildJsonLd` emits a single industry Service node instead of the
376
+ * organization-level Service nodes. Covers website-local depth-1, website-service depth-1,
377
+ * and website-local depth-5.
378
+ */
379
+ industryService?: {
380
+ serviceType: string;
381
+ audience?: string;
382
+ description?: string;
383
+ areaServed?: string;
384
+ };
385
+ /**
386
+ * RFC-0512: extra JSON-LD nodes injected into the @graph for team profile pages.
387
+ * AI-agent profile pages inject a SoftwareApplication node; the team hub injects
388
+ * a CollectionPage node with hasPart. Human profile pages do not need this —
389
+ * the extended Person node is already emitted by buildPersonNode.
390
+ */
391
+ extraGraphNodes?: import("./jsonld/types.ts").JsonLdNode[];
392
+ };
393
+
394
+ export type SemanticSiteModel = {
395
+ baseUrl: string;
396
+ lang: string;
397
+ defaultLanguage?: string;
398
+ organization: SemanticOrganization;
399
+ pages: SemanticPageModel[];
400
+ /** RFC-0789: agent block from system.md, populated by the semantic loader. */
401
+ agent?: { enabled?: boolean };
402
+ };