@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
@@ -0,0 +1,248 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>
4
+ RFC-0267: the WorkspaceIO port — the single seam through which kernel commands
5
+ touch the filesystem and spawn processes. `KernelRuntimeContext.io` carries an
6
+ adapter chosen by the executor: the default fs-backed adapter, a recording
7
+ adapter (universal `--dry-run`: intercepts writes/deletes, records intents,
8
+ touches nothing), or a read-only adapter (used for `mutatesState: false`
9
+ commands; throws KERNEL-META-01 on any attempted mutation). Adoption is
10
+ ratcheted — ambient `node:fs` imports keep working in unmigrated modules;
11
+ `kernel.io.lint` (IO-01) only gates new/migrated modules.
12
+
13
+ RFC-0326: `createDefaultIO` now returns `{ io, intents }` — the io writes to
14
+ real disk AND records every mutation as a `WriteIntent` for execution-report
15
+ surfacing (`filesModified`). This unifies the dry-run and real-run paths: both
16
+ capture intents, just from different adapters.
17
+ </purpose>
18
+ <non-goals>
19
+ <item>Do not abstract network access — filesystem and process execution only.</item>
20
+ <item>Do not enforce IO at the module-import level — that is kernel.io.lint's static check.</item>
21
+ </non-goals>
22
+ </MODULE_CONTRACT>
23
+ <KEY_DECISIONS>
24
+ <item>WorkspaceIO is the single filesystem seam — kernel commands never touch fs directly.</item>
25
+ </KEY_DECISIONS>
26
+ <CHANGE_SUMMARY>
27
+ <item>RFC-0267: initial implementation.</item>
28
+ <item>RFC-0267 follow-up: add readdir(path): Promise&lt;DirEntry[]&gt; to complete the port so directory-listing commands (e.g. sitemap.generate) migrate mechanically without importing node:fs for Dirent.</item>
29
+ <item>RFC-0326: createDefaultIO returns { io, intents } — writes touch real disk AND record WriteIntent[] for filesModified reporting.</item>
30
+ <item>RFC-1097: step 6 — compass.migrate codemod run
31
+
32
+ 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>
33
+ <item>RFC-1097: sweep — werkstatt-engine clean
34
+
35
+ 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>
36
+ </CHANGE_SUMMARY>
37
+ */
38
+
39
+ import {
40
+ readFile as fsReadFile,
41
+ mkdir as fsMkdir,
42
+ rm as fsRm,
43
+ readdir as fsReaddir,
44
+ stat,
45
+ } from "node:fs/promises";
46
+ import { glob as fsGlob } from "node:fs/promises";
47
+ import { spawn } from "node:child_process";
48
+ import { dirname } from "node:path";
49
+ import { writeFileAtomic } from "./fs-atomic.ts";
50
+
51
+ export interface ExecOptions {
52
+ cwd?: string;
53
+ timeoutMs?: number;
54
+ }
55
+
56
+ export interface ExecResult {
57
+ exitCode: number | null;
58
+ stdout: string;
59
+ stderr: string;
60
+ }
61
+
62
+ /**
63
+ * A directory entry in a port-neutral shape — no `node:fs` `Dirent` leaks
64
+ * through the port, so command modules never need to import `node:fs` just to
65
+ * type a listing. `isFile`/`isDirectory` are plain booleans (not methods).
66
+ */
67
+ export interface DirEntry {
68
+ name: string;
69
+ isFile: boolean;
70
+ isDirectory: boolean;
71
+ }
72
+
73
+ export interface WorkspaceIO {
74
+ readFile(path: string): Promise<string>;
75
+ readFileBytes(path: string): Promise<Uint8Array>;
76
+ exists(path: string): Promise<boolean>;
77
+ glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;
78
+ /** List a directory's immediate entries. Read-only; throws if the path is not a directory. */
79
+ readdir(path: string): Promise<DirEntry[]>;
80
+ /** Atomic by contract (rfc-0258). */
81
+ writeFile(path: string, content: string | Uint8Array): Promise<void>;
82
+ mkdir(path: string): Promise<void>;
83
+ rm(path: string, opts?: { recursive?: boolean }): Promise<void>;
84
+ exec(command: string, args: string[], opts?: ExecOptions): Promise<ExecResult>;
85
+ }
86
+
87
+ async function execImpl(command: string, args: string[], opts?: ExecOptions): Promise<ExecResult> {
88
+ return new Promise((resolve, reject) => {
89
+ const child = spawn(command, args, { cwd: opts?.cwd });
90
+ let stdout = "";
91
+ let stderr = "";
92
+ child.stdout?.on("data", (chunk) => {
93
+ stdout += chunk;
94
+ });
95
+ child.stderr?.on("data", (chunk) => {
96
+ stderr += chunk;
97
+ });
98
+ const timer = opts?.timeoutMs
99
+ ? setTimeout(() => {
100
+ child.kill();
101
+ }, opts.timeoutMs)
102
+ : undefined;
103
+ timer?.unref?.();
104
+ child.on("close", (exitCode) => {
105
+ if (timer) clearTimeout(timer);
106
+ resolve({ exitCode, stdout, stderr });
107
+ });
108
+ child.on("error", (error) => {
109
+ if (timer) clearTimeout(timer);
110
+ reject(error);
111
+ });
112
+ });
113
+ }
114
+
115
+ /**
116
+ * RFC-0326: the default, real fs-backed adapter. `writeFile` is atomic
117
+ * (rfc-0258). Now returns `{ io, intents }` matching `createRecordingIO`'s
118
+ * shape — the io writes to real disk; intents captures every mutation for
119
+ * `filesModified` reporting on execution reports.
120
+ */
121
+ export function createDefaultIO(): { io: WorkspaceIO; intents: WriteIntent[] } {
122
+ const intents: WriteIntent[] = [];
123
+ const io: WorkspaceIO = {
124
+ async readFile(path) {
125
+ return fsReadFile(path, "utf8");
126
+ },
127
+ async readFileBytes(path) {
128
+ return fsReadFile(path);
129
+ },
130
+ async exists(path) {
131
+ try {
132
+ await stat(path);
133
+ return true;
134
+ } catch {
135
+ return false;
136
+ }
137
+ },
138
+ async glob(pattern, opts) {
139
+ const results: string[] = [];
140
+ for await (const entry of fsGlob(pattern, { cwd: opts?.cwd })) {
141
+ results.push(entry);
142
+ }
143
+ return results;
144
+ },
145
+ async readdir(path) {
146
+ const entries = await fsReaddir(path, { withFileTypes: true });
147
+ return entries.map((entry) => ({
148
+ name: entry.name,
149
+ isFile: entry.isFile(),
150
+ isDirectory: entry.isDirectory(),
151
+ }));
152
+ },
153
+ async writeFile(path, content) {
154
+ await fsMkdir(dirname(path), { recursive: true });
155
+ await writeFileAtomic(path, content);
156
+ const bytes =
157
+ typeof content === "string" ? Buffer.byteLength(content, "utf8") : content.byteLength;
158
+ intents.push({ kind: "write", path, bytes });
159
+ },
160
+ async mkdir(path) {
161
+ await fsMkdir(path, { recursive: true });
162
+ intents.push({ kind: "mkdir", path });
163
+ },
164
+ async rm(path, opts) {
165
+ await fsRm(path, { recursive: opts?.recursive ?? false, force: true });
166
+ intents.push({ kind: "rm", path });
167
+ },
168
+ exec: execImpl,
169
+ };
170
+ return { io, intents };
171
+ }
172
+
173
+ export interface WriteIntent {
174
+ kind: "write" | "mkdir" | "rm";
175
+ path: string;
176
+ bytes?: number;
177
+ }
178
+
179
+ /**
180
+ * Wraps a base adapter for universal `--dry-run`: reads pass through to the
181
+ * base adapter (so a command can still make write decisions based on real
182
+ * state), but writes/mkdir/rm are intercepted, recorded, and never touch disk.
183
+ */
184
+ export function createRecordingIO(base: WorkspaceIO): { io: WorkspaceIO; intents: WriteIntent[] } {
185
+ const intents: WriteIntent[] = [];
186
+ const io: WorkspaceIO = {
187
+ readFile: base.readFile.bind(base),
188
+ readFileBytes: base.readFileBytes.bind(base),
189
+ exists: base.exists.bind(base),
190
+ glob: base.glob.bind(base),
191
+ readdir: base.readdir.bind(base),
192
+ async writeFile(path, content) {
193
+ const bytes =
194
+ typeof content === "string" ? Buffer.byteLength(content, "utf8") : content.byteLength;
195
+ intents.push({ kind: "write", path, bytes });
196
+ },
197
+ async mkdir(path) {
198
+ intents.push({ kind: "mkdir", path });
199
+ },
200
+ async rm(path) {
201
+ intents.push({ kind: "rm", path });
202
+ },
203
+ async exec() {
204
+ throw new Error("createRecordingIO: exec() is not supported under --dry-run.");
205
+ },
206
+ };
207
+ return { io, intents };
208
+ }
209
+
210
+ export class KernelMetaError extends Error {
211
+ constructor(
212
+ readonly commandName: string,
213
+ readonly attemptedPath: string,
214
+ ) {
215
+ super(
216
+ `KERNEL-META-01: command "${commandName}" declares mutatesState: false but attempted to write "${attemptedPath}". ` +
217
+ `Fix the command, or if the write is legitimate, set mutatesState: true and declare the path in writes (RFC-0266).`,
218
+ );
219
+ this.name = "KernelMetaError";
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Wraps a base adapter so every mutation throws KERNEL-META-01 naming the
225
+ * command and the attempted path. Used for every `mutatesState: false`
226
+ * command (proves the metadata trustworthy) and by the test harness.
227
+ */
228
+ export function createReadOnlyIO(base: WorkspaceIO, commandName: string): WorkspaceIO {
229
+ return {
230
+ readFile: base.readFile.bind(base),
231
+ readFileBytes: base.readFileBytes.bind(base),
232
+ exists: base.exists.bind(base),
233
+ glob: base.glob.bind(base),
234
+ readdir: base.readdir.bind(base),
235
+ async writeFile(path) {
236
+ throw new KernelMetaError(commandName, path);
237
+ },
238
+ async mkdir(path) {
239
+ throw new KernelMetaError(commandName, path);
240
+ },
241
+ async rm(path) {
242
+ throw new KernelMetaError(commandName, path);
243
+ },
244
+ async exec(command, args) {
245
+ throw new KernelMetaError(commandName, `${command} ${args.join(" ")}`);
246
+ },
247
+ };
248
+ }
@@ -17,7 +17,7 @@ import {
17
17
  formatClaimSubject,
18
18
  claimSubjectsEqual,
19
19
  ClaimSubjectParseError,
20
- } from "../knowledge/claim.ts";
20
+ } from "../claim.ts";
21
21
 
22
22
  test("parse: lang-scoped subject with simple field", () => {
23
23
  const s = parseClaimSubject("business/de/location#residents");
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { test, expect } from "vitest";
11
- import { normalizeForHash, hashSourceValue, derivedState } from "../knowledge/derivation.ts";
11
+ import { normalizeForHash, hashSourceValue, derivedState } from "../derivation.ts";
12
12
 
13
13
  test("normalize: whitespace and markdown are insensitive", () => {
14
14
  expect(normalizeForHash("Hello world")).toBe("Hello world");
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { test, expect } from "vitest";
11
- import { addDuration, evaluateFreshness } from "../knowledge/freshness.ts";
11
+ import { addDuration, evaluateFreshness } from "../freshness.ts";
12
12
 
13
13
  test("addDuration: months and years are calendar-correct", () => {
14
14
  expect(addDuration("2026-01-15", "P1Y")).toBe("2027-01-15");
@@ -18,7 +18,7 @@ import {
18
18
  projectGraph,
19
19
  projectTemporalSeo,
20
20
  type ClaimEvent,
21
- } from "../knowledge/ledger.ts";
21
+ } from "../ledger.ts";
22
22
 
23
23
  function evt(partial: Partial<ClaimEvent>): ClaimEvent {
24
24
  const subject = partial.subject ?? "business/de/location#residents";
@@ -18,7 +18,7 @@ import {
18
18
  defaultCriticality,
19
19
  isRedTask,
20
20
  type MaintenanceTask,
21
- } from "../knowledge/plan.ts";
21
+ } from "../plan.ts";
22
22
 
23
23
  test("stableTaskId: idempotent for the same (subject, trigger)", () => {
24
24
  const a = stableTaskId("business/de/offer#price.monthly", "expired");
@@ -13,7 +13,7 @@ import {
13
13
  extractJsonPath,
14
14
  compareValues,
15
15
  coerceNumber,
16
- } from "../knowledge/source.ts";
16
+ } from "../source.ts";
17
17
 
18
18
  test("descriptor: valid http-json passes", () => {
19
19
  const r = sourceDescriptorSchema.safeParse({
@@ -0,0 +1,15 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>Legal share index — re-export the translation-policy surface for legal content consumers.</purpose>
4
+ <non-goals>
5
+ <item>Do not implement legal policy logic here — the policy lives in translation-policy.ts.</item>
6
+ </non-goals>
7
+ </MODULE_CONTRACT>
8
+ <CHANGE_SUMMARY>
9
+ <item>RFC-1097: sweep — tail packages clean
10
+
11
+ Sweep batch 3: rewrote ~95 purposes across werkstatt-knowledge, werkstatt-shared, godot-game, phaser-game, lifecycle-core, projektarchiv-*, portal-*, billing-*, typescript (CONTRACT-02/PURPOSE-02). Real KEY_DECISIONS on 5 godot utils, non-goals on 5 CONTRACT-03 files, headers on 4 headerless files, CS-07 history literal fix on 2 files. Policy: vitest.config.ts + test-fixtures testPatterns, worker-configuration.d.ts excludedPath. All non-site/engine packages now 0 diagnostics.</item>
12
+ </CHANGE_SUMMARY>
13
+ */
14
+
15
+ export * from "./translation-policy.ts";
@@ -1,14 +1,8 @@
1
1
  /*
2
2
  <MODULE_CONTRACT>
3
3
  <purpose>RFC-0899: Runtime access protection middleware for dev/alt subdomains. Checks Host header and requires Basic Auth with a 4-digit PIN for dev.* and alt.* hosts. Sets X-Robots-Tag headers to prevent indexing.</purpose>
4
- <keywords>middleware, access-protection, basic-auth, pin, dev, alt, RFC-0899</keywords>
5
- <responsibilities>
6
- <item>Check Host header against dev.* and alt.* patterns — pass through for main domain.</item>
7
- <item>Require Basic Auth (username: warp, password: ACCESS_PIN env var) for dev/alt hosts.</item>
8
- <item>Set X-Robots-Tag: noindex, nofollow, noai, noimageai on ALL dev/alt responses (including 401).</item>
9
- <item>Use constant-time string comparison for auth check to prevent timing attacks.</item>
10
- <item>Pass through when ACCESS_PIN is unset (allows new sites before protection is configured).</item>
11
- </responsibilities>
4
+
5
+
12
6
  <non-goals>
13
7
  <item>Do not modify the HTML response body — only headers and access gating.</item>
14
8
  <item>Do not activate for the main/production domain, even if the PIN secret is set on the main Worker.</item>
@@ -17,6 +11,12 @@
17
11
  </MODULE_CONTRACT>
18
12
  <CHANGE_SUMMARY>
19
13
  <item>RFC-0899: Initial access protection middleware for dev/alt subdomains.</item>
14
+ <item>RFC-1097: step 6 — compass.migrate codemod run
15
+
16
+ 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>
17
+ <item>RFC-1097: sweep — werkstatt-engine clean
18
+
19
+ 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>
20
20
  </CHANGE_SUMMARY>
21
21
  */
22
22
 
@@ -17,7 +17,12 @@ never crash rendering for a reason unrelated to the author's actual props.
17
17
  </MODULE_CONTRACT>
18
18
  <CHANGE_SUMMARY>
19
19
  <item>RFC-0262: initial implementation.</item>
20
- <item>Replaced hand-rolled validateShape with ajv standard validator.</item>
20
+ <item>RFC-1097: step 6 — compass.migrate codemod run
21
+
22
+ 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>
23
+ <item>RFC-1097: sweep — werkstatt-engine clean
24
+
25
+ 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>
21
26
  </CHANGE_SUMMARY>
22
27
  */
23
28
 
@@ -3,7 +3,7 @@
3
3
  <purpose>Shared utility for scanning TypeScript source files for import specifiers
4
4
  matching a pattern. Used by werkstatt.autonomy.validate, werkstatt.shared.validate,
5
5
  and forge.autonomy.validate to avoid code duplication (Fowler: Duplicated Code).</purpose>
6
- <keywords>scan, import, utility, shared, validate, autonomy</keywords>
6
+
7
7
  <non-goals>
8
8
  <item>Does not define what is forbidden or exempt — callers provide the pattern and filter.</item>
9
9
  <item>Does not scan test files — .test.ts and .spec.ts are always excluded.</item>
@@ -12,6 +12,13 @@ and forge.autonomy.validate to avoid code duplication (Fowler: Duplicated Code).
12
12
  <CHANGE_SUMMARY>
13
13
  <item>RFC-0868: extract shared directory-scanning utility from autonomy-validate and shared-validate.</item>
14
14
  <item>RFC-0940: move to @warpgogol/werkstatt-shared so forge can import without depending on @warpgogol/werkstatt-engine.</item>
15
+ <item>RFC-1097: step 6 — compass.migrate codemod run
16
+
17
+ 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>
18
+ <item>RFC-1099: export EXCLUDE_DIRS + EXCLUDE_SUFFIXES; extend EXCLUDE_DIRS with cache/build/test dirs (.turbo, .astro, .wrangler, .cache, .stryker-tmp, coverage, __tests__) so the werkstatt-typescript workspace model and all import-scan consumers share one canonical exclusion set.</item>
19
+ <item>RFC-1097: sweep — werkstatt-engine clean
20
+
21
+ 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>
15
22
  </CHANGE_SUMMARY>
16
23
  */
17
24
 
@@ -23,8 +30,21 @@ export interface ImportViolation {
23
30
  specifier: string;
24
31
  }
25
32
 
26
- const EXCLUDE_DIRS = new Set(["node_modules", "tests", "tests-handoff", "dist", "templates"]);
27
- const EXCLUDE_SUFFIXES = [".test.ts", ".spec.ts"];
33
+ export const EXCLUDE_DIRS = new Set([
34
+ "node_modules",
35
+ "tests",
36
+ "tests-handoff",
37
+ "dist",
38
+ "templates",
39
+ ".turbo",
40
+ ".astro",
41
+ ".wrangler",
42
+ ".cache",
43
+ ".stryker-tmp",
44
+ "coverage",
45
+ "__tests__",
46
+ ]);
47
+ export const EXCLUDE_SUFFIXES = [".test.ts", ".spec.ts"];
28
48
 
29
49
  const IMPORT_PATTERN =
30
50
  /(?:^|\n)\s*(?:import\s+(?:type\s+)?[^;]+?\s+from\s+|require\s*\(\s*)["'`]([^"'`]+)["'`]/g;
@@ -8,12 +8,13 @@
8
8
  </MODULE_CONTRACT>
9
9
  <CHANGE_SUMMARY>
10
10
  <item>RFC-0767: relocated loadDerivedPrices from packages/ui to packages/share to break circular dependency. Node-only subpath export.</item>
11
+ <item>RFC-1074: return null for empty {} content — semantically equivalent to "no derived prices".</item>
11
12
  </CHANGE_SUMMARY>
12
13
  */
13
14
 
14
15
  import { readFileSync } from "node:fs";
15
16
  import { join } from "node:path";
16
- import type { DerivedPriceEntry } from "./price-marker-resolver.ts";
17
+ import type { DerivedPriceEntry } from "../../semantic/price-marker-resolver.ts";
17
18
 
18
19
  export function loadDerivedPrices(
19
20
  cwd: string = process.cwd(),
@@ -32,5 +33,6 @@ export function loadDerivedPrices(
32
33
  }
33
34
  throw err;
34
35
  }
35
- return JSON.parse(raw) as Record<string, DerivedPriceEntry[]>;
36
+ const parsed = JSON.parse(raw) as Record<string, DerivedPriceEntry[]>;
37
+ return Object.keys(parsed).length > 0 ? parsed : null;
36
38
  }
@@ -19,7 +19,7 @@ over the normalized Markdown body (excluding frontmatter).
19
19
  */
20
20
 
21
21
  import { createHash } from "node:crypto";
22
- import type { SemanticPageType } from "./models.ts";
22
+ import type { SemanticPageType } from "../../semantic/models.ts";
23
23
 
24
24
  export interface MarkdownTwinSemanticMeta {
25
25
  id: string;
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { loadDerivedPrices } from "../semantic/derived-prices-loader.ts";
6
+
7
+ describe("loadDerivedPrices", () => {
8
+ it("returns null when file does not exist", () => {
9
+ const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
10
+ try {
11
+ const result = loadDerivedPrices(tmpDir);
12
+ expect(result).toBeNull();
13
+ } finally {
14
+ rmSync(tmpDir, { recursive: true });
15
+ }
16
+ });
17
+
18
+ it("returns null for empty {} content (RFC-1074)", () => {
19
+ const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
20
+ try {
21
+ const srcDir = join(tmpDir, "src");
22
+ mkdirSync(srcDir, { recursive: true });
23
+ writeFileSync(join(srcDir, "derived-prices.generated.json"), "{}\n");
24
+ const result = loadDerivedPrices(tmpDir);
25
+ expect(result).toBeNull();
26
+ } finally {
27
+ rmSync(tmpDir, { recursive: true });
28
+ }
29
+ });
30
+
31
+ it("loads and parses JSON when file exists", () => {
32
+ const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
33
+ try {
34
+ const srcDir = join(tmpDir, "src");
35
+ mkdirSync(srcDir, { recursive: true });
36
+ writeFileSync(
37
+ join(srcDir, "derived-prices.generated.json"),
38
+ JSON.stringify({
39
+ "https://warpgogol.com/id/offerings/hosting": [
40
+ {
41
+ chargeRef: "monthly",
42
+ targetCurrency: "USD",
43
+ amount: { value: "15", currency: "USD" },
44
+ trace: {
45
+ source: { amount: "10", currency: "EUR" },
46
+ rate: { value: "0.9", pair: "EUR/USD" },
47
+ },
48
+ },
49
+ ],
50
+ }),
51
+ );
52
+ const result = loadDerivedPrices(tmpDir);
53
+ expect(result).not.toBeNull();
54
+ expect(Object.keys(result!)).toContain("https://warpgogol.com/id/offerings/hosting");
55
+ } finally {
56
+ rmSync(tmpDir, { recursive: true });
57
+ }
58
+ });
59
+ });
@@ -0,0 +1,152 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ AUDIENCE_BY_PAGE_TYPE,
4
+ buildMarkdownTwin,
5
+ buildMarkdownTwinFrontmatter,
6
+ computeContentHash,
7
+ parseMarkdownTwinFrontmatter,
8
+ verifyMarkdownTwinHash,
9
+ type MarkdownTwinProvenance,
10
+ } from "../semantic/markdown-twin-provenance.ts";
11
+
12
+ const baseProvenance: MarkdownTwinProvenance = {
13
+ canonical: "https://example.com/de/page",
14
+ language: "de",
15
+ lastModified: "2024-01-15",
16
+ license: "CC-BY-4.0",
17
+ generator: "test",
18
+ sourceKind: "authored",
19
+ };
20
+
21
+ describe("computeContentHash", () => {
22
+ it("produces sha256: prefix", () => {
23
+ expect(computeContentHash("body text").startsWith("sha256:")).toBe(true);
24
+ });
25
+
26
+ it("is deterministic for same input", () => {
27
+ expect(computeContentHash("body")).toBe(computeContentHash("body"));
28
+ });
29
+
30
+ it("normalizes trailing whitespace", () => {
31
+ expect(computeContentHash("body\n\n")).toBe(computeContentHash("body"));
32
+ });
33
+
34
+ it("normalizes CRLF to LF", () => {
35
+ expect(computeContentHash("a\r\nb")).toBe(computeContentHash("a\nb"));
36
+ });
37
+ });
38
+
39
+ describe("buildMarkdownTwinFrontmatter", () => {
40
+ it("includes all core provenance fields", () => {
41
+ const fm = buildMarkdownTwinFrontmatter(baseProvenance, "sha256:abc");
42
+ expect(fm).toContain('canonical: "https://example.com/de/page"');
43
+ expect(fm).toContain('language: "de"');
44
+ expect(fm).toContain('lastModified: "2024-01-15"');
45
+ expect(fm).toContain('contentHash: "sha256:abc"');
46
+ expect(fm).toContain('license: "CC-BY-4.0"');
47
+ expect(fm).toContain('generator: "test"');
48
+ expect(fm).toContain('sourceKind: "authored"');
49
+ expect(fm).toContain('schema: "gogol.markdown-twin@2"');
50
+ });
51
+
52
+ it("emits null for lastModified when null", () => {
53
+ const fm = buildMarkdownTwinFrontmatter(
54
+ { ...baseProvenance, lastModified: null },
55
+ "sha256:abc",
56
+ );
57
+ expect(fm).toContain("lastModified: null");
58
+ });
59
+
60
+ it("includes pageId when provided", () => {
61
+ const fm = buildMarkdownTwinFrontmatter(
62
+ { ...baseProvenance, pageId: "about" },
63
+ "sha256:abc",
64
+ );
65
+ expect(fm).toContain('pageId: "about"');
66
+ });
67
+
68
+ it("includes sourceInputs when provided", () => {
69
+ const fm = buildMarkdownTwinFrontmatter(
70
+ { ...baseProvenance, sourceInputs: ["file1.md", "file2.md"] },
71
+ "sha256:abc",
72
+ );
73
+ expect(fm).toContain('sourceInputs:');
74
+ expect(fm).toContain('"file1.md"');
75
+ });
76
+
77
+ it("includes semantic meta when provided", () => {
78
+ const fm = buildMarkdownTwinFrontmatter(
79
+ {
80
+ ...baseProvenance,
81
+ semantic: {
82
+ id: "page-1",
83
+ route: "/de/page",
84
+ title: "Page",
85
+ type: "content",
86
+ domain: "content",
87
+ audience: "general",
88
+ lang: "de",
89
+ metaDescription: "A page",
90
+ priority: 0.7,
91
+ tags: ["tag1"],
92
+ },
93
+ },
94
+ "sha256:abc",
95
+ );
96
+ expect(fm).toContain('id: "page-1"');
97
+ expect(fm).toContain('type: "content"');
98
+ expect(fm).toContain("priority: 0.7");
99
+ });
100
+ });
101
+
102
+ describe("buildMarkdownTwin", () => {
103
+ it("produces frontmatter + body", () => {
104
+ const twin = buildMarkdownTwin("# Hello\n\nWorld", baseProvenance);
105
+ expect(twin.startsWith("---\n")).toBe(true);
106
+ expect(twin).toContain("# Hello");
107
+ expect(twin).toContain("World");
108
+ });
109
+ });
110
+
111
+ describe("parseMarkdownTwinFrontmatter", () => {
112
+ it("round-trips buildMarkdownTwin output", () => {
113
+ const body = "# Hello\n\nWorld";
114
+ const twin = buildMarkdownTwin(body, baseProvenance);
115
+ const parsed = parseMarkdownTwinFrontmatter(twin);
116
+ expect(parsed).not.toBeNull();
117
+ expect(parsed!.frontmatter.canonical).toBe("https://example.com/de/page");
118
+ expect(parsed!.frontmatter.language).toBe("de");
119
+ expect(parsed!.body).toBe("# Hello\n\nWorld\n");
120
+ });
121
+
122
+ it("returns null for no frontmatter", () => {
123
+ expect(parseMarkdownTwinFrontmatter("just text")).toBeNull();
124
+ });
125
+ });
126
+
127
+ describe("verifyMarkdownTwinHash", () => {
128
+ it("verifies correct hash", () => {
129
+ const twin = buildMarkdownTwin("# Hello", baseProvenance);
130
+ expect(verifyMarkdownTwinHash(twin)).toBe(true);
131
+ });
132
+
133
+ it("fails for tampered body", () => {
134
+ const twin = buildMarkdownTwin("# Hello", baseProvenance);
135
+ const tampered = twin.replace("# Hello", "# Tampered");
136
+ expect(verifyMarkdownTwinHash(tampered)).toBe(false);
137
+ });
138
+ });
139
+
140
+ describe("AUDIENCE_BY_PAGE_TYPE", () => {
141
+ it("maps home to general", () => {
142
+ expect(AUDIENCE_BY_PAGE_TYPE.home).toBe("general");
143
+ });
144
+
145
+ it("maps projects to developer", () => {
146
+ expect(AUDIENCE_BY_PAGE_TYPE.projects).toBe("developer");
147
+ });
148
+
149
+ it("maps legal to business_owner", () => {
150
+ expect(AUDIENCE_BY_PAGE_TYPE.legal).toBe("business_owner");
151
+ });
152
+ });