@warpgogol/werkstatt-shared 0.14.0 → 0.15.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 (437) hide show
  1. package/README.md +31 -13
  2. package/README.uk.md +25 -15
  3. package/package.json +519 -762
  4. package/src/{share/agent → agent}/ard-catalog.ts +6 -1
  5. package/src/{share/agent → agent}/dns-aid.test.ts +2 -2
  6. package/src/{share/agent → agent}/manifest.ts +15 -1
  7. package/src/{share/agent → agent}/search.ts +6 -1
  8. package/src/{share → agent}/tests/api-catalog.test.ts +2 -2
  9. package/src/{share → agent}/tests/ard-catalog.test.ts +2 -2
  10. package/src/{share → agent}/tests/capability.test.ts +1 -1
  11. package/src/{share → agent}/tests/fleet-catalog.test.ts +1 -1
  12. package/src/{share → agent}/tests/knowledge.test.ts +2 -2
  13. package/src/{share → agent}/tests/manifest.test.ts +1 -1
  14. package/src/{share → agent}/tests/mcp-card.test.ts +2 -2
  15. package/src/agent/tests/omit-empty.test.ts +33 -0
  16. package/src/{share → agent}/tests/openapi.test.ts +2 -2
  17. package/src/{share → agent}/tests/proof.test.ts +1 -1
  18. package/src/{share → attribution}/material-credits.ts +4 -4
  19. package/src/{share → checks}/check-hints.ts +6 -1
  20. package/src/checks/index.ts +4 -1
  21. package/src/checks/lib/astro-site-url.ts +6 -1
  22. package/src/checks/lib/i18n.ts +14 -0
  23. package/src/checks/result-helpers.ts +22 -5
  24. package/src/checks/tests/remediation-auto-populate.test.ts +83 -0
  25. package/src/{share → client-scripts}/counter-utils.ts +6 -2
  26. package/src/{share/scripts → client-scripts}/external-link-qr.ts +11 -16
  27. package/src/{share/scripts → client-scripts}/external-links.ts +12 -1
  28. package/src/{share/scripts → client-scripts}/gsap-counter.ts +8 -3
  29. package/src/client-scripts/index.ts +35 -0
  30. package/src/{share/scripts → client-scripts}/inline-number-animation.ts +1 -1
  31. package/src/{share/scripts → client-scripts}/lenis.ts +6 -1
  32. package/src/{share/scripts → client-scripts}/lordicon.ts +6 -1
  33. package/src/{share/scripts → client-scripts}/orchestrator.ts +10 -1
  34. package/src/{share/scripts → client-scripts}/scheduler.ts +6 -1
  35. package/src/client-scripts/scroll-spy.ts +106 -0
  36. package/src/client-scripts/tests/external-link-qr.test.ts +8 -0
  37. package/src/client-scripts/tests/external-links.test.ts +25 -0
  38. package/src/client-scripts/tests/gsap-counter.test.ts +8 -0
  39. package/src/client-scripts/tests/gsap-mountain-journey.test.ts +8 -0
  40. package/src/client-scripts/tests/gsap-parallax.test.ts +8 -0
  41. package/src/client-scripts/tests/gsap-reveal.test.ts +8 -0
  42. package/src/client-scripts/tests/gsap-stagger.test.ts +8 -0
  43. package/src/client-scripts/tests/inline-number-animation.test.ts +8 -0
  44. package/src/client-scripts/tests/lenis.test.ts +8 -0
  45. package/src/client-scripts/tests/live-photos.test.ts +8 -0
  46. package/src/client-scripts/tests/lordicon.test.ts +8 -0
  47. package/src/client-scripts/tests/orchestrator.test.ts +47 -0
  48. package/src/client-scripts/tests/scheduler.test.ts +23 -0
  49. package/src/client-scripts/tests/scroll-spy.test.ts +204 -0
  50. package/src/{share/scripts → client-scripts/tests}/video-player.test.ts +51 -31
  51. package/src/component/contracts.ts +206 -0
  52. package/src/component/index.ts +11 -0
  53. package/src/{share → content}/content-reference.ts +3 -3
  54. package/src/{share/content → content}/entity-id.ts +6 -3
  55. package/src/content/index.ts +3 -0
  56. package/src/{share/content → content}/merge.ts +6 -1
  57. package/src/content/system-manifest.test.ts +107 -0
  58. package/src/content/system-manifest.ts +12 -94
  59. package/src/{share → content}/tests/resolve-field-path.test.ts +1 -1
  60. package/src/{share → content}/tests/substitute-deep.test.ts +1 -1
  61. package/src/content-discipline/index.ts +19 -0
  62. package/src/{share/content-discipline → content-discipline}/parsers.ts +2 -2
  63. package/src/{share/env.d.ts → env.d.ts} +6 -3
  64. package/src/fingerprint/canonical-json.ts +731 -0
  65. package/src/fingerprint/index.ts +12 -0
  66. package/src/fingerprint/primitives.ts +72 -0
  67. package/src/{share/i18n → i18n}/localization.ts +6 -2
  68. package/src/integration/adapters.ts +10 -71
  69. package/src/integration/dispatch.ts +1 -1
  70. package/src/integration/funnel.ts +6 -1
  71. package/src/integration/index.ts +101 -4
  72. package/src/integration/lagebild-destination-adapter.ts +108 -0
  73. package/src/integration/lagebild-ingress.ts +7 -12
  74. package/src/integration/orchestration.ts +11 -10
  75. package/src/integration/tests/deliver-event.test.ts +1 -1
  76. package/src/integration/tests/dispatch.test.ts +4 -4
  77. package/src/integration/tests/hub-runtime.test.ts +22 -14
  78. package/src/integration/vitest.config.ts +8 -0
  79. package/src/kernel/desired-state.ts +227 -0
  80. package/src/kernel/diagnostic.ts +289 -0
  81. package/src/kernel/fs-atomic.ts +131 -0
  82. package/src/kernel/index.ts +15 -0
  83. package/src/kernel/tests/fs-atomic.test.ts +150 -0
  84. package/src/kernel/tests/workspace-io.test.ts +187 -0
  85. package/src/kernel/types.ts +459 -0
  86. package/src/kernel/workspace-io.ts +248 -0
  87. package/src/{share → knowledge}/tests/claim.test.ts +1 -1
  88. package/src/{share → knowledge}/tests/derivation.test.ts +1 -1
  89. package/src/{share → knowledge}/tests/freshness.test.ts +1 -1
  90. package/src/{share → knowledge}/tests/ledger.test.ts +1 -1
  91. package/src/{share → knowledge}/tests/plan.test.ts +1 -1
  92. package/src/{share → knowledge}/tests/source.test.ts +1 -1
  93. package/src/legal/index.ts +15 -0
  94. package/src/{share/middleware → middleware}/access-protection.ts +8 -8
  95. package/src/{share → node}/dev-props-validator.ts +6 -1
  96. package/src/{share → node}/import-scan.ts +23 -3
  97. package/src/{share → node}/semantic/derived-prices-loader.ts +4 -2
  98. package/src/{share → node}/semantic/markdown-twin-provenance.ts +1 -1
  99. package/src/node/tests/derived-prices-loader.test.ts +59 -0
  100. package/src/node/tests/markdown-twin-provenance.test.ts +152 -0
  101. package/src/observability/env-resolver.ts +6 -1
  102. package/src/observability/index.ts +6 -1
  103. package/src/observability/otlp-converter.ts +6 -1
  104. package/src/observability/otlp-transport.ts +6 -1
  105. package/src/observability/pusher.ts +6 -1
  106. package/src/observability/redact.ts +6 -1
  107. package/src/observability/typed-refs.ts +6 -2
  108. package/src/observability/vitest.config.ts +1 -0
  109. package/src/{share → offers}/formula-eval.ts +3 -3
  110. package/src/{share → offers}/tests/formula-eval.test.ts +2 -2
  111. package/src/onboarding/index.ts +1 -0
  112. package/src/{share → onboarding}/tests/onboarding-yaml.test.ts +1 -1
  113. package/src/ontology/archetype-registry.ts +6 -1
  114. package/src/ontology/archetypes/index.json +33 -1
  115. package/src/ontology/archetypes/index.yaml +27 -1
  116. package/src/ontology/archetypes/sections/entity-grid.yaml +46 -0
  117. package/src/ontology/archetypes/sections/exit-diagram.yaml +43 -0
  118. package/src/ontology/biome-token-projection.ts +6 -1
  119. package/src/ontology/cosmic/index.ts +6 -1
  120. package/src/ontology/cosmic/moon-catalog.ts +6 -1
  121. package/src/ontology/cosmic/planet-catalog.ts +6 -1
  122. package/src/ontology/cosmic/star-catalog.ts +6 -1
  123. package/src/ontology/enums.ts +6 -1
  124. package/src/ontology/external-surfaces/index.ts +1 -1
  125. package/src/ontology/index.ts +6 -2
  126. package/src/ontology/manifest.ts +26 -4
  127. package/src/ontology/operations/artifact-store.ts +45 -0
  128. package/src/ontology/operations/dht.ts +98 -0
  129. package/src/ontology/operations/handoff.ts +92 -0
  130. package/src/ontology/operations/index.ts +187 -1
  131. package/src/ontology/operations/leitstand.ts +99 -0
  132. package/src/ontology/operations/materialization.ts +90 -0
  133. package/src/ontology/operations/mission.ts +111 -0
  134. package/src/ontology/operations/naming-policy.ts +132 -0
  135. package/src/ontology/operations/notausgang.ts +64 -0
  136. package/src/ontology/operations/release.ts +121 -0
  137. package/src/ontology/operations/sternsystem.ts +192 -0
  138. package/src/ontology/operations/werkstatt.ts +48 -0
  139. package/src/ontology/schemas/biome.ts +7 -2
  140. package/src/ontology/schemas/capability.ts +1 -1
  141. package/src/ontology/schemas/constellation.ts +6 -1
  142. package/src/ontology/schemas/index.ts +6 -2
  143. package/src/ontology/schemas/manifest-resolver.ts +6 -1
  144. package/src/ontology/schemas/page-entry.ts +9 -5
  145. package/src/ontology/schemas/system/growth.ts +6 -1
  146. package/src/ontology/schemas/system/manifest.ts +40 -1
  147. package/src/ontology/schemas/system/page-output.ts +7 -6
  148. package/src/ontology/schemas/system/tests/growth.test.ts +22 -0
  149. package/src/ontology/schemas/system/tests/integrations.test.ts +12 -0
  150. package/src/ontology/schemas/system/tests/manifest.test.ts +22 -0
  151. package/src/ontology/schemas/system/tests/page-output.test.ts +13 -0
  152. package/src/ontology/schemas/system/tests/release.test.ts +22 -0
  153. package/src/ontology/schemas/system/tests/text.test.ts +18 -0
  154. package/src/ontology/schemas/system/tests/verification.test.ts +12 -0
  155. package/src/ontology/schemas/system/text.ts +15 -0
  156. package/src/ontology/schemas/system.ts +6 -2
  157. package/src/ontology/schemas/tests/biome.test.ts +19 -0
  158. package/src/ontology/schemas/tests/capability.test.ts +22 -0
  159. package/src/ontology/schemas/tests/constellation.test.ts +22 -0
  160. package/src/ontology/schemas/tests/dns-records.test.ts +13 -0
  161. package/src/ontology/schemas/tests/manifest-resolver.test.ts +13 -0
  162. package/src/ontology/schemas/tests/page-entry.test.ts +22 -0
  163. package/src/ontology/schemas/tests/section-archetype.test.ts +12 -0
  164. package/src/ontology/schemas/tests/site-family.test.ts +18 -0
  165. package/src/ontology/schemas/tests/system.test.ts +20 -0
  166. package/src/ontology/shared-section-props/body-fragments.ts +2 -0
  167. package/src/ontology/tests/sternsystem-owner.test.ts +1 -1
  168. package/src/ontology/vitest.config.ts +1 -0
  169. package/src/{share → page}/page.ts +13 -9
  170. package/src/{share → page}/tests/dev-props-validator.test.ts +1 -1
  171. package/src/{share → page}/tests/hero-section-numbering-parity.test.ts +1 -1
  172. package/src/passport/index.ts +6 -1
  173. package/src/passport/key-rotate.ts +10 -2
  174. package/src/passport/schema.ts +6 -1
  175. package/src/passport/sign.ts +8 -3
  176. package/src/passport/vitest.config.ts +1 -0
  177. package/src/pbt/index.test.ts +95 -0
  178. package/src/pbt/index.ts +251 -0
  179. package/src/plugin/plugin-contract.ts +1 -1
  180. package/src/{share → policy}/entitlement.ts +24 -4
  181. package/src/{share → policy}/feature-policy.ts +8 -3
  182. package/src/{share → policy}/visibility.ts +7 -2
  183. package/src/redirects/redirects.ts +117 -0
  184. package/src/{share → redirects/tests}/redirects.test.ts +1 -1
  185. package/src/remediation/remediation-catalog.ts +316 -0
  186. package/src/{share/routes → routes}/template-filter.ts +1 -1
  187. package/src/{share → runtime}/runtime-context.ts +7 -2
  188. package/src/{share → runtime}/shared-context.ts +1 -1
  189. package/src/{share/schemas → schemas}/claims.ts +2 -2
  190. package/src/{share/schemas → schemas}/effects.ts +6 -1
  191. package/src/{share/schemas → schemas}/features.ts +1 -1
  192. package/src/{share/schemas → schemas}/index.ts +3 -3
  193. package/src/{share/schemas → schemas}/navigation.ts +6 -1
  194. package/src/{share/schemas → schemas}/page-base.ts +6 -2
  195. package/src/{share/schemas → schemas}/person.ts +1 -1
  196. package/src/{share/schemas → schemas}/standard-list-item.ts +1 -1
  197. package/src/schemas/tests/claim-records.test.ts +52 -0
  198. package/src/schemas/tests/claims.test.ts +23 -0
  199. package/src/schemas/tests/effects.test.ts +116 -0
  200. package/src/schemas/tests/features.test.ts +61 -0
  201. package/src/schemas/tests/horizontal-align.test.ts +16 -0
  202. package/src/schemas/tests/icon-color.test.ts +16 -0
  203. package/src/schemas/tests/live-photo.test.ts +40 -0
  204. package/src/schemas/tests/material-credit.test.ts +51 -0
  205. package/src/schemas/tests/media.test.ts +26 -0
  206. package/src/schemas/tests/navigation.test.ts +58 -0
  207. package/src/schemas/tests/page-base.test.ts +19 -0
  208. package/src/schemas/tests/participant.test.ts +26 -0
  209. package/src/schemas/tests/person.test.ts +12 -0
  210. package/src/schemas/tests/print.test.ts +30 -0
  211. package/src/schemas/tests/section-background.test.ts +31 -0
  212. package/src/schemas/tests/section-body.test.ts +16 -0
  213. package/src/schemas/tests/section-cards.test.ts +17 -0
  214. package/src/schemas/tests/section-cta.test.ts +41 -0
  215. package/src/schemas/tests/section-header.test.ts +31 -0
  216. package/src/schemas/tests/section-image.test.ts +24 -0
  217. package/src/schemas/tests/section-motion.test.ts +29 -0
  218. package/src/schemas/tests/section-shell.test.ts +42 -0
  219. package/src/schemas/tests/section-stats.test.ts +17 -0
  220. package/src/schemas/tests/site-background.test.ts +33 -0
  221. package/src/schemas/tests/standard-list-item.test.ts +16 -0
  222. package/src/{share → sections}/rfc0042-utils.ts +1 -1
  223. package/src/{share/semantic → semantic}/block-extractors/index.ts +20 -1
  224. package/src/{share/semantic → semantic}/business-projection.ts +95 -1
  225. package/src/semantic/canonical-uri.ts +54 -0
  226. package/src/{share/semantic → semantic}/extract.ts +100 -1
  227. package/src/semantic/fact-extraction.test.ts +47 -0
  228. package/src/semantic/fact-extraction.ts +46 -0
  229. package/src/semantic/freshness.ts +67 -0
  230. package/src/{share/semantic → semantic}/ids.ts +6 -1
  231. package/src/{share/semantic → semantic}/index.ts +9 -2
  232. package/src/{share/semantic → semantic}/jsonld/breadcrumb.ts +6 -2
  233. package/src/{share/semantic → semantic}/jsonld/context.ts +6 -2
  234. package/src/{share/semantic → semantic}/jsonld/faq.ts +6 -2
  235. package/src/{share/semantic → semantic}/jsonld/initiative.ts +6 -1
  236. package/src/{share/semantic → semantic}/jsonld/organization.ts +6 -1
  237. package/src/{share/semantic → semantic}/jsonld/person.ts +6 -2
  238. package/src/{share/semantic → semantic}/jsonld/service.ts +6 -2
  239. package/src/semantic/jsonld/shared.ts +36 -0
  240. package/src/semantic/jsonld/tests/article.test.ts +89 -0
  241. package/src/semantic/jsonld/tests/breadcrumb.test.ts +62 -0
  242. package/src/semantic/jsonld/tests/collection-list.test.ts +39 -0
  243. package/src/semantic/jsonld/tests/faq.test.ts +60 -0
  244. package/src/semantic/jsonld/tests/initiative.test.ts +56 -0
  245. package/src/semantic/jsonld/tests/organization.test.ts +123 -0
  246. package/src/semantic/jsonld/tests/person.test.ts +89 -0
  247. package/src/semantic/jsonld/tests/service.test.ts +65 -0
  248. package/src/semantic/jsonld/tests/shared.test.ts +41 -0
  249. package/src/semantic/jsonld/tests/video.test.ts +84 -0
  250. package/src/semantic/jsonld/tests/webpage.test.ts +93 -0
  251. package/src/semantic/jsonld/tests/website.test.ts +27 -0
  252. package/src/semantic/jsonld/types.ts +24 -0
  253. package/src/{share/semantic → semantic}/jsonld/webpage.ts +6 -1
  254. package/src/semantic/jsonld/website.ts +32 -0
  255. package/src/{share/semantic → semantic}/jsonld.ts +6 -1
  256. package/src/{share/semantic → semantic}/llms.ts +41 -3
  257. package/src/{share/semantic → semantic}/models.ts +27 -38
  258. package/src/{share/semantic → semantic}/organization-profile.ts +3 -0
  259. package/src/{share/semantic → semantic}/page-builders/markdown-page.ts +6 -3
  260. package/src/{share/semantic → semantic}/page-utils.ts +6 -3
  261. package/src/semantic/tests/ai.test.ts +55 -0
  262. package/src/semantic/tests/block-extraction.test.ts +34 -0
  263. package/src/{share/tests/breadcrumbs.test.ts → semantic/tests/breadcrumbs-0229.test.ts} +1 -1
  264. package/src/semantic/tests/breadcrumbs.test.ts +127 -0
  265. package/src/{share → semantic}/tests/build-page-price-markers.test.ts +2 -2
  266. package/src/semantic/tests/build-page.test.ts +122 -0
  267. package/src/semantic/tests/business-projection.test.ts +367 -0
  268. package/src/semantic/tests/canonical-uri.test.ts +56 -0
  269. package/src/semantic/tests/extract.test.ts +209 -0
  270. package/src/semantic/tests/feed.test.ts +113 -0
  271. package/src/semantic/tests/freshness.pbt.test.ts +108 -0
  272. package/src/semantic/tests/helpers.ts +32 -0
  273. package/src/semantic/tests/ids.test.ts +118 -0
  274. package/src/{share/tests/image-sitemap.test.ts → semantic/tests/image-sitemap-0150.test.ts} +1 -1
  275. package/src/semantic/tests/image-sitemap.test.ts +109 -0
  276. package/src/{share → semantic}/tests/jsonld-service.test.ts +2 -2
  277. package/src/{share → semantic}/tests/jsonld-video.test.ts +3 -3
  278. package/src/{share → semantic}/tests/jsonld-webpage.test.ts +3 -3
  279. package/src/semantic/tests/jsonld.test.ts +61 -0
  280. package/src/{share → semantic}/tests/llms-0789.test.ts +2 -2
  281. package/src/semantic/tests/llms-policy.test.ts +60 -0
  282. package/src/semantic/tests/llms.test.ts +164 -0
  283. package/src/semantic/tests/markdown-hygiene.test.ts +72 -0
  284. package/src/semantic/tests/markdown-page.test.ts +97 -0
  285. package/src/{share → semantic}/tests/organization-jsonld.test.ts +3 -3
  286. package/src/semantic/tests/organization-profile.test.ts +107 -0
  287. package/src/{share/tests/output-projection.test.ts → semantic/tests/output-projection-0143.test.ts} +1 -1
  288. package/src/semantic/tests/output-projection.test.ts +77 -0
  289. package/src/semantic/tests/page-markdown.test.ts +98 -0
  290. package/src/semantic/tests/page-utils.test.ts +88 -0
  291. package/src/{share/tests/price-marker-resolver.test.ts → semantic/tests/price-marker-resolver-0767.test.ts} +2 -2
  292. package/src/semantic/tests/price-marker-resolver.test.ts +90 -0
  293. package/src/semantic/tests/project-claims.pbt.test.ts +60 -0
  294. package/src/semantic/tests/robots.test.ts +70 -0
  295. package/src/{share/semantic → semantic}/tests/split-sentences.test.ts +1 -1
  296. package/src/{share → semantic}/tests/twin-path.test.ts +1 -1
  297. package/src/semantic/tests/update-stamp.test.ts +102 -0
  298. package/src/signing/index.ts +13 -0
  299. package/src/signing/key.ts +139 -0
  300. package/src/signing/sign.ts +66 -0
  301. package/src/signing/types.ts +29 -0
  302. package/src/{share/slug → slug}/slug-url.ts +4 -1
  303. package/src/stack/run-tool.ts +108 -0
  304. package/src/stack/stack-checks.ts +124 -0
  305. package/src/stack/tests/run-tool.test.ts +138 -0
  306. package/src/stack/tests/stack-checks.test.ts +141 -0
  307. package/src/stack/tests/walk-files.test.ts +131 -0
  308. package/src/stack/walk-files.ts +114 -0
  309. package/src/surface/blueprint.ts +342 -66
  310. package/src/surface/decision-composer.ts +6 -1
  311. package/src/surface/geo.ts +6 -1
  312. package/src/surface/index.ts +11 -7
  313. package/src/surface/types.ts +2 -2
  314. package/src/surface/vitest.config.ts +1 -0
  315. package/src/tests/signing-core.test.ts +129 -0
  316. package/src/{share → text}/css-value-normalize.ts +6 -1
  317. package/src/text/string-utils.ts +24 -0
  318. package/src/{share → text}/tests/text-normalize.test.ts +5 -0
  319. package/src/{share → text}/text-normalize.ts +4 -3
  320. package/src/{share → text}/wrap-inline-numbers.ts +1 -1
  321. package/src/types/axiom-study.d.ts +36 -0
  322. package/src/types/hls-js-light.d.ts +21 -0
  323. package/src/types/qrcode-browser.d.ts +23 -0
  324. package/src/typography/fix.pbt.test.ts +208 -0
  325. package/src/typography/fix.ts +148 -0
  326. package/src/typography/index.ts +54 -0
  327. package/src/typography/locale-defaults.ts +97 -0
  328. package/src/typography/rules-tier1.test.ts +459 -0
  329. package/src/typography/rules-tier1.ts +925 -0
  330. package/src/typography/rules-tier2-locale.pbt.test.ts +190 -0
  331. package/src/typography/rules-tier2-locale.test.ts +286 -0
  332. package/src/typography/rules-tier2-locale.ts +399 -0
  333. package/src/typography/rules-tier2-structure.test.ts +330 -0
  334. package/src/typography/rules-tier2-structure.ts +378 -0
  335. package/src/typography/rules-tier3-advisory.test.ts +290 -0
  336. package/src/typography/rules-tier3-advisory.ts +239 -0
  337. package/src/typography/text-surface.test.ts +244 -0
  338. package/src/typography/text-surface.ts +448 -0
  339. package/src/index.ts +0 -14
  340. package/src/integration/port-barrel.ts +0 -105
  341. package/src/share/content/index.ts +0 -16
  342. package/src/share/content-discipline/index.ts +0 -14
  343. package/src/share/index.ts +0 -86
  344. package/src/share/legal/index.ts +0 -1
  345. package/src/share/redirects.ts +0 -54
  346. package/src/share/scripts/index.ts +0 -26
  347. package/src/share/semantic/jsonld/shared.ts +0 -31
  348. package/src/share/semantic/jsonld/types.ts +0 -18
  349. package/src/share/semantic/jsonld/website.ts +0 -27
  350. package/src/share/string-utils.ts +0 -19
  351. package/src/share/types/axiom-study.d.ts +0 -22
  352. package/src/share/types/hls-js-light.d.ts +0 -16
  353. package/src/share/types/qrcode-browser.d.ts +0 -18
  354. package/src/share/utility-registry.yaml +0 -36
  355. package/src/share/vitest.config.ts +0 -8
  356. package/src/surface/blueprint-schema.ts +0 -314
  357. package/src/surface/blueprint-types.ts +0 -256
  358. /package/src/{share/agent → agent}/api-catalog.ts +0 -0
  359. /package/src/{share/agent → agent}/capability.ts +0 -0
  360. /package/src/{share/agent → agent}/dns-aid.ts +0 -0
  361. /package/src/{share/agent → agent}/fleet-catalog.ts +0 -0
  362. /package/src/{share/agent → agent}/index.ts +0 -0
  363. /package/src/{share/agent → agent}/knowledge.ts +0 -0
  364. /package/src/{share/agent → agent}/mcp-card.ts +0 -0
  365. /package/src/{share/agent → agent}/omit-empty.ts +0 -0
  366. /package/src/{share/agent → agent}/openapi.ts +0 -0
  367. /package/src/{share/agent → agent}/proof.ts +0 -0
  368. /package/src/{share/agent → agent}/search.test.ts +0 -0
  369. /package/src/{share → attribution}/attribution-display.ts +0 -0
  370. /package/src/{share/scripts → client-scripts}/gsap-mountain-journey.ts +0 -0
  371. /package/src/{share/scripts → client-scripts}/gsap-parallax.ts +0 -0
  372. /package/src/{share/scripts → client-scripts}/gsap-reveal.ts +0 -0
  373. /package/src/{share/scripts → client-scripts}/gsap-stagger.ts +0 -0
  374. /package/src/{share/scripts → client-scripts}/live-photos.ts +0 -0
  375. /package/src/{share/scripts → client-scripts}/video-player.ts +0 -0
  376. /package/src/{share/content → content}/resolve-field-path.ts +0 -0
  377. /package/src/{share/content → content}/substitute-deep.ts +0 -0
  378. /package/src/{share → content}/tests/content-ref-index.test.ts +0 -0
  379. /package/src/{share/content-discipline → content-discipline}/types.ts +0 -0
  380. /package/src/{share → image-provider}/image-provider.ts +0 -0
  381. /package/src/{share/knowledge → knowledge}/claim.ts +0 -0
  382. /package/src/{share/knowledge → knowledge}/derivation.ts +0 -0
  383. /package/src/{share/knowledge → knowledge}/freshness.ts +0 -0
  384. /package/src/{share/knowledge → knowledge}/index.ts +0 -0
  385. /package/src/{share/knowledge → knowledge}/ledger.ts +0 -0
  386. /package/src/{share/knowledge → knowledge}/plan.ts +0 -0
  387. /package/src/{share/knowledge → knowledge}/source.ts +0 -0
  388. /package/src/{share/legal → legal}/translation-policy.ts +0 -0
  389. /package/src/{share/middleware → middleware}/language-redirect.ts +0 -0
  390. /package/src/{share/middleware → middleware}/tests/access-protection.test.ts +0 -0
  391. /package/src/{share → node}/fs/index.ts +0 -0
  392. /package/src/{share/tests/markdown-twin-provenance.test.ts → node/tests/markdown-twin-provenance-0613.test.ts} +0 -0
  393. /package/src/{share → offers}/offer-capacity.ts +0 -0
  394. /package/src/{share/onboarding-yaml/index.ts → onboarding/yaml.ts} +0 -0
  395. /package/src/{share → ontology}/tests/ontology-role-by-cosmic-name.test.ts +0 -0
  396. /package/src/{share/routes → routes}/tests/template-filter.test.ts +0 -0
  397. /package/src/{share/schemas → schemas}/claim-records.ts +0 -0
  398. /package/src/{share/schemas → schemas}/horizontal-align.ts +0 -0
  399. /package/src/{share/schemas → schemas}/icon-color.ts +0 -0
  400. /package/src/{share/schemas → schemas}/live-photo.ts +0 -0
  401. /package/src/{share/schemas → schemas}/material-credit.ts +0 -0
  402. /package/src/{share/schemas → schemas}/media.ts +0 -0
  403. /package/src/{share/schemas → schemas}/participant.ts +0 -0
  404. /package/src/{share/schemas → schemas}/print.ts +0 -0
  405. /package/src/{share/schemas → schemas}/section-background.ts +0 -0
  406. /package/src/{share/schemas → schemas}/section-body.ts +0 -0
  407. /package/src/{share/schemas → schemas}/section-cards.ts +0 -0
  408. /package/src/{share/schemas → schemas}/section-cta.ts +0 -0
  409. /package/src/{share/schemas → schemas}/section-header.ts +0 -0
  410. /package/src/{share/schemas → schemas}/section-image.ts +0 -0
  411. /package/src/{share/schemas → schemas}/section-motion.ts +0 -0
  412. /package/src/{share/schemas → schemas}/section-shell.ts +0 -0
  413. /package/src/{share/schemas → schemas}/section-stats.ts +0 -0
  414. /package/src/{share/schemas → schemas}/site-background.ts +0 -0
  415. /package/src/{share/semantic → semantic}/ai.ts +0 -0
  416. /package/src/{share/semantic → semantic}/block-extraction.ts +0 -0
  417. /package/src/{share/semantic → semantic}/breadcrumbs.ts +0 -0
  418. /package/src/{share/semantic → semantic}/build-page.ts +0 -0
  419. /package/src/{share/semantic → semantic}/feed.ts +0 -0
  420. /package/src/{share/semantic → semantic}/image-sitemap.ts +0 -0
  421. /package/src/{share/semantic → semantic}/jsonld/article.ts +0 -0
  422. /package/src/{share/semantic → semantic}/jsonld/collection-list.ts +0 -0
  423. /package/src/{share/semantic → semantic}/jsonld/video.ts +0 -0
  424. /package/src/{share/semantic → semantic}/llms-policy.ts +0 -0
  425. /package/src/{share/semantic → semantic}/markdown-hygiene.ts +0 -0
  426. /package/src/{share/semantic → semantic}/output-projection.ts +0 -0
  427. /package/src/{share/semantic → semantic}/page-markdown.ts +0 -0
  428. /package/src/{share/semantic → semantic}/price-marker-resolver.ts +0 -0
  429. /package/src/{share/semantic → semantic}/robots.ts +0 -0
  430. /package/src/{share/semantic → semantic}/update-stamp.ts +0 -0
  431. /package/src/{share/slug → slug}/heading-slugger.ts +0 -0
  432. /package/src/{share/slug → slug}/index.ts +0 -0
  433. /package/src/{share/slug → slug}/slug-id.ts +0 -0
  434. /package/src/{share/slug → slug}/strategies.ts +0 -0
  435. /package/src/{share/slug → slug}/tests/slug.test.ts +0 -0
  436. /package/src/{share → text}/tests/text-normalize.pbt.test.ts +0 -0
  437. /package/src/{share → text}/text-position.ts +0 -0
@@ -59,7 +59,7 @@ export function need<T>(fieldName: string, value: T | undefined | null): T | str
59
59
  * const props = cast<TeamSectionContent>(pageOverride);
60
60
  * ```
61
61
  */
62
- export function cast<T extends Record<string, unknown>>(pageOverride: Record<string, unknown>): T {
62
+ export function cast<T extends object>(pageOverride: Record<string, unknown>): T {
63
63
  return pageOverride as unknown as T;
64
64
  }
65
65
 
@@ -501,10 +501,27 @@ for (const blockType of PASSPORT_NOOP_TYPES) {
501
501
  });
502
502
  }
503
503
 
504
+ // ---------------------------------------------------------------------------
505
+ // entity-grid (RFC-1062) — extracts heading and body items with descriptions.
504
506
  // ---------------------------------------------------------------------------
505
507
  // Site-specific block types that have no semantic text to extract but must be
506
508
  // registered so page.blocks.extract.validate does not fail.
507
- // ---------------------------------------------------------------------------
509
+ BLOCK_EXTRACTORS.register<Record<string, unknown>>({
510
+ blockType: "entity-grid",
511
+ extract(props) {
512
+ const heading = safeString(safeGet(props, "header.heading"));
513
+ const lead = safeString(safeGet(props, "header.subheading"));
514
+ const items = safeArray(safeGet(props, "body.items"), (item) => {
515
+ const number = safeString(safeGet(item, "number"));
516
+ const title = safeString(safeGet(item, "title"));
517
+ const description = safeString(safeGet(item, "description"));
518
+ if (!title) return undefined;
519
+ return { title: number ? `${number}. ${title}` : title, description };
520
+ });
521
+ return { heading, lead, items };
522
+ },
523
+ });
524
+
508
525
  const SITE_NOOP_TYPES = [
509
526
  "nachweis-list",
510
527
  "nachweis-detail",
@@ -514,6 +531,8 @@ const SITE_NOOP_TYPES = [
514
531
  "mountain-journey",
515
532
  "dynamic-status-block",
516
533
  "service-metadata-block",
534
+ "toc",
535
+ "exit-diagram",
517
536
  ] as const;
518
537
 
519
538
  for (const blockType of SITE_NOOP_TYPES) {
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  <MODULE_CONTRACT>
3
- <purpose>RFC-0148: pure projectors that map canonical business-schema data into the semantic model, plus the projection visibility boundary. Framework-agnostic and side-effect-free, so the disk llms path and the Astro JSON-LD path project every business file identically. Lives in @warpgogol/werkstatt-shared/share (not @warpgogol/werkstatt-site/pbp) because @warpgogol/werkstatt-site/pbp depends on @warpgogol/site-kernel-content — placing the projectors here keeps the node disk loader cycle-free.</purpose>
3
+ <purpose>RFC-0148: pure projectors that map canonical business-schema data into the semantic model, plus the projection visibility boundary. Framework-agnostic and side-effect-free, so the disk llms path and the Astro JSON-LD path project every business file identically. Lives in @warpgogol/werkstatt-shared/semantic (not @warpgogol/werkstatt-site/pbp) because @warpgogol/werkstatt-site/pbp depends on @warpgogol/site-kernel-content — placing the projectors here keeps the node disk loader cycle-free.</purpose>
4
4
  <non-goals>
5
5
  <item>Do not read files — pure mapping over already-loaded data.</item>
6
6
  <item>Do not project privacy-sensitive domains (external-services, compliance).</item>
@@ -10,6 +10,7 @@
10
10
  <item>RFC-0148: initial projection registry — offer + location projectors and the visibility boundary.</item>
11
11
  <item>RFC-0287: added projectWeb for the Agent Surface knowledge tier.</item>
12
12
  <item>RFC-0373: added projectServices for business service catalog projection.</item>
13
+ <item>RFC-1076: add projectClaims projector and SemanticClaimProvenance / SemanticEvidenceRef types.</item>
13
14
  </CHANGE_SUMMARY>
14
15
  */
15
16
 
@@ -21,6 +22,38 @@ import type {
21
22
  SemanticWeb,
22
23
  } from "./models.ts";
23
24
 
25
+ export interface SemanticClaimProvenance {
26
+ /** Stable claim ID from PbpClaim.id. */
27
+ id: string;
28
+ /** Claim class: factual, risk, benefit, etc. */
29
+ claimClass: string;
30
+ /** Claim kind: risk, benefit, comparison, fact, limitation, recommendation. */
31
+ claimKind: string;
32
+ /** The claim statement text. */
33
+ statement: string;
34
+ /** ISO 639-1 language tag of the statement (RFC-0706). */
35
+ statementLang?: string;
36
+ /** Verification level N0–N3 (ADR-0028). */
37
+ verificationLevel?: string;
38
+ /** Confidence: high, medium, low. */
39
+ confidence?: string;
40
+ /** Evidence references — resolved from PbpClaim.evidenceRefs. */
41
+ evidence: SemanticEvidenceRef[];
42
+ }
43
+
44
+ export interface SemanticEvidenceRef {
45
+ /** EvidenceSource entity ID. */
46
+ id: string;
47
+ /** Evidence kind: verified-record, third-party-registry, certificate, etc. */
48
+ kind: string;
49
+ /** Human-readable label for the evidence source. */
50
+ label: string;
51
+ /** SHA-256 integrity hash of the canonical evidence artifact, if available. */
52
+ sha256?: string;
53
+ /** Canonical URI of the evidence source (RFC-1075), if available. */
54
+ canonicalUri?: string;
55
+ }
56
+
24
57
  /**
25
58
  * RFC-0148 privacy boundary. `public` projects to AI (llms) + JSON-LD; `pageMeta`
26
59
  * is build-time only (e.g. legal-page dates → sitemap lastmod); `none` is never
@@ -253,6 +286,67 @@ export function projectServices(
253
286
  return services;
254
287
  }
255
288
 
289
+ /**
290
+ * RFC-1076: project PBP claims with their evidence references into the semantic model.
291
+ * Only claims with status "published" are projected. The sha256 is read from the
292
+ * canonical item (items[key] where canonical === true), falling back to the first
293
+ * item. Localization is handled by the semantic loader (per-language loading with
294
+ * default-language fallback), not by this projector.
295
+ */
296
+ export function projectClaims(
297
+ claims: ReadonlyArray<Record<string, unknown>> | undefined,
298
+ evidenceSources: Record<string, Record<string, unknown>> | undefined,
299
+ ): SemanticClaimProvenance[] {
300
+ if (!claims?.length) return [];
301
+ const result: SemanticClaimProvenance[] = [];
302
+ for (const claim of claims) {
303
+ const id = typeof claim["id"] === "string" ? claim["id"] : "";
304
+ if (!id) continue;
305
+ const status = typeof claim["status"] === "string" ? claim["status"] : "";
306
+ if (status !== "published") continue;
307
+ const evidenceRefs = (claim["evidenceRefs"] ?? {}) as Record<string, { ref?: string }>;
308
+ const evidence: SemanticEvidenceRef[] = [];
309
+ for (const ref of Object.values(evidenceRefs)) {
310
+ const sourceId = ref?.ref;
311
+ if (!sourceId) continue;
312
+ const source = evidenceSources?.[sourceId];
313
+ if (!source) continue;
314
+ const items = (source["items"] ?? {}) as Record<
315
+ string,
316
+ { sha256?: string; canonical?: boolean }
317
+ >;
318
+ const itemValues = Object.values(items);
319
+ const canonicalItem = itemValues.find((it) => it?.canonical === true) ?? itemValues[0];
320
+ evidence.push({
321
+ id: sourceId,
322
+ kind: typeof source["kind"] === "string" ? source["kind"] : "",
323
+ label: typeof source["name"] === "string" ? source["name"] : sourceId,
324
+ ...(typeof canonicalItem?.["sha256"] === "string"
325
+ ? { sha256: canonicalItem["sha256"] }
326
+ : {}),
327
+ ...(typeof source["canonicalUri"] === "string"
328
+ ? { canonicalUri: source["canonicalUri"] }
329
+ : {}),
330
+ });
331
+ }
332
+ result.push({
333
+ id,
334
+ claimClass: typeof claim["claimClass"] === "string" ? claim["claimClass"] : "",
335
+ claimKind: typeof claim["claimKind"] === "string" ? claim["claimKind"] : "",
336
+ statement: typeof claim["statement"] === "string" ? claim["statement"] : "",
337
+ ...(typeof claim["statementLang"] === "string"
338
+ ? { statementLang: claim["statementLang"] }
339
+ : {}),
340
+ ...(typeof claim["verificationLevel"] === "string"
341
+ ? { verificationLevel: claim["verificationLevel"] }
342
+ : {}),
343
+ ...(typeof claim["confidence"] === "string" ? { confidence: claim["confidence"] } : {}),
344
+ evidence,
345
+ });
346
+ }
347
+ return result;
348
+ }
349
+
256
350
  /**
257
351
  * RFC-0287: project the business web/domain identity record (business/{lang}/web.md
258
352
  * — primaryUrl, statusUrl, domains.{primary,german}). A thin, faithful passthrough of
@@ -0,0 +1,54 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>RFC-1075: derive persistent canonical URIs for PBP entity envelopes from site origin and entity identity. Used for Linked Data @id fields in JSON-LD and llms-full.txt projections.</purpose>
4
+ <non-goals>
5
+ <item>Does not validate that the entity ID is well-formed — callers are responsible for providing valid IDs.</item>
6
+ <item>Does not perform URL normalization beyond trailing-slash removal on the site origin.</item>
7
+ </non-goals>
8
+ </MODULE_CONTRACT>
9
+ <CHANGE_SUMMARY>
10
+ <item>RFC-1075: initial — deriveCanonicalUri pure function for persistent entity @id URIs.</item>
11
+ </CHANGE_SUMMARY>
12
+ */
13
+
14
+ /**
15
+ * Entity types supported by the PBP canonical URI scheme.
16
+ *
17
+ * The URI path pattern is `/.well-known/entity/{type}/{id}` for typed entities
18
+ * (e.g. offerings) and `/.well-known/entity/business` for the single business entity.
19
+ */
20
+ export type CanonicalEntityType = "business" | "offering";
21
+
22
+ /**
23
+ * RFC-1075: derive a persistent canonical URI for a PBP entity.
24
+ *
25
+ * The URI follows the pattern:
26
+ * - Business: `{siteOrigin}/.well-known/entity/business`
27
+ * - Offering: `{siteOrigin}/.well-known/entity/offering/{entityId}`
28
+ *
29
+ * The `siteOrigin` is stripped of trailing slashes to produce a clean base.
30
+ * When `siteOrigin` is absent or empty, the function returns `undefined` —
31
+ * callers should skip emitting `@id` in that case.
32
+ *
33
+ * @param siteOrigin - The site origin URL (e.g. `https://example.com`)
34
+ * @param type - The entity type (`"business"` or `"offering"`)
35
+ * @param entityId - The entity ID (required for `"offering"`, ignored for `"business"`)
36
+ * @returns The canonical URI string, or `undefined` when `siteOrigin` is absent
37
+ */
38
+ export function deriveCanonicalUri(
39
+ siteOrigin: string | undefined,
40
+ type: CanonicalEntityType,
41
+ entityId?: string,
42
+ ): string | undefined {
43
+ if (!siteOrigin) return undefined;
44
+
45
+ const base = siteOrigin.replace(/\/+$/, "");
46
+
47
+ if (type === "business") {
48
+ return `${base}/.well-known/entity/business`;
49
+ }
50
+
51
+ if (!entityId) return undefined;
52
+
53
+ return `${base}/.well-known/entity/offering/${entityId}`;
54
+ }
@@ -7,7 +7,7 @@
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
9
  <item>RFC-0133: backfilled MODULE_MAP and CHANGE_SUMMARY markers for compass.validate compliance.</item>
10
- <item>RFC-0915: removed custom slugify() — replaced by slugId from @warpgogol/werkstatt-shared/share/slug.</item>
10
+ <item>RFC-0915: removed custom slugify() — replaced by slugId from @warpgogol/werkstatt-shared/slug.</item>
11
11
  </CHANGE_SUMMARY>
12
12
  */
13
13
 
@@ -160,6 +160,105 @@ export function splitSentences(text: string, locale: string = "en"): string[] {
160
160
  return sentences.filter(Boolean);
161
161
  }
162
162
 
163
+ export type MarkdownList = {
164
+ marker: "-" | "*" | "+" | "digit";
165
+ items: string[];
166
+ };
167
+
168
+ const LIST_MARKER_PATTERNS: Array<{ marker: MarkdownList["marker"]; regex: RegExp }> = [
169
+ { marker: "-", regex: /^-\s+/ },
170
+ { marker: "*", regex: /^\*\s+/ },
171
+ { marker: "+", regex: /^\+\s+/ },
172
+ { marker: "digit", regex: /^\d+\.\s+/ },
173
+ ];
174
+
175
+ function matchListMarker(
176
+ line: string,
177
+ ): { marker: MarkdownList["marker"]; text: string } | undefined {
178
+ for (const { marker, regex } of LIST_MARKER_PATTERNS) {
179
+ const match = line.match(regex);
180
+ if (match) {
181
+ return { marker, text: line.slice(match[0].length).trim() };
182
+ }
183
+ }
184
+ return undefined;
185
+ }
186
+
187
+ function isTopLevelListLine(
188
+ line: string,
189
+ ): { marker: MarkdownList["marker"]; text: string } | undefined {
190
+ // Top-level: no leading whitespace before the marker
191
+ if (/^\s/.test(line)) return undefined;
192
+ return matchListMarker(line);
193
+ }
194
+
195
+ function isIndentedListLine(line: string): boolean {
196
+ // Indented list line: starts with whitespace + list marker
197
+ if (!/^\s/.test(line)) return false;
198
+ const trimmed = line.trimStart();
199
+ return LIST_MARKER_PATTERNS.some(({ regex }) => regex.test(trimmed));
200
+ }
201
+
202
+ export function extractLists(markdown: string): MarkdownList[] {
203
+ const normalized = markdown.trim();
204
+ if (!normalized) return [];
205
+
206
+ const lines = normalized.split("\n");
207
+ const lists: MarkdownList[] = [];
208
+ let currentList: MarkdownList | null = null;
209
+ let inCodeFence = false;
210
+
211
+ for (const line of lines) {
212
+ // Track fenced code blocks
213
+ if (line.trimStart().startsWith("```")) {
214
+ inCodeFence = !inCodeFence;
215
+ if (currentList) {
216
+ lists.push(currentList);
217
+ currentList = null;
218
+ }
219
+ continue;
220
+ }
221
+
222
+ if (inCodeFence) {
223
+ continue;
224
+ }
225
+
226
+ const topMatch = isTopLevelListLine(line);
227
+
228
+ if (topMatch) {
229
+ // Continue current list if same marker type
230
+ if (currentList && currentList.marker === topMatch.marker) {
231
+ currentList.items.push(topMatch.text);
232
+ } else {
233
+ // Different marker or first list — flush previous, start new
234
+ if (currentList) {
235
+ lists.push(currentList);
236
+ }
237
+ currentList = { marker: topMatch.marker, items: [topMatch.text] };
238
+ }
239
+ continue;
240
+ }
241
+
242
+ // Indented list line — part of parent item, not a new item
243
+ if (isIndentedListLine(line)) {
244
+ continue;
245
+ }
246
+
247
+ // Non-list line (blank, prose, heading, etc.) — terminate current list
248
+ if (currentList) {
249
+ lists.push(currentList);
250
+ currentList = null;
251
+ }
252
+ }
253
+
254
+ // Flush trailing list
255
+ if (currentList) {
256
+ lists.push(currentList);
257
+ }
258
+
259
+ return lists;
260
+ }
261
+
163
262
  export function extractListFacts(markdown: string): string[] {
164
263
  return markdown
165
264
  .split("\n")
@@ -0,0 +1,47 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { normalizeFactValue, type CanonicalFact } from "./fact-extraction.ts";
3
+
4
+ describe("fact-extraction: normalizeFactValue", () => {
5
+ test("normalizes email to lowercase", () => {
6
+ expect(normalizeFactValue("email", "Info@Test.COM")).toBe("info@test.com");
7
+ });
8
+
9
+ test("normalizes phone by stripping tel: prefix and separators", () => {
10
+ expect(normalizeFactValue("phone", "tel:+49 30 123-4567")).toBe("+49301234567");
11
+ });
12
+
13
+ test("normalizes phone by stripping spaces, hyphens, and parentheses", () => {
14
+ expect(normalizeFactValue("phone", "+49 (30) 123-4567")).toBe("+49301234567");
15
+ });
16
+
17
+ test("trims whitespace for other types", () => {
18
+ expect(normalizeFactValue("price", " 2900 ")).toBe("2900");
19
+ });
20
+
21
+ test("trims whitespace for name", () => {
22
+ expect(normalizeFactValue("name", " Test Business ")).toBe("Test Business");
23
+ });
24
+
25
+ test("handles empty string", () => {
26
+ expect(normalizeFactValue("email", "")).toBe("");
27
+ expect(normalizeFactValue("phone", "")).toBe("");
28
+ expect(normalizeFactValue("price", "")).toBe("");
29
+ });
30
+ });
31
+
32
+ describe("fact-extraction: CanonicalFact interface", () => {
33
+ test("CanonicalFact can be constructed with all fields", () => {
34
+ const fact: CanonicalFact = {
35
+ type: "price",
36
+ entityId: "offering-1",
37
+ entityType: "offering",
38
+ value: "2900",
39
+ surface: "canonical",
40
+ source: "pbp",
41
+ };
42
+ expect(fact.type).toBe("price");
43
+ expect(fact.entityId).toBe("offering-1");
44
+ expect(fact.value).toBe("2900");
45
+ expect(fact.surface).toBe("canonical");
46
+ });
47
+ });
@@ -0,0 +1,46 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>RFC-1077: Canonical fact interface and normalization utility for cross-surface fact parity validation. Shared between werkstatt-shared (contract) and werkstatt-site (extraction logic).</purpose>
4
+ <non-goals>
5
+ <item>Do not import from werkstatt-site — this package must not depend on the site plugin.</item>
6
+ <item>Do not implement fact extraction — that lives in werkstatt-site where PbpResolvedGraph is available.</item>
7
+ </non-goals>
8
+ </MODULE_CONTRACT>
9
+ <CHANGE_SUMMARY>
10
+ <item>RFC-1077: initial implementation — CanonicalFact interface and normalizeFactValue.</item>
11
+ </CHANGE_SUMMARY>
12
+ */
13
+
14
+ /** RFC-1077: A canonical fact extracted from the PBP resolved graph or a rendered surface. */
15
+ export interface CanonicalFact {
16
+ /** Fact type: price, address, email, foundingYear, representative, phone, name. */
17
+ type: string;
18
+ /** Entity ID the fact belongs to (e.g. offering ID, business ID, place ID). */
19
+ entityId: string;
20
+ /** Entity type: business, offering, place, contactPoint. */
21
+ entityType: string;
22
+ /** The canonical value as a string (normalized for comparison). */
23
+ value: string;
24
+ /** The surface where this fact was found: html, llms-full, jsonld, canonical. */
25
+ surface: string;
26
+ /** Source file path or URL where the fact was found. */
27
+ source: string;
28
+ }
29
+
30
+ /** RFC-1077: Normalize a fact value for comparison across surfaces. */
31
+ export function normalizeFactValue(type: string, value: string): string {
32
+ const trimmed = value.trim();
33
+ if (type === "email") return trimmed.toLowerCase();
34
+ if (type === "phone") return trimmed.replace(/^tel:/, "").replace(/[\s\-()]/g, "");
35
+ if (type === "price") {
36
+ let stripped = trimmed.replace(/\s*(EUR|USD|GBP|CHF|UAH|€|\$|£|₴)\s*$/i, "");
37
+ // Handle German thousands separator: "2.000" → "2000", "1.040" → "1040"
38
+ stripped = stripped.replace(/(\d)\.(\d{3})(?!\d)/g, "$1$2");
39
+ // Handle space thousands separator: "2 000" → "2000"
40
+ stripped = stripped.replace(/(\d)\s(\d{3})(?!\d)/g, "$1$2");
41
+ const num = parseFloat(stripped);
42
+ if (!isNaN(num)) return String(num);
43
+ return stripped;
44
+ }
45
+ return trimmed;
46
+ }
@@ -0,0 +1,67 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-1078: Pure freshness calculation functions for semantic.freshness.validate.
5
+ Provides calculateAgeDays, isAssessmentStale, isItemStale, and the FreshnessViolation
6
+ interface. All functions are pure and deterministic for a fixed reference date.
7
+ </purpose>
8
+ <non-goals>
9
+ <item>Does not compile PBP profiles — that is the validator's job in werkstatt-site.</item>
10
+ <item>Does not emit diagnostics — the validator collects violations and emits them.</item>
11
+ </non-goals>
12
+ </MODULE_CONTRACT>
13
+ <CHANGE_SUMMARY>
14
+ <item>RFC-1078: initial — calculateAgeDays, isAssessmentStale, isItemStale, FreshnessViolation, DEFAULT_FRESHNESS_WINDOW_DAYS.</item>
15
+ </CHANGE_SUMMARY>
16
+ */
17
+
18
+ /** RFC-1078: Default freshness window for evidence items without a declared maxAgeDays. */
19
+ export const DEFAULT_FRESHNESS_WINDOW_DAYS = 180;
20
+
21
+ /** RFC-1078: A freshness violation detected by semantic.freshness.validate. */
22
+ export interface FreshnessViolation {
23
+ rule: string;
24
+ entityType: string;
25
+ entityId: string;
26
+ /** The field that is stale: assessment.observedAt, items[].retrievedAt, etc. */
27
+ field: string;
28
+ /** The observed timestamp. */
29
+ observedAt: string;
30
+ /** The maximum age in days. */
31
+ maxAgeDays: number;
32
+ /** The actual age in days at validation time. */
33
+ actualAgeDays: number;
34
+ message: string;
35
+ }
36
+
37
+ /**
38
+ * RFC-1078: Calculate age in days from an ISO timestamp to a reference date.
39
+ * Pure and deterministic for a fixed reference date.
40
+ * Returns Number.MAX_SAFE_INTEGER for invalid date strings.
41
+ */
42
+ export function calculateAgeDays(observedAt: string, referenceDate: Date = new Date()): number {
43
+ const observed = new Date(observedAt);
44
+ if (isNaN(observed.getTime())) return Number.MAX_SAFE_INTEGER;
45
+ const diffMs = referenceDate.getTime() - observed.getTime();
46
+ return Math.floor(diffMs / (1000 * 60 * 60 * 24));
47
+ }
48
+
49
+ /** RFC-1078: Check if a technical assessment is stale. Pure. */
50
+ export function isAssessmentStale(
51
+ assessment: { observedAt: string; freshness: { maxAgeDays: number } },
52
+ referenceDate: Date = new Date(),
53
+ ): boolean {
54
+ const ageDays = calculateAgeDays(assessment.observedAt, referenceDate);
55
+ return ageDays > assessment.freshness.maxAgeDays;
56
+ }
57
+
58
+ /** RFC-1078: Check if an evidence item is stale. Pure. Returns false if retrievedAt is missing. */
59
+ export function isItemStale(
60
+ item: { retrievedAt?: string },
61
+ maxAgeDays: number,
62
+ referenceDate: Date = new Date(),
63
+ ): boolean {
64
+ if (!item.retrievedAt) return false;
65
+ const ageDays = calculateAgeDays(item.retrievedAt, referenceDate);
66
+ return ageDays > maxAgeDays;
67
+ }
@@ -7,8 +7,13 @@
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Moved from app semantic/ids to packages/share/src/semantic/ids.ts — framework-agnostic, reusable across all apps.</item>
11
10
  <item>RFC-0910: add canonicalRootUrl — unprefixed root URL for entity identity (Organization.url, WebSite.url).</item>
11
+ <item>RFC-1097: step 6 — compass.migrate codemod run
12
+
13
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
14
+ <item>RFC-1097: sweep — werkstatt-engine clean
15
+
16
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
12
17
  </CHANGE_SUMMARY>
13
18
  */
14
19
 
@@ -6,7 +6,12 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Expanded barrel to cover the full semantic layer: ids, jsonld, llms, page-utils, page-builders.</item>
9
+ <item>RFC-1097: step 6 — compass.migrate codemod run
10
+
11
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
12
+ <item>RFC-1097: sweep — werkstatt-engine clean
13
+
14
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
10
15
  </CHANGE_SUMMARY>
11
16
  */
12
17
 
@@ -32,5 +37,7 @@ export * from "./build-page.ts";
32
37
  export * from "./block-extraction.ts";
33
38
  export * from "./block-extractors/index.ts";
34
39
  export * from "./update-stamp.ts";
35
- export * from "./markdown-twin-provenance.ts";
36
40
  export * from "./price-marker-resolver.ts";
41
+ export * from "./canonical-uri.ts";
42
+ export * from "./fact-extraction.ts";
43
+ export * from "./freshness.ts";
@@ -6,8 +6,12 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Added breadcrumb support for JSON-LD generation.</item>
10
- <item>Moved from app semantic/jsonld/breadcrumb to packages/share.</item>
9
+ <item>RFC-1097: step 6 — compass.migrate codemod run
10
+
11
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
12
+ <item>RFC-1097: sweep — werkstatt-engine clean
13
+
14
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
11
15
  </CHANGE_SUMMARY>
12
16
  */
13
17
 
@@ -7,8 +7,12 @@
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Added servicesListId and initiativesListId derived IDs.</item>
11
- <item>Moved from app semantic/jsonld/context to packages/share.</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — werkstatt-engine clean
14
+
15
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
12
16
  </CHANGE_SUMMARY>
13
17
  */
14
18
 
@@ -6,8 +6,12 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Added FAQPage JSON-LD support.</item>
10
- <item>Moved from app semantic/jsonld/faq to packages/share.</item>
9
+ <item>RFC-1097: step 6 — compass.migrate codemod run
10
+
11
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
12
+ <item>RFC-1097: sweep — werkstatt-engine clean
13
+
14
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
11
15
  </CHANGE_SUMMARY>
12
16
  */
13
17
 
@@ -6,7 +6,12 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Added initiatives list node plus initiative item-position wiring.</item>
9
+ <item>RFC-1097: step 6 — compass.migrate codemod run
10
+
11
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
12
+ <item>RFC-1097: sweep — werkstatt-engine clean
13
+
14
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
10
15
  </CHANGE_SUMMARY>
11
16
  */
12
17
 
@@ -7,7 +7,12 @@
7
7
  </non-goals>
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
- <item>Added Organization JSON-LD generation.</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — werkstatt-engine clean
14
+
15
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
11
16
  </CHANGE_SUMMARY>
12
17
  */
13
18
 
@@ -6,9 +6,13 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Added Person JSON-LD generation for organization members.</item>
10
- <item>Moved from app semantic/jsonld/person to packages/share.</item>
11
9
  <item>RFC-0512: emit address, knowsAbout, affiliation when present on SemanticPerson.</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — werkstatt-engine clean
14
+
15
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
12
16
  </CHANGE_SUMMARY>
13
17
  */
14
18
 
@@ -6,9 +6,13 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>Added Service JSON-LD generation.</item>
10
- <item>Moved from app semantic/jsonld/service to packages/share.</item>
11
9
  <item>RFC-0498: extend buildServiceNodes to gate Service emission by per-depth policy for all surface depths (website-local depth-1, website-service depth-1, website-local depth-5).</item>
10
+ <item>RFC-1097: step 6 — compass.migrate codemod run
11
+
12
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
13
+ <item>RFC-1097: sweep — werkstatt-engine clean
14
+
15
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
12
16
  </CHANGE_SUMMARY>
13
17
  */
14
18