@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,163 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>Section visual and header JSON Schema fragments for RFC-0101/RFC-0102: visual sub-schemas and header sub-schemas applied at section root.</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-0303 Phase 3: extracted from shared-section-props/index.ts as part of the domain split.</item>
10
+ </CHANGE_SUMMARY>
11
+ */
12
+
13
+ import { EFFECT_STACK_ITEM_SCHEMA, ALIGN_ENUM, type JsonSchemaFragment } from "./common.ts";
14
+
15
+ /** RFC-0101 — section visual contract (background / effects / density / tone / containerVariant / motion). */
16
+ export const SECTION_VISUAL_FRAGMENT: JsonSchemaFragment = {
17
+ properties: {
18
+ background: {
19
+ oneOf: [
20
+ {
21
+ type: "object",
22
+ additionalProperties: false,
23
+ required: ["kind"],
24
+ properties: {
25
+ kind: { const: "color" },
26
+ color: { type: "string", minLength: 1 },
27
+ },
28
+ },
29
+ {
30
+ type: "object",
31
+ additionalProperties: false,
32
+ required: ["kind", "imageName"],
33
+ properties: {
34
+ kind: { const: "image" },
35
+ imageName: { type: "string", minLength: 1 },
36
+ fit: { enum: ["cover", "tile", "stretch-width", "stretch-height"] },
37
+ quality: { enum: ["low", "mid", "high", "max"] },
38
+ tintOpacity: { type: "number", minimum: 0, maximum: 1 },
39
+ },
40
+ },
41
+ {
42
+ type: "object",
43
+ additionalProperties: false,
44
+ required: ["kind", "texture"],
45
+ properties: {
46
+ kind: { const: "texture" },
47
+ texture: { type: "string", minLength: 1 },
48
+ },
49
+ },
50
+ {
51
+ type: "object",
52
+ additionalProperties: false,
53
+ required: ["kind"],
54
+ properties: { kind: { const: "transparent" } },
55
+ },
56
+ {
57
+ type: "object",
58
+ additionalProperties: false,
59
+ required: ["kind", "direction"],
60
+ properties: {
61
+ kind: { const: "fade" },
62
+ direction: { enum: ["vertical", "horizontal"] },
63
+ from: { type: "string", minLength: 1 },
64
+ to: { type: "string", minLength: 1 },
65
+ startOpacity: { type: "number", minimum: 0, maximum: 1 },
66
+ endOpacity: { type: "number", minimum: 0, maximum: 1 },
67
+ inset: { type: "number", minimum: 0, maximum: 0.5 },
68
+ noStartFade: { type: "boolean" },
69
+ noEndFade: { type: "boolean" },
70
+ },
71
+ },
72
+ ],
73
+ },
74
+ effects: {
75
+ type: "array",
76
+ minItems: 1,
77
+ items: {
78
+ type: "object",
79
+ additionalProperties: false,
80
+ required: ["target", "stack"],
81
+ properties: {
82
+ target: { type: "string", minLength: 1 },
83
+ stack: {
84
+ type: "array",
85
+ minItems: 1,
86
+ items: EFFECT_STACK_ITEM_SCHEMA,
87
+ },
88
+ },
89
+ },
90
+ },
91
+ density: { enum: ["compact", "normal", "spacious"] },
92
+ tone: { enum: ["default", "warning", "success", "muted"] },
93
+ containerVariant: { enum: ["default", "narrow", "full"] },
94
+ motion: {
95
+ type: "object",
96
+ additionalProperties: false,
97
+ properties: {
98
+ reveal: {
99
+ type: "object",
100
+ additionalProperties: false,
101
+ properties: {
102
+ variant: { enum: ["fade", "fade-up", "fade-up-stagger"] },
103
+ once: { type: "boolean" },
104
+ threshold: { type: "number", minimum: 0, maximum: 1 },
105
+ },
106
+ },
107
+ parallax: {
108
+ type: "object",
109
+ additionalProperties: false,
110
+ properties: {
111
+ variant: { enum: ["subtle", "balanced", "dramatic"] },
112
+ speed: { type: "number", minimum: 0, maximum: 2 },
113
+ },
114
+ },
115
+ stagger: {
116
+ type: "object",
117
+ additionalProperties: false,
118
+ properties: {
119
+ delay: { type: "number", minimum: 0, maximum: 2 },
120
+ childSelector: { type: "string" },
121
+ },
122
+ },
123
+ off: { type: "boolean" },
124
+ },
125
+ },
126
+ },
127
+ };
128
+
129
+ /** RFC-0102 — section header (tone-segmented heading + optional subheading + alignment + level). */
130
+ export const SECTION_HEADER_FRAGMENT: JsonSchemaFragment = {
131
+ properties: {
132
+ header: {
133
+ type: "object",
134
+ additionalProperties: false,
135
+ required: ["heading"],
136
+ properties: {
137
+ heading: {
138
+ oneOf: [
139
+ { type: "string", minLength: 1 },
140
+ {
141
+ type: "array",
142
+ minItems: 1,
143
+ items: {
144
+ type: "object",
145
+ additionalProperties: false,
146
+ required: ["text"],
147
+ properties: {
148
+ text: { type: "string", minLength: 1 },
149
+ tone: { enum: ["default", "primary", "accent", "muted", "inverse"] },
150
+ },
151
+ },
152
+ },
153
+ ],
154
+ },
155
+ eyebrow: { type: "string", minLength: 1 },
156
+ subheading: { type: "string", minLength: 1 },
157
+ align: ALIGN_ENUM,
158
+ level: { enum: [1, 2] },
159
+ hideSectionNumber: { type: "boolean" },
160
+ },
161
+ },
162
+ },
163
+ };
@@ -0,0 +1,6 @@
1
+ family: charity-donation-trust
2
+ version: 1.0.0
3
+ rules:
4
+ - Respect beneficiary dignity; avoid savior framing.
5
+ - Prefer concrete local context over abstract global heroics.
6
+ - Do not imply moral failure if the visitor does not donate.
@@ -0,0 +1,44 @@
1
+ id: charity-donation-trust
2
+ displayName: Charity · Donation trust
3
+ version: 1.0.0
4
+ description: |
5
+ Donation-first trust system for mission-driven nonprofits. Emphasizes mission clarity,
6
+ impact proof, transparent fund allocation, and a single primary ask.
7
+
8
+ detection:
9
+ signals:
10
+ archetypePrimary: donation-funnel
11
+ audienceAny: [donors, supporters, volunteers]
12
+ conversionPrimary: donation-intent
13
+ materialMentionsAny: [donation, transparency, recurring-support]
14
+ threshold: 0.7
15
+
16
+ recipe:
17
+ candidateBiomes:
18
+ - nonprofit-trust
19
+ candidateConstellations:
20
+ - nonprofit-donation-funnel
21
+ requiredSectionArchetypes:
22
+ # Remapped 2026-05-29 from placeholder names to the existing archetype YAMLs
23
+ # under packages/ontology/archetypes/sections/ (see RFC-0131).
24
+ - hero
25
+ - impact
26
+ - donation-use
27
+ - final-cta
28
+ conversionGoals:
29
+ primary:
30
+ id: donation-confirmation
31
+ eventName: donation-confirmed
32
+ secondary:
33
+ - id: donation-intent
34
+ eventName: donation-intent
35
+ - id: contact-submitted
36
+ eventName: contact-submit
37
+ auditThresholds:
38
+ transparencyVisible: required
39
+ impactProofVisible: required
40
+ singlePrimaryAsk: required
41
+ testimonialPresent: warn
42
+ agentReadinessBaseline:
43
+ maxBytesToCta: 4096
44
+ requireStructuredData: [Organization, FAQPage]
@@ -0,0 +1,6 @@
1
+ family: charity-donation-trust
2
+ version: 1.0.0
3
+ rules:
4
+ - Use plain-language fundraising copy.
5
+ - Prefer short declarative sentences near CTAs.
6
+ - Ban unverifiable absolutes such as "guaranteed impact".
@@ -0,0 +1,6 @@
1
+ family: check-quality-operator
2
+ version: 1.0.0
3
+ rules:
4
+ - "URL-first framing: the visitor brings a URL, not a business problem."
5
+ - Show what the check covers before asking for action.
6
+ - "Reports must be concrete and actionable, not vanity scores."
@@ -0,0 +1,40 @@
1
+ id: check-quality-operator
2
+ displayName: Check · Quality-operator
3
+ version: 1.0.0
4
+ description: |
5
+ Trust system for URL-first website-quality operators. The visitor arrives
6
+ with a URL, understands what the check covers, and runs or requests a
7
+ concrete quality audit with an actionable report. No Handwerk conversion
8
+ funnel, no donation ask — the primary action is "run the check".
9
+
10
+ detection:
11
+ signals:
12
+ archetypePrimary: quality-audit-tool
13
+ audienceAny: [webmasters, operators, agencies]
14
+ conversionPrimary: check-initiated
15
+ materialMentionsAny: [url-check, quality-report, action-pack, audit]
16
+ threshold: 0.7
17
+
18
+ recipe:
19
+ candidateBiomes:
20
+ - check-concrete-blueprint
21
+ candidateConstellations:
22
+ - check-quality-landing
23
+ requiredSectionArchetypes:
24
+ - hero
25
+ conversionGoals:
26
+ primary:
27
+ id: check-initiated
28
+ eventName: check-started
29
+ secondary:
30
+ - id: report-downloaded
31
+ eventName: report-downloaded
32
+ - id: faq-engagement
33
+ eventName: faq-question-opened
34
+ auditThresholds:
35
+ urlFirstFraming: required
36
+ actionPackVisible: required
37
+ testimonialPresent: forbidden
38
+ agentReadinessBaseline:
39
+ maxBytesToCta: 4096
40
+ requireStructuredData: [Organization, FAQPage]
@@ -0,0 +1,6 @@
1
+ family: check-quality-operator
2
+ version: 1.0.0
3
+ rules:
4
+ - Prefer precise technical German over marketing language.
5
+ - Ban vague quality claims without evidence.
6
+ - Use direct, operational phrasing near CTAs.
@@ -0,0 +1,6 @@
1
+ family: handwerk-trust-engineering
2
+ version: 1.0.0
3
+ rules:
4
+ - Respect German Handwerk norms: practical proof beats visionary abstraction.
5
+ - Do not use startup-style disruption language.
6
+ - Make ownership, exit terms, and responsibilities explicit.
@@ -0,0 +1,53 @@
1
+ id: handwerk-trust-engineering
2
+ displayName: Handwerk · Trust-engineering
3
+ version: 1.0.0
4
+ description: |
5
+ B2B trust system for small German Handwerk businesses. Founder-led,
6
+ written-conditions-first, vendor-lock-in-averse. Conversion is a written
7
+ inquiry; lead-count and ROI promises are forbidden.
8
+
9
+ detection:
10
+ signals:
11
+ archetypePrimary: b2b-trust-system
12
+ audienceAny: [handwerker, maler-lackierer, kleinunternehmen]
13
+ conversionPrimary: qualified-project-inquiry
14
+ materialMentionsAny: [notausgang, vendor-lock-in, controlled-responsibility]
15
+ threshold: 0.7
16
+
17
+ recipe:
18
+ candidateBiomes:
19
+ - handwerk-material-warm
20
+ candidateConstellations:
21
+ - handwerk-trust-funnel
22
+ requiredSectionArchetypes:
23
+ - hero-decision-card
24
+ - video-section
25
+ - trust-strip
26
+ - comparison-cards
27
+ - audience-cards
28
+ - ownership-block
29
+ - notausgang-block
30
+ - controlled-responsibility-block
31
+ - price-card
32
+ - people
33
+ - faq-list
34
+ - final-cta
35
+ conversionGoals:
36
+ primary:
37
+ id: qualified-inquiry
38
+ eventName: inquiry-submitted
39
+ secondary:
40
+ - id: faq-engagement
41
+ eventName: faq-question-opened
42
+ - id: price-page-read
43
+ eventName: scroll-depth-80
44
+ auditThresholds:
45
+ forbiddenROIPromise: error
46
+ forbiddenLeadCountGuarantee: error
47
+ notausgangVisible: required
48
+ priceVisible: required
49
+ founderIdentified: required
50
+ testimonialPresent: forbidden
51
+ agentReadinessBaseline:
52
+ maxBytesToCta: 4096
53
+ requireStructuredData: [Organization, FAQPage, Service]
@@ -0,0 +1,6 @@
1
+ family: handwerk-trust-engineering
2
+ version: 1.0.0
3
+ rules:
4
+ - Prefer concrete business German over slogan language.
5
+ - Ban ROI guarantees and lead-count promises.
6
+ - Use direct, written-condition phrasing near CTAs and pricing.
@@ -0,0 +1,89 @@
1
+ import { test, expect } from "vitest";
2
+ import fc from "fast-check";
3
+ import { StarCatalog, starNameSchema } from "../cosmic/star-catalog.ts";
4
+ import { PlanetCatalog, planetNameSchema } from "../cosmic/planet-catalog.ts";
5
+ import { MoonCatalog, moonNameSchema } from "../cosmic/moon-catalog.ts";
6
+ import { cosmicNameSchema } from "../cosmic/index.ts";
7
+ import {
8
+ LayerValues,
9
+ layerSchema,
10
+ ComponentRoleValues,
11
+ componentRoleSchema,
12
+ IndustryValues,
13
+ industrySchema,
14
+ } from "../enums.ts";
15
+
16
+ test("PBT: any star from the catalog passes starNameSchema", () => {
17
+ fc.assert(
18
+ fc.property(fc.constantFrom(...StarCatalog), (star) => {
19
+ expect(starNameSchema.safeParse(star).success).toBe(true);
20
+ }),
21
+ );
22
+ });
23
+
24
+ test("PBT: any planet from the catalog passes planetNameSchema", () => {
25
+ fc.assert(
26
+ fc.property(fc.constantFrom(...PlanetCatalog), (planet) => {
27
+ expect(planetNameSchema.safeParse(planet).success).toBe(true);
28
+ }),
29
+ );
30
+ });
31
+
32
+ test("PBT: any moon from the catalog passes moonNameSchema", () => {
33
+ fc.assert(
34
+ fc.property(fc.constantFrom(...MoonCatalog), (moon) => {
35
+ expect(moonNameSchema.safeParse(moon).success).toBe(true);
36
+ }),
37
+ );
38
+ });
39
+
40
+ test("PBT: any cosmic name passes cosmicNameSchema", () => {
41
+ const allCosmic = [...StarCatalog, ...PlanetCatalog, ...MoonCatalog];
42
+ fc.assert(
43
+ fc.property(fc.constantFrom(...allCosmic), (name) => {
44
+ expect(cosmicNameSchema.safeParse(name).success).toBe(true);
45
+ }),
46
+ );
47
+ });
48
+
49
+ test("PBT: any Layer value passes layerSchema", () => {
50
+ fc.assert(
51
+ fc.property(fc.constantFrom(...LayerValues), (v) => {
52
+ expect(layerSchema.safeParse(v).success).toBe(true);
53
+ }),
54
+ );
55
+ });
56
+
57
+ test("PBT: any ComponentRole value passes componentRoleSchema", () => {
58
+ fc.assert(
59
+ fc.property(fc.constantFrom(...ComponentRoleValues), (v) => {
60
+ expect(componentRoleSchema.safeParse(v).success).toBe(true);
61
+ }),
62
+ );
63
+ });
64
+
65
+ test("PBT: any Industry value passes industrySchema", () => {
66
+ fc.assert(
67
+ fc.property(fc.constantFrom(...IndustryValues), (v) => {
68
+ expect(industrySchema.safeParse(v).success).toBe(true);
69
+ }),
70
+ );
71
+ });
72
+
73
+ test("PBT: random non-cosmic strings fail cosmicNameSchema", () => {
74
+ fc.assert(
75
+ fc.property(
76
+ fc
77
+ .string({ minLength: 1 })
78
+ .filter(
79
+ (s) =>
80
+ !StarCatalog.includes(s as never) &&
81
+ !PlanetCatalog.includes(s as never) &&
82
+ !MoonCatalog.includes(s as never),
83
+ ),
84
+ (s) => {
85
+ expect(cosmicNameSchema.safeParse(s).success).toBe(false);
86
+ },
87
+ ),
88
+ );
89
+ });
@@ -0,0 +1,203 @@
1
+ import { test, expect, describe } from "vitest";
2
+ import {
3
+ LayerValues,
4
+ layerSchema,
5
+ ComponentRoleValues,
6
+ componentRoleSchema,
7
+ IndustryValues,
8
+ industrySchema,
9
+ IndustryLabels,
10
+ } from "../enums.ts";
11
+ import { StarCatalog, starNameSchema } from "../cosmic/star-catalog.ts";
12
+ import { PlanetCatalog, planetNameSchema } from "../cosmic/planet-catalog.ts";
13
+ import { MoonCatalog, moonNameSchema } from "../cosmic/moon-catalog.ts";
14
+ import { cosmicNameSchema } from "../cosmic/index.ts";
15
+
16
+ describe("Layer enum", () => {
17
+ test("has exactly 3 values", () => {
18
+ expect(LayerValues).toHaveLength(3);
19
+ });
20
+
21
+ test("contains page, section, component", () => {
22
+ expect([...LayerValues].sort()).toEqual(["component", "page", "section"]);
23
+ });
24
+
25
+ test("schema accepts valid values", () => {
26
+ expect(layerSchema.safeParse("page").success).toBe(true);
27
+ expect(layerSchema.safeParse("section").success).toBe(true);
28
+ expect(layerSchema.safeParse("component").success).toBe(true);
29
+ });
30
+
31
+ test("schema rejects invalid values", () => {
32
+ expect(layerSchema.safeParse("layout").success).toBe(false);
33
+ expect(layerSchema.safeParse("").success).toBe(false);
34
+ });
35
+ });
36
+
37
+ describe("ComponentRole enum", () => {
38
+ test("contains section framework primitives", () => {
39
+ expect(ComponentRoleValues).toContain("section-shell");
40
+ expect(ComponentRoleValues).toContain("section-header");
41
+ expect(ComponentRoleValues).toContain("section-body");
42
+ expect(ComponentRoleValues).toContain("section-cta");
43
+ expect(ComponentRoleValues).toContain("section-image");
44
+ expect(ComponentRoleValues).toContain("site-background");
45
+ });
46
+
47
+ test("schema accepts valid values", () => {
48
+ expect(componentRoleSchema.safeParse("header").success).toBe(true);
49
+ expect(componentRoleSchema.safeParse("section-shell").success).toBe(true);
50
+ });
51
+
52
+ test("schema rejects invalid values", () => {
53
+ expect(componentRoleSchema.safeParse("unknown-role").success).toBe(false);
54
+ });
55
+
56
+ test("has no duplicate values", () => {
57
+ const seen = new Set<string>();
58
+ for (const v of ComponentRoleValues) {
59
+ expect(seen.has(v)).toBe(false);
60
+ seen.add(v);
61
+ }
62
+ });
63
+ });
64
+
65
+ describe("Industry enum", () => {
66
+ test("has exactly 6 values", () => {
67
+ expect(IndustryValues).toHaveLength(6);
68
+ });
69
+
70
+ test("schema accepts valid values", () => {
71
+ expect(industrySchema.safeParse("trades-and-construction").success).toBe(true);
72
+ expect(industrySchema.safeParse("non-profit").success).toBe(true);
73
+ });
74
+
75
+ test("schema rejects invalid values", () => {
76
+ expect(industrySchema.safeParse("technology").success).toBe(false);
77
+ });
78
+
79
+ test("IndustryLabels covers all Industry values", () => {
80
+ for (const v of IndustryValues) {
81
+ expect(IndustryLabels[v]).toBeDefined();
82
+ expect(IndustryLabels[v].length).toBeGreaterThan(0);
83
+ }
84
+ });
85
+ });
86
+
87
+ describe("StarCatalog", () => {
88
+ test("is non-empty", () => {
89
+ expect(StarCatalog.length).toBeGreaterThan(100);
90
+ });
91
+
92
+ test("contains known stars", () => {
93
+ expect(StarCatalog).toContain("Vega");
94
+ expect(StarCatalog).toContain("Sirius");
95
+ expect(StarCatalog).toContain("Polaris");
96
+ });
97
+
98
+ test("has no duplicate entries", () => {
99
+ const seen = new Set<string>();
100
+ for (const s of StarCatalog) {
101
+ expect(seen.has(s)).toBe(false);
102
+ seen.add(s);
103
+ }
104
+ });
105
+
106
+ test("schema accepts valid star names", () => {
107
+ expect(starNameSchema.safeParse("Vega").success).toBe(true);
108
+ });
109
+
110
+ test("schema rejects invalid star names", () => {
111
+ expect(starNameSchema.safeParse("NotAStar").success).toBe(false);
112
+ });
113
+ });
114
+
115
+ describe("PlanetCatalog", () => {
116
+ test("contains known planets", () => {
117
+ expect(PlanetCatalog).toContain("Europa");
118
+ expect(PlanetCatalog).toContain("Io");
119
+ expect(PlanetCatalog).toContain("Titan");
120
+ expect(PlanetCatalog).toContain("Ceres");
121
+ });
122
+
123
+ test("has no duplicate entries", () => {
124
+ const seen = new Set<string>();
125
+ for (const p of PlanetCatalog) {
126
+ expect(seen.has(p)).toBe(false);
127
+ seen.add(p);
128
+ }
129
+ });
130
+
131
+ test("schema accepts valid planet names", () => {
132
+ expect(planetNameSchema.safeParse("Europa").success).toBe(true);
133
+ });
134
+
135
+ test("schema rejects invalid planet names", () => {
136
+ expect(planetNameSchema.safeParse("Earth").success).toBe(false);
137
+ });
138
+ });
139
+
140
+ describe("MoonCatalog", () => {
141
+ test("contains known moons", () => {
142
+ expect(MoonCatalog).toContain("Oberon");
143
+ expect(MoonCatalog).toContain("Triton");
144
+ expect(MoonCatalog).toContain("Charon");
145
+ });
146
+
147
+ test("contains passport-reserved moons", () => {
148
+ const reserved = ["Methone", "Despina", "Klarissa", "Bianca", "Adrastea"];
149
+ for (const r of reserved) {
150
+ expect(MoonCatalog).toContain(r);
151
+ }
152
+ });
153
+
154
+ test("has no duplicate entries", () => {
155
+ const seen = new Set<string>();
156
+ for (const m of MoonCatalog) {
157
+ expect(seen.has(m)).toBe(false);
158
+ seen.add(m);
159
+ }
160
+ });
161
+
162
+ test("schema accepts valid moon names", () => {
163
+ expect(moonNameSchema.safeParse("Oberon").success).toBe(true);
164
+ });
165
+
166
+ test("schema rejects invalid moon names", () => {
167
+ expect(moonNameSchema.safeParse("Luna").success).toBe(false);
168
+ });
169
+ });
170
+
171
+ describe("Cross-catalog identity", () => {
172
+ test("Planet and Moon catalogs are mutually disjoint", () => {
173
+ const planetSet = new Set<string>(PlanetCatalog);
174
+ for (const m of MoonCatalog) {
175
+ expect(planetSet.has(m)).toBe(false);
176
+ }
177
+ });
178
+
179
+ test("Star and Moon catalogs are mutually disjoint", () => {
180
+ const starSet = new Set<string>(StarCatalog);
181
+ for (const m of MoonCatalog) {
182
+ expect(starSet.has(m)).toBe(false);
183
+ }
184
+ });
185
+ });
186
+
187
+ describe("cosmicNameSchema", () => {
188
+ test("accepts star names", () => {
189
+ expect(cosmicNameSchema.safeParse("Vega").success).toBe(true);
190
+ });
191
+
192
+ test("accepts planet names", () => {
193
+ expect(cosmicNameSchema.safeParse("Europa").success).toBe(true);
194
+ });
195
+
196
+ test("accepts moon names", () => {
197
+ expect(cosmicNameSchema.safeParse("Oberon").success).toBe(true);
198
+ });
199
+
200
+ test("rejects non-cosmic strings", () => {
201
+ expect(cosmicNameSchema.safeParse("NotInAnyCatalog").success).toBe(false);
202
+ });
203
+ });