@konneal/engine 0.1.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 (285) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +13 -0
  3. package/dist/admin.d.ts +26 -0
  4. package/dist/ai.d.ts +6 -0
  5. package/dist/anchors.d.ts +6 -0
  6. package/dist/answercache.d.ts +22 -0
  7. package/dist/ask.d.ts +5 -0
  8. package/dist/auth.d.ts +12 -0
  9. package/dist/bubble.d.ts +14 -0
  10. package/dist/chunk-LLWPT2XV.js +49 -0
  11. package/dist/chunk-MB74PTRM.js +114 -0
  12. package/dist/chunk-WOGQM7DJ.js +197 -0
  13. package/dist/chunk-WWNCWKKC.js +42 -0
  14. package/dist/completion.d.ts +5 -0
  15. package/dist/config.d.ts +154 -0
  16. package/dist/config.js +37 -0
  17. package/dist/context.d.ts +115 -0
  18. package/dist/conversations.d.ts +5 -0
  19. package/dist/drafts.d.ts +129 -0
  20. package/dist/env.d.ts +57 -0
  21. package/dist/faithfulness.d.ts +5 -0
  22. package/dist/grader.d.ts +3 -0
  23. package/dist/graph.d.ts +13 -0
  24. package/dist/hybrid.d.ts +7 -0
  25. package/dist/index.d.ts +9 -0
  26. package/dist/index.js +5373 -0
  27. package/dist/internal_gateway.d.ts +14 -0
  28. package/dist/lexical.d.ts +7 -0
  29. package/dist/livedata.d.ts +77 -0
  30. package/dist/memories.d.ts +10 -0
  31. package/dist/modelplane.d.ts +61 -0
  32. package/dist/oidc.d.ts +73 -0
  33. package/dist/pipeline.d.ts +57 -0
  34. package/dist/profile.d.ts +2 -0
  35. package/dist/profile.gen.d.ts +70 -0
  36. package/dist/profile.js +8 -0
  37. package/dist/projects.d.ts +8 -0
  38. package/dist/prompts/conversational.md +8 -0
  39. package/dist/prompts/enrichment.md +3 -0
  40. package/dist/prompts/faithfulness.md +1 -0
  41. package/dist/prompts/grader.md +5 -0
  42. package/dist/prompts/listwise.md +3 -0
  43. package/dist/prompts/precision.md +1 -0
  44. package/dist/prompts/reflect.md +1 -0
  45. package/dist/prompts/relevancy.md +1 -0
  46. package/dist/prompts/research.md +10 -0
  47. package/dist/prompts/section-summary.md +5 -0
  48. package/dist/prompts/summarize.md +1 -0
  49. package/dist/prompts/system.md +18 -0
  50. package/dist/prompts/understanding.md +17 -0
  51. package/dist/quota.d.ts +13 -0
  52. package/dist/reflect.d.ts +5 -0
  53. package/dist/refs.d.ts +40 -0
  54. package/dist/refusal.d.ts +9 -0
  55. package/dist/refusal.js +9 -0
  56. package/dist/requestScope.d.ts +26 -0
  57. package/dist/requestScope.js +10 -0
  58. package/dist/research.d.ts +8 -0
  59. package/dist/search.d.ts +4 -0
  60. package/dist/selfquery.d.ts +7 -0
  61. package/dist/session.d.ts +1 -0
  62. package/dist/share.d.ts +2 -0
  63. package/dist/structural.d.ts +27 -0
  64. package/dist/tablecontext.d.ts +11 -0
  65. package/dist/understand.d.ts +11 -0
  66. package/dist/understandContract.d.ts +29 -0
  67. package/dist/verdict.d.ts +24 -0
  68. package/docs/API.md +451 -0
  69. package/docs/ARCHITECTURE.md +302 -0
  70. package/docs/AUDIT-2026-08-24.md +71 -0
  71. package/docs/CONTRIBUTOR-AUDIT-2026-08-25.md +147 -0
  72. package/docs/INGEST-ARCHITECTURE.md +158 -0
  73. package/docs/MCP.md +92 -0
  74. package/docs/METANORMA-AI-SERIALIZATION.md +247 -0
  75. package/docs/MKO-EXPORT-PIPELINE.md +147 -0
  76. package/docs/REDESIGN-NORMATIVE-RAG-ETSI.md +485 -0
  77. package/docs/RESEARCH-SOTA-2026.md +243 -0
  78. package/docs/ROADMAP-SOTA.md +130 -0
  79. package/docs/SOTA-STAGE-SPECS.md +509 -0
  80. package/docs/annealment/F1-verdict.md +27 -0
  81. package/docs/annealment/F10-notes.md +19 -0
  82. package/docs/annealment/F11-composition.md +17 -0
  83. package/docs/annealment/F12-passport.md +17 -0
  84. package/docs/annealment/F2-counterfactual.md +20 -0
  85. package/docs/annealment/F3-absence.md +21 -0
  86. package/docs/annealment/F4-instance.md +18 -0
  87. package/docs/annealment/F5-workflow.md +21 -0
  88. package/docs/annealment/F6-impact.md +21 -0
  89. package/docs/annealment/F7-editions.md +18 -0
  90. package/docs/annealment/F8-selfverify.md +19 -0
  91. package/docs/annealment/F9-projection-qa.md +17 -0
  92. package/docs/annealment/L0-locate.md +19 -0
  93. package/docs/annealment/L1-extract.md +18 -0
  94. package/docs/annealment/L2-nomenclature.md +22 -0
  95. package/docs/annealment/L3-geometry.md +23 -0
  96. package/docs/annealment/L4-composition.md +21 -0
  97. package/docs/annealment/L5-cross-standard.md +20 -0
  98. package/docs/annealment/L6-diachrony.md +21 -0
  99. package/docs/annealment/L7-perception.md +20 -0
  100. package/docs/annealment/L8-computation.md +22 -0
  101. package/docs/annealment/L9-instance-process.md +23 -0
  102. package/docs/annealment/README.md +10 -0
  103. package/docs/guidelines-metanorma-ai-programme.md +279 -0
  104. package/docs/identity-onboarding-rag.md +65 -0
  105. package/docs/identity-service.md +219 -0
  106. package/docs/knowledge-annealment.md +273 -0
  107. package/docs/konneal-extraction-plan.md +481 -0
  108. package/docs/metanorma-for-ai.md +270 -0
  109. package/docs/mirror-plan.md +36 -0
  110. package/docs/multi-sdo-architecture.md +191 -0
  111. package/docs/paper-annealment-comparison.md +259 -0
  112. package/docs/paper-assets/architecture.svg +94 -0
  113. package/docs/paper-assets/contract-v2.svg +94 -0
  114. package/docs/paper-assets/mko-ingest.svg +91 -0
  115. package/docs/paper-oiml-bulletin.md +402 -0
  116. package/docs/paper-oiml-bulletin.mdx +419 -0
  117. package/docs/product-branding-options.md +172 -0
  118. package/docs/projects-design.md +88 -0
  119. package/docs/sota-mechanisms.md +184 -0
  120. package/docs/spec-api.md +77 -0
  121. package/docs/spec-pipeline.md +126 -0
  122. package/docs/vector-adapter.md +88 -0
  123. package/package.json +70 -0
  124. package/profile/corpora.yaml +5 -0
  125. package/profile/datasets.yaml +14 -0
  126. package/profile/prompts.yaml +5 -0
  127. package/profile/publisher.yaml +17 -0
  128. package/profile/retrieval.yaml +1 -0
  129. package/profile/sources.yaml +5 -0
  130. package/profile/ui.yaml +7 -0
  131. package/scripts/gen_profile.mjs +33 -0
  132. package/workers/shared/ai.ts +21 -0
  133. package/workers/shared/auth.ts +16 -0
  134. package/workers/shared/chunk.ts +108 -0
  135. package/workers/shared/oidc.ts +312 -0
  136. package/workers/shared/router.ts +45 -0
  137. package/workers/shared/session.ts +104 -0
  138. package/workers/worker_internal/src/index.ts +157 -0
  139. package/workers/worker_internal/tsconfig.json +15 -0
  140. package/workers/worker_internal/wrangler.toml +32 -0
  141. package/workers/worker_mcp/src/index.ts +175 -0
  142. package/workers/worker_mcp/tsconfig.json +13 -0
  143. package/workers/worker_mcp/wrangler.toml +18 -0
  144. package/workers/worker_public/migrations/0002_conversations.sql +22 -0
  145. package/workers/worker_public/migrations/0003_shared_conversations.sql +9 -0
  146. package/workers/worker_public/migrations/0004_graph.sql +16 -0
  147. package/workers/worker_public/migrations/0005_documents.sql +19 -0
  148. package/workers/worker_public/migrations/0006_conversation_entities.sql +11 -0
  149. package/workers/worker_public/migrations/0007_chunks_fts.sql +43 -0
  150. package/workers/worker_public/migrations/0008_unit_payloads.sql +15 -0
  151. package/workers/worker_public/migrations/0009_chunks_unit.sql +8 -0
  152. package/workers/worker_public/migrations/0009_message_context.sql +7 -0
  153. package/workers/worker_public/migrations/0010_model_nodes.sql +33 -0
  154. package/workers/worker_public/migrations/0011_schema_union.sql +38 -0
  155. package/workers/worker_public/migrations/0012_memories.sql +15 -0
  156. package/workers/worker_public/migrations/0013_projects.sql +21 -0
  157. package/workers/worker_public/node_modules/@cloudflare/workers-types/2021-11-03/index.d.ts +16306 -0
  158. package/workers/worker_public/node_modules/@cloudflare/workers-types/2021-11-03/index.ts +16261 -0
  159. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-01-31/index.d.ts +16373 -0
  160. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-01-31/index.ts +16328 -0
  161. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-03-21/index.d.ts +16382 -0
  162. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-03-21/index.ts +16337 -0
  163. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-08-04/index.d.ts +16383 -0
  164. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-08-04/index.ts +16338 -0
  165. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-10-31/index.d.ts +16403 -0
  166. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-10-31/index.ts +16358 -0
  167. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-11-30/index.d.ts +16408 -0
  168. package/workers/worker_public/node_modules/@cloudflare/workers-types/2022-11-30/index.ts +16363 -0
  169. package/workers/worker_public/node_modules/@cloudflare/workers-types/2023-03-01/index.d.ts +16414 -0
  170. package/workers/worker_public/node_modules/@cloudflare/workers-types/2023-03-01/index.ts +16369 -0
  171. package/workers/worker_public/node_modules/@cloudflare/workers-types/2023-07-01/index.d.ts +16414 -0
  172. package/workers/worker_public/node_modules/@cloudflare/workers-types/2023-07-01/index.ts +16369 -0
  173. package/workers/worker_public/node_modules/@cloudflare/workers-types/README.md +135 -0
  174. package/workers/worker_public/node_modules/@cloudflare/workers-types/entrypoints.svg +53 -0
  175. package/workers/worker_public/node_modules/@cloudflare/workers-types/experimental/index.d.ts +17095 -0
  176. package/workers/worker_public/node_modules/@cloudflare/workers-types/experimental/index.ts +17050 -0
  177. package/workers/worker_public/node_modules/@cloudflare/workers-types/index.d.ts +16306 -0
  178. package/workers/worker_public/node_modules/@cloudflare/workers-types/index.ts +16261 -0
  179. package/workers/worker_public/node_modules/@cloudflare/workers-types/latest/index.d.ts +16447 -0
  180. package/workers/worker_public/node_modules/@cloudflare/workers-types/latest/index.ts +16402 -0
  181. package/workers/worker_public/node_modules/@cloudflare/workers-types/oldest/index.d.ts +16306 -0
  182. package/workers/worker_public/node_modules/@cloudflare/workers-types/oldest/index.ts +16261 -0
  183. package/workers/worker_public/node_modules/@cloudflare/workers-types/package.json +11 -0
  184. package/workers/worker_public/package.json +13 -0
  185. package/workers/worker_public/prompts/conversational.md +8 -0
  186. package/workers/worker_public/prompts/enrichment.md +3 -0
  187. package/workers/worker_public/prompts/faithfulness.md +1 -0
  188. package/workers/worker_public/prompts/grader.md +5 -0
  189. package/workers/worker_public/prompts/listwise.md +3 -0
  190. package/workers/worker_public/prompts/precision.md +1 -0
  191. package/workers/worker_public/prompts/reflect.md +1 -0
  192. package/workers/worker_public/prompts/relevancy.md +1 -0
  193. package/workers/worker_public/prompts/research.md +10 -0
  194. package/workers/worker_public/prompts/section-summary.md +5 -0
  195. package/workers/worker_public/prompts/summarize.md +1 -0
  196. package/workers/worker_public/prompts/system.md +18 -0
  197. package/workers/worker_public/prompts/understanding.md +17 -0
  198. package/workers/worker_public/public/app.js +166 -0
  199. package/workers/worker_public/public/index.html +48 -0
  200. package/workers/worker_public/public/style.css +147 -0
  201. package/workers/worker_public/schema.sql +248 -0
  202. package/workers/worker_public/src/admin.ts +358 -0
  203. package/workers/worker_public/src/ai.ts +71 -0
  204. package/workers/worker_public/src/anchors.ts +41 -0
  205. package/workers/worker_public/src/answercache.ts +72 -0
  206. package/workers/worker_public/src/ask.ts +1094 -0
  207. package/workers/worker_public/src/auth.ts +252 -0
  208. package/workers/worker_public/src/bubble.ts +111 -0
  209. package/workers/worker_public/src/completion.ts +75 -0
  210. package/workers/worker_public/src/config.ts +238 -0
  211. package/workers/worker_public/src/context.ts +238 -0
  212. package/workers/worker_public/src/conversations.ts +162 -0
  213. package/workers/worker_public/src/drafts.ts +497 -0
  214. package/workers/worker_public/src/env.ts +90 -0
  215. package/workers/worker_public/src/faithfulness.ts +63 -0
  216. package/workers/worker_public/src/grader.ts +89 -0
  217. package/workers/worker_public/src/graph.ts +63 -0
  218. package/workers/worker_public/src/hybrid.ts +77 -0
  219. package/workers/worker_public/src/index.ts +441 -0
  220. package/workers/worker_public/src/internal_gateway.ts +41 -0
  221. package/workers/worker_public/src/lexical.ts +86 -0
  222. package/workers/worker_public/src/lib/hit.ts +4 -0
  223. package/workers/worker_public/src/lib/http.ts +83 -0
  224. package/workers/worker_public/src/lib/router.ts +4 -0
  225. package/workers/worker_public/src/livedata.ts +334 -0
  226. package/workers/worker_public/src/memories.ts +81 -0
  227. package/workers/worker_public/src/modelplane.ts +213 -0
  228. package/workers/worker_public/src/oidc.ts +333 -0
  229. package/workers/worker_public/src/pipeline.ts +377 -0
  230. package/workers/worker_public/src/ports/blobs.ts +7 -0
  231. package/workers/worker_public/src/ports/cloudflare/adapters.ts +177 -0
  232. package/workers/worker_public/src/ports/kv.ts +8 -0
  233. package/workers/worker_public/src/ports/model.ts +28 -0
  234. package/workers/worker_public/src/ports/runtime.ts +13 -0
  235. package/workers/worker_public/src/ports/store.ts +20 -0
  236. package/workers/worker_public/src/ports/vector.ts +26 -0
  237. package/workers/worker_public/src/profile.gen.ts +101 -0
  238. package/workers/worker_public/src/profile.ts +16 -0
  239. package/workers/worker_public/src/projects.ts +108 -0
  240. package/workers/worker_public/src/prompts.d.ts +6 -0
  241. package/workers/worker_public/src/quota.ts +54 -0
  242. package/workers/worker_public/src/reflect.ts +67 -0
  243. package/workers/worker_public/src/refs.ts +107 -0
  244. package/workers/worker_public/src/refusal.ts +65 -0
  245. package/workers/worker_public/src/requestScope.ts +71 -0
  246. package/workers/worker_public/src/research.ts +126 -0
  247. package/workers/worker_public/src/search.ts +56 -0
  248. package/workers/worker_public/src/selfquery.ts +25 -0
  249. package/workers/worker_public/src/session.ts +4 -0
  250. package/workers/worker_public/src/share.ts +53 -0
  251. package/workers/worker_public/src/stages/conceptGraph.ts +68 -0
  252. package/workers/worker_public/src/stages/conceptSteer.ts +39 -0
  253. package/workers/worker_public/src/stages/corpusScope.ts +25 -0
  254. package/workers/worker_public/src/stages/dedup.ts +10 -0
  255. package/workers/worker_public/src/stages/dense.ts +73 -0
  256. package/workers/worker_public/src/stages/diversity.ts +33 -0
  257. package/workers/worker_public/src/stages/editionCover.ts +63 -0
  258. package/workers/worker_public/src/stages/editionSteer.ts +88 -0
  259. package/workers/worker_public/src/stages/familyBoost.ts +22 -0
  260. package/workers/worker_public/src/stages/federate.ts +22 -0
  261. package/workers/worker_public/src/stages/glossary.ts +65 -0
  262. package/workers/worker_public/src/stages/graphLane.ts +31 -0
  263. package/workers/worker_public/src/stages/hyde.ts +29 -0
  264. package/workers/worker_public/src/stages/index.ts +69 -0
  265. package/workers/worker_public/src/stages/lexicalUnion.ts +21 -0
  266. package/workers/worker_public/src/stages/multiQuery.ts +57 -0
  267. package/workers/worker_public/src/stages/overviewDemote.ts +14 -0
  268. package/workers/worker_public/src/stages/poolOpen.ts +10 -0
  269. package/workers/worker_public/src/stages/propagate.ts +15 -0
  270. package/workers/worker_public/src/stages/rerank.ts +47 -0
  271. package/workers/worker_public/src/stages/seal.ts +16 -0
  272. package/workers/worker_public/src/stages/sectionDescent.ts +61 -0
  273. package/workers/worker_public/src/stages/stdRefNudge.ts +35 -0
  274. package/workers/worker_public/src/stages/subQuery.ts +42 -0
  275. package/workers/worker_public/src/stages/termNudge.ts +24 -0
  276. package/workers/worker_public/src/stages/typedPin.ts +131 -0
  277. package/workers/worker_public/src/stages/types.ts +112 -0
  278. package/workers/worker_public/src/stages/windowFloor.ts +23 -0
  279. package/workers/worker_public/src/structural.ts +171 -0
  280. package/workers/worker_public/src/tablecontext.ts +41 -0
  281. package/workers/worker_public/src/understand.ts +72 -0
  282. package/workers/worker_public/src/understandContract.ts +67 -0
  283. package/workers/worker_public/src/verdict.ts +255 -0
  284. package/workers/worker_public/tsconfig.json +18 -0
  285. package/workers/worker_public/wrangler.toml +104 -0
@@ -0,0 +1,481 @@
1
+ # The Konneal extraction plan — packages, phases, end-state
2
+
3
+ > Status: PLAN v4 (2026-09-13) — adds the multi-cloud posture (§5
4
+ > ports and adapters, §6 state management, §7 the software/infrastructure
5
+ > split). v3's boundary — Konneal is the backend: build pipeline + API
6
+ > plane — is redrawn: **Konneal is
7
+ > the backend** — the build pipeline and the API plane — and nothing
8
+ > else. The user plane (interface, site shell, articles, branding)
9
+ > belongs wholly to the publisher. The shareable surface between them
10
+ > is the documented API plus one small package: `@konneal/client`, the
11
+ > API types, the streaming client and the contract-bound renderers
12
+ > (typed blocks, citations, the in-context document pane). v3 keeps the
13
+ > v2 guarantees — content build first-class (§2.1), real customization
14
+ > (§2.2, now by ownership rather than theming), publisher-owned
15
+ > Cloudflare topology (§2.3) — and simplifies the extraction
16
+ > accordingly. Extends docs/multi-sdo-architecture.md §7 (whose
17
+ > step 1, the profile extraction, is shipped) into the full package
18
+ > topology and the phased extraction. The discipline is the one this
19
+ > codebase already keeps: every phase lands with zero behavior change,
20
+ > the drift and contract tests green, and the promotion gates passing
21
+ > against production.
22
+
23
+ ## 1. The principle that shapes everything
24
+
25
+ Two facts decide the package boundaries:
26
+
27
+ 1. **The wire contract is two-sided and must never split.** The chunk
28
+ wire type (`workers/shared/chunk.ts`) and the producer-side adapter
29
+ (`ingest/vector_adapter.py`) are two expressions of one contract,
30
+ held together today by a contract test. They live or break together,
31
+ so the serving workers and the ingest CLI ship from ONE repository,
32
+ versioned in lockstep.
33
+ 2. **A deployment is configuration, branding and content — nothing
34
+ else.** The end-state of `oimlsmart/ai` (the OIML deployment) is a
35
+ profile, a theme, article content, deployment config, and pinned
36
+ references to the content that already lives in its own repositories
37
+ (the corpora, the bibliography, the terminology, the models). "Data
38
+ elsewhere" is already true at the content level; the extraction
39
+ finishes the job at the code level.
40
+
41
+ ## 2. The package topology
42
+
43
+ ```
44
+ konneal/engine (the monorepo — one version train)
45
+ ├── packages/engine-workers/ @konneal/engine (npm)
46
+ │ routes table, ask pipeline, stages, verdict engine, absence,
47
+ │ verify, research, auth relying-party, quota, admin ops
48
+ ├── packages/client/ @konneal/client (npm)
49
+ │ the API types, the SSE client, and the contract-bound
50
+ │ renderers (typed blocks, citations, the document pane)
51
+ ├── packages/profile-schema/ @konneal/profile (npm)
52
+ │ the profile schema, codegen, drift guard
53
+ ├── ingest/ konneal-ingest (PyPI)
54
+ │ parse/chunk/embed/upsert/enrich/replay/reconcile/restore +
55
+ │ the wire adapter (reads profile/*.yaml directly)
56
+ ├── harness/ (in-repo tooling)
57
+ │ the eval runners (grade/golden/annealment/variance/ui) —
58
+ │ content-neutral; suites come from a profile
59
+ └── docs/
60
+ spec-pipeline, spec-api, INGEST-ARCHITECTURE, sota-mechanisms,
61
+ multi-sdo-architecture
62
+
63
+ konneal/konneal.github.io the product site (exists)
64
+ konneal/create-publisher template repo (later, phase D):
65
+ npm create @konneal/publisher —
66
+ profile skeleton + wrangler + CI
67
+
68
+ oimlsmart/ai becomes publisher-oiml (reference)
69
+ ├── profile/ publisher.yaml, datasets.yaml, corpora.yaml,
70
+ │ sources.yaml (pinned refs to the content repos),
71
+ │ evals/ (golden + annealment suites — OIML content),
72
+ │ prompts.yaml (voice vars + rare overrides),
73
+ │ codec: oiml-pubid
74
+ ├── theme/ logo, colors, fonts, nav labels
75
+ ├── site/ the ENTIRE user plane, unchanged: the chat app,
76
+ │ the articles (MDX), the annealment panel, branding,
77
+ │ the site shell — consuming @konneal/client for the
78
+ │ contract components
79
+ ├── deploy/ wrangler.toml(s) — bindings, vars, INDEX_VERSION —
80
+ │ and the thin deploy wrapper
81
+ ├── whitepaper/ OIML's academic artifact (content, stays)
82
+ ├── .github/ CI: profile validation + engine-pinned gates
83
+ └── workers/src/ ENTRY ONLY (~10 lines: createWorker({ profile }))
84
+ ```
85
+
86
+ ### 2.1 The content build path (Metanorma and Primmel stay first-class)
87
+
88
+ The build that turns a publisher's Metanorma corpus and Primmel
89
+ packages into a serving index is engine machinery driven by
90
+ profile-declared sources. The engine CLI gains one orchestration
91
+ command:
92
+
93
+ ```
94
+ konneal build --profile profile/
95
+ ```
96
+
97
+ It reads `profile/sources.yaml` — the pinned references to the
98
+ publisher's Metanorma corpora (clean and recovered), relaton
99
+ bibliography, Glossarist terminology, and Primmel packages checkout —
100
+ and runs the derivation in the order the incidents taught, as
101
+ structure rather than memory: parse (clean-beats-dirty precedence,
102
+ shell flagging, language policy from the profile) → typed units from
103
+ the Metanorma documents → the model plane from the Primmel projection
104
+ (the freshness gate: a package's source hash moves, the build fails
105
+ until re-indexed) → terminology and graph ingestion → embed → upsert →
106
+ restore gaps → enrichment replay → reconcile against the canonical
107
+ declaration → unit assets → rendered documents → the answer-cache
108
+ generation stamp. The sequence mistakes that caused the 2026-09-09/10/11
109
+ incidents become impossible for every SDO, not just this one.
110
+
111
+ The build stamps the index with a wire version alongside the existing
112
+ index version, so a deployment never serves an index built by an
113
+ ingest version its serving engine cannot read — the freshness
114
+ mechanism extended from content drift to engine drift.
115
+
116
+ ### 2.2 The interface (owned by the publisher, served by contract)
117
+
118
+ The publisher owns the entire user plane: the chat application, the
119
+ article pages, the site shell of their choosing, the branding, the
120
+ annealment panel, the whitepaper surface. Nothing about their frontend
121
+ waits on an engine release, and nothing about the engine carries their
122
+ taste. OIML's site stays exactly where it is, in the deployment
123
+ repository, including the site-shell dependency it already uses.
124
+
125
+ Two things cross the boundary, and only two:
126
+
127
+ 1. **The documented API** (spec-api.md): ask and search, absence and
128
+ verification, research, sessions, projects and memory files,
129
+ datasets, auth, administration, and the MCP servers. The UI already
130
+ speaks it over HTTP and server-sent events, and the UI test suite
131
+ already runs against stubbed APIs — the seam exists and is proven.
132
+ The memory and project features are backend features: the engine
133
+ owns the D1 schema and CRUD; the publisher's frontend renders them.
134
+ 2. **`@konneal/client`** — a small npm package extracted from the
135
+ current site: the API types, the streaming client, and the
136
+ contract-bound renderers (formula/table/figure/verdict blocks,
137
+ citation chips, the in-context document pane). Renderers of the
138
+ answer contract ship with the contract, so block rendering cannot
139
+ fork and drift from the wire types; pages, layout and everything
140
+ else stay publisher code consuming them.
141
+
142
+ For the second SDO, the Konneal org ships a **forkable UI starter** —
143
+ `konneal/ui-starter`, seeded from OIML's site at extraction and kept
144
+ as a template to copy, not a dependency to pin. Fork-not-depend is the
145
+ honest model for frontends.
146
+
147
+ Backend customization still composes, because publisher logic is not
148
+ only frontend: the OIML-CS application-draft acts are ask-path
149
+ behavior. The worker entry stays composable —
150
+
151
+ ```ts
152
+ createWorker({ profile, hooks: { acts: oimlDraftActs }, extraRoutes })
153
+ ```
154
+
155
+ — with custom routes reusing the engine's handlers and auth, and the
156
+ draft-act branch moving out of the engine's ask path into OIML's hook.
157
+
158
+ ### 2.3 The Cloudflare topology (bindings are the publisher's facts)
159
+
160
+ Wrangler configuration, bindings, secrets and accounts stay in the
161
+ deployment repository untouched — Vectorize indexes, D1, KV, R2,
162
+ Queues, the OIDC issuer are per-publisher facts declared by the
163
+ profile's audiences (the two-index isolation pattern generalizes: one
164
+ index per audience, and the binding lint enforces it against the
165
+ profile's declarations, not a hardcoded list). The engine provides two
166
+ thin commands the deployment wraps: `konneal bootstrap` (create the
167
+ declared indexes/buckets/namespaces, patch ids into wrangler) and
168
+ `konneal deploy` (today's guarded deploy — branch and tree checks,
169
+ version bump, settle, profile-sourced smoke) so the operational
170
+ discipline ships with the engine instead of being re-implemented per
171
+ SDO.
172
+
173
+ **The development loop while both repos live:** the deployment pins
174
+ exact engine versions in its lockfile, with a `file:` override for
175
+ local engine work — the same pattern this repo already uses for the
176
+ site shell. Engine PRs run the engine's fixture matrix; the deployment
177
+ CI runs its own gates on the pinned version; neither blocks the other
178
+ until a release is deliberately adopted.
179
+
180
+ **Versioning.** The engine releases semver from `konneal/engine`; a
181
+ deployment pins exact versions (the same deliberateness as any
182
+ dependency). The wire contract, the UI and the workers share the
183
+ monorepo's version because they share its review. Content drift is
184
+ already governed by the freshness gate (`source_hash`); engine drift
185
+ joins it in the deployment's lockfile.
186
+
187
+ **Why npm/PyPI rather than submodules or a template-only engine.**
188
+ Cloudflare Workers bundle from `node_modules` as a matter of course; a
189
+ real package gives SDOs version pinning, changelogs and upgrade
190
+ paths — the governance the architecture doc named as an open question,
191
+ answered mechanically.
192
+
193
+ ## 3. The remaining publisher facts (the audit delta)
194
+
195
+ Found since the architecture doc; each moves in the phase shown:
196
+
197
+ | Fact | Today | Moves to | Phase |
198
+ |---|---|---|---|
199
+ | Identifier grammar | OIML patterns in `upload_documents.py` + site `docSlug` | profile `codec: oiml-pubid`; engine carries the codec registry | A |
200
+ | Prompt voice | `prompts/system.md` names OIML and the corpus shape | template vars + `profile/prompts.yaml` | A |
201
+ | Eval suites | `tests/golden/*` (OIML questions) | `profile/evals/`; harness reads the profile path | A |
202
+ | Annealment panel data | `site/src/chat/annealmentLadder.ts` | `profile/evals/` (it IS the measured ladder) | A |
203
+ | Process expansion terms | `THRESHOLDS.processExpansion` (OIML-CS/CASCO words) | profile dataset note / expansion list | A |
204
+ | Smoke queries | OIML questions in `deploy.sh` | `profile/evals/smoke` | A |
205
+ | Models table (site) | hardcoded in how-it-works | profile (publisher's model policy disclosure) | A |
206
+ | Glossary/relaton/graph sources | ingest config paths | `profile/sources.yaml` (pinned refs) | A |
207
+
208
+ ## 4. The phases (each independently shippable, gates green)
209
+
210
+ **Phase A — generalize in place** (in `oimlsmart/ai`, zero behavior
211
+ change): everything in §3, the codec registry (the OIML codec wraps the
212
+ pubid library; a plain-slug codec proves genericity), prompt
213
+ templates, evals-to-profile with the harness reading the declared path,
214
+ the profile codegen extended to feed the site. The repo is now
215
+ *conceptually* a profile + engine, with the engine still physically
216
+ inside it.
217
+
218
+ **Phase B — the engine is born** (`konneal/engine`): move the code with
219
+ its history (`git filter-repo` per subtree, so archaeology survives —
220
+ blame for the 40017 fix must still point at the 40017 incident);
221
+ establish the monorepo workspaces, the npm/PyPI packaging, the engine's
222
+ own CI running the harness against a fixture corpus. `oimlsmart/ai`
223
+ keeps running unchanged in parallel.
224
+
225
+ **Phase C — the consumer flip**: `oimlsmart/ai` depends on
226
+ `@konneal/engine@x.y.z`; `workers/` shrinks to the entry; `ingest/` and
227
+ the heavy `scripts/` become dependencies and thin wrappers; CI re-points;
228
+ the full promotion gate runs against production before the flip is
229
+ declared done. Nothing about the deployment's operations changes —
230
+ same wrangler, same bindings, same deploy flow.
231
+
232
+ **Phase D — the ecosystem**: the forkable `konneal/ui-starter` seeded
233
+ from OIML's site, `create-publisher` scaffolding, the reference matrix
234
+ in engine CI (this profile as fixture #1, a second fixture from
235
+ another Metanorma flavor), the product site build in
236
+ `konneal.github.io`, and the public flip of the repos at launch.
237
+
238
+ The backend-only boundary shrinks the extraction itself: Phase B moves
239
+ the workers, ingest, harness and docs — never the site; the client
240
+ package is extracted from the site in Phase C, with the site's
241
+ remaining local copies deleted behind a one-release deprecation so the
242
+ flip is a lockfile change, not a rewrite. The UI test suite stays in
243
+ the deployment repo (it tests the deployment's frontend); the engine's
244
+ CI tests the API plane, which the golden and annealment runners
245
+ already exercise over HTTP.
246
+
247
+ ## 5. Invariants that make each phase safe
248
+
249
+ - The profile drift test (YAML ≡ codegen) — exists.
250
+ - The TS↔py wire contract test — exists, moves with the contract.
251
+ - The promotion gates (golden ×3 + annealment ×6) — run at every phase
252
+ boundary against production.
253
+ - The deploy version guard and smoke (now retry-hardened) — unchanged.
254
+ - The binding-isolation lint — moves with the workers, runs in engine
255
+ CI against the fixture profile.
256
+
257
+ ## 6. Honest risks, named
258
+
259
+ - **Workers-from-npm ergonomics**: standard wrangler bundling; verified
260
+ in phase B before the flip, with the current repo as fallback the
261
+ whole time.
262
+ - **Contract-renderer drift**: eliminated where it matters — the
263
+ block renderers ship in `@konneal/client` with the types; the
264
+ publisher's pages cannot fork the contract even though they own the
265
+ frontend. The residual risk is an SDO ignoring the client package in
266
+ a bespoke frontend; the API docs and the MCP surface keep the wire
267
+ honest regardless.
268
+ - **History preservation**: filter-repo per subtree; the reference
269
+ READMEs cross-link so the archaeology stays reachable from both
270
+ repos.
271
+ - **The whitepaper and articles are OIML's**, not the engine's — they
272
+ stay in the publisher repo; the engine's docs describe mechanisms,
273
+ never this publisher.
274
+ - **Trademark screening** remains the gating step before any public
275
+ Konneal marketing; the repos stay private until it clears.
276
+
277
+ ## 5. Ports and adapters — the multi-cloud posture
278
+
279
+ The engine's domain logic is portable software; infrastructure appears
280
+ only behind narrow ports, each with one reference adapter (Cloudflare,
281
+ because it is proven in production) and a conformance suite. Additional
282
+ adapters are contributed against the suite when a real deployment
283
+ demands them — never speculatively.
284
+
285
+ | Port | Semantics the engine requires | Reference adapter | Other adapters (on demand) |
286
+ |---|---|---|---|
287
+ | `ModelRunner` | run(role, kind, payload, {effort, budget, sampling}); streaming for answers | Workers AI binding | any OpenAI-compatible HTTP endpoint (covers most clouds, gateways and self-hosting; the z.ai vision lane already runs over HTTP — the precedent), Ollama/local |
288
+ | `VectorIndex` | dense query with metadata filters, upsert, getByIds, delete; the scalar-or-string-array metadata law is the PORT contract | Vectorize | pgvector (the universal default), Qdrant, Weaviate, OpenSearch |
289
+ | `Store` | the repositories: documents registry, model plane, unit payloads, sessions, conversations, projects, memory files, API keys, telemetry | D1 (SQLite) | libsql/Turso, Postgres, MySQL |
290
+ | `Kv` | get/put with TTL on the hot read path | Workers KV | Redis (ubiquitous), DynamoDB, in-memory |
291
+ | `Blobs` | put/get/delete immutable objects | R2 | any S3-compatible endpoint — R2 already speaks S3 |
292
+ | `Runtime` | background work after response (waitUntil) | Workers | the Node/Bun equivalents |
293
+ | Optional: `BotCheck` | human verification for the anonymous tier | Turnstile | hCaptcha, none |
294
+
295
+ Design rules that keep the ports honest:
296
+
297
+ - **Lexical search stays in the engine.** Vectorize has no sparse
298
+ vectors, so the lexical lane already runs engine-side over the
299
+ relational store. Adapters therefore need only dense search plus
300
+ filters — the weakest common denominator — and richer backends are a
301
+ superset, never a requirement.
302
+ - **Model policy is deployment data, quirks are adapter facts.** Which
303
+ model serves which role is already configuration (`MODELS` +
304
+ `roleModel` overrides); provider-specific call shaping (the GLM
305
+ effort-budget rule, provider message-shape limits) lives inside the
306
+ adapter and is documented with it.
307
+ - **Port purity is linted.** Domain modules import ports, never
308
+ adapters; the binding lint grows into this check, so an
309
+ infrastructure API cannot leak back into the stages.
310
+ - **The conformance suites are the contract.** The wire law (already
311
+ tested TS↔Python), repository behavior, KV semantics and a
312
+ model round-trip each become suites every adapter must pass — the
313
+ same discipline the profile drift test applies to configuration.
314
+
315
+ **The reference path is zero-configuration.** A Cloudflare deployment
316
+ declares no adapters file and no model policy of its own: the engine
317
+ defaults to the Cloudflare reference adapters, wiring them from
318
+ wrangler.toml's bindings exactly as today, and ships the reference
319
+ model policy (with the `roleModel`/effort environment overrides that
320
+ already exist). Adapter and model-policy configuration appears in a
321
+ deployment repository only when that deployment deviates from the
322
+ reference — which the reference deployment never does. The multi-cloud
323
+ machinery is invisible unless invoked; ai.oimlsmart.org carries none
324
+ of it.
325
+
326
+ **Phasing stance — ports as seams, adapters on demand.** Phases A–C
327
+ proceed Cloudflare-flavored exactly as planned; Phase B introduces the
328
+ port boundaries as interfaces with the Cloudflare adapter as the sole
329
+ implementation. The engine becomes adapter-shaped without paying for a
330
+ second adapter. When a concrete SDO requires another cloud, the work
331
+ is implementing adapters against existing conformance suites plus
332
+ their infrastructure configuration — a focused contribution, not a
333
+ rewrite, because the seams already exist.
334
+
335
+ ## 6. State management — the taxonomy that answers migration
336
+
337
+ Every piece of state is classified, and the class determines its
338
+ multi-cloud story:
339
+
340
+ | Class | Contents | Multi-cloud story |
341
+ |---|---|---|
342
+ | **Rebuildable** (derived corpus) | vector indexes, unit payloads, model-plane nodes, rendered documents, unit assets | **Rebuild, never migrate.** The derivation pipeline is the chain of custody: pinned sources → `konneal build` → state. Moving clouds is re-running the build against the new target; the canonical-set declaration and reconciliation verify the result. This is the dividend of "data elsewhere". |
343
+ | **Live** (user and tenant state) | sessions, conversations, projects, memory files, API keys | **Export/import through the ports.** `konneal state export|import` walks the repositories; portable precisely because the repositories are ported. |
344
+ | **Ephemeral** (by design) | answer caches (exact + semantic), enrichment contexts, quota counters | **No migration.** TTLs and the corpus-generation stamp already treat this state as disposable; a new deployment cold-starts and converges within the TTL window (quota counters accept a day-boundary reset — documented, not hidden). |
345
+ | **Analytics** | query and spend telemetry | **Export or cut over** — append-only rows; the deployment chooses import-for-continuity or a clean cutover. |
346
+
347
+ Secrets, bindings and domains are infrastructure configuration in the
348
+ deployment repository and never migrate through the engine at all.
349
+
350
+ ## 7. Software versus infrastructure — the split, stated as law
351
+
352
+ - **Software (the engine ships it):** the retrieval stages and scoring,
353
+ the answer contract and its enforcement, the verdict engine, the
354
+ build derivation and its invariants, the evaluation harness, the
355
+ profile system, the HTTP route table and API surface, the OIDC
356
+ relying-party logic, quota and cache semantics, the port definitions,
357
+ the Cloudflare adapters, and the conformance suites. None of it knows
358
+ an account id, a binding name or a provider catalog.
359
+ - **Infrastructure (the deployment declares it):** the choice and
360
+ configuration of adapters, bindings, accounts and credentials, the
361
+ model policy (which concrete models serve which roles, at what
362
+ pricing), capacity and limits, scheduling, domains and CDN.
363
+ - **The law:** infrastructure appears in the engine only behind a
364
+ port, one reference adapter per port, conformance-tested. The
365
+ current codebase is already close: the ingest CLI speaks provider
366
+ REST through one class, the restore/replay tools proved both binding
367
+ and HTTP lanes for the same operations, and every provider gotcha
368
+ (getByIds above twenty, the metadata law, the effort-budget rule) is
369
+ already documented as a fact rather than scattered as folklore. The
370
+ extraction formalizes what the incidents already taught.
371
+
372
+ ## 8. Worked examples — the full stack on AWS or Azure
373
+
374
+ What follows is what a deployment actually configures on a full-stack
375
+ hyperscaler, and what stays untouched in the engine. The profile is
376
+ identical on every cloud; only the adapter wiring and infrastructure
377
+ configuration differ.
378
+
379
+ ### 8.1 The per-port mapping
380
+
381
+ | Port | AWS | Azure |
382
+ |---|---|---|
383
+ | Compute for the API plane | containers (ECS Fargate / App Runner) behind ALB or API Gateway | Container Apps / App Service / Functions |
384
+ | `ModelRunner` | Bedrock models, or self-hosted open-weight models on EC2/SageMaker behind an OpenAI-compatible endpoint (vLLM) | Azure AI Foundry endpoints (OpenAI-compatible), or the same self-hosted lane |
385
+ | `VectorIndex` | pgvector on Aurora/RDS Postgres (or OpenSearch) | pgvector on Azure Database for PostgreSQL (or Azure AI Search — a superset: vectors, filters and BM25) |
386
+ | `Store` | Aurora/RDS Postgres | Azure Database for PostgreSQL |
387
+ | `Kv` | ElastiCache Redis | Azure Cache for Redis |
388
+ | `Blobs` | S3 | Azure Blob Storage (S3-interop or a thin adapter) |
389
+ | `Runtime` (waitUntil) | the container adapter (no isolate limits) | same |
390
+ | Scheduling | EventBridge Scheduler → the engine's `/admin/tick` route | a scheduled job → the same route |
391
+ | `BotCheck` | Turnstile — a cloud-neutral web service, unchanged | unchanged |
392
+
393
+ ### 8.2 What the SDO configures (the deployment repository)
394
+
395
+ ```
396
+ publisher-deployment/
397
+ ├── profile/ # IDENTICAL on every cloud: publisher, datasets,
398
+ │ # corpora, evals, sources.yaml (pinned content
399
+ │ # refs), prompts, codec
400
+ ├── adapters.yaml # the port→implementation choice + endpoints:
401
+ │ # vector: pgvector(postgres-url), store: postgres,
402
+ │ # kv: redis, blobs: s3, models: openai-compatible(base-url)
403
+ ├── model-policy.yaml # role→model mapping over THIS cloud's catalog,
404
+ │ # with pricing and the per-family call rules
405
+ ├── infra/ # Terraform/CDK/Bicep: the database, Redis, the
406
+ │ # bucket, DNS/CDN, secrets, the container service,
407
+ │ # the scheduler — the cloud's own language
408
+ ├── deploy/ # pipeline: build the container, deploy,
409
+ │ # konneal bootstrap (schema + index declaration),
410
+ │ # konneal build, konneal deploy (guards + smoke)
411
+ └── CI # profile validation + engine-pinned gates,
412
+ # exactly as on Cloudflare
413
+ ```
414
+
415
+ `konneal bootstrap` and `konneal build` run the same code everywhere:
416
+ bootstrap applies the repository schema and the index declaration
417
+ through the chosen adapters; build reads `profile/sources.yaml` and
418
+ runs the derivation into the declared state.
419
+
420
+ ### 8.3 What remains platform-independent (in Konneal)
421
+
422
+ All of the domain, unchanged and untested-differently per cloud: the
423
+ retrieval stages and scoring, the answer contract and its enforcement,
424
+ the verdict engine, provable absence, verification, the research loop,
425
+ sessions/projects/memory-file logic, quota and cache semantics, the
426
+ build derivation and its invariants (canonical set, wire law, replay),
427
+ the evaluation harness and grading semantics, the profile system, the
428
+ HTTP route table and API surface, the MCP servers, `@konneal/client`,
429
+ the port definitions, the conformance suites, and the Cloudflare
430
+ reference adapters.
431
+
432
+ ### 8.4 The honest deltas
433
+
434
+ 1. **Model catalogs differ — the one real delta.** The reference cost
435
+ policy rides Cloudflare's open-weight catalog. A hyperscaler
436
+ deployment either maps roles onto that cloud's catalog in
437
+ `model-policy.yaml`, or keeps the exact policy by serving the same
438
+ open-weight models itself behind an OpenAI-compatible endpoint —
439
+ the adapter makes self-hosting a first-class lane, which is the
440
+ documented fallback posture already.
441
+ 2. **The execution model loosens, not tightens.** Containers have none
442
+ of the isolate limits (subrequest counts, topK caps) the engine
443
+ already respects; the engine asks every adapter for the weakest
444
+ common denominator, so nothing breaks and richer backends are a
445
+ bonus.
446
+ 3. **Deploy tooling is the cloud's own.** Wrangler is Cloudflare's;
447
+ AWS and Azure deployments carry Terraform/CDK/Bicep in `infra/`.
448
+ The guarded deploy semantics (version discipline, smoke, gates) are
449
+ engine commands and travel intact.
450
+ 4. **Dialect and behavior drift** across relational backends is the
451
+ conformance suites' job — an adapter ships only when the repository
452
+ suite passes against it.
453
+
454
+ ## 9. Impact on the reference deployment (ai.oimlsmart.org)
455
+
456
+ **At runtime: nothing changes, at any phase.** Phases A–C are
457
+ behavior-preserving by construction — the port interfaces erase at
458
+ runtime, the adapters call the exact same bindings, and every phase
459
+ boundary runs the full promotion gate against production before it is
460
+ declared done. The infrastructure, the models, the index, the caches
461
+ and the operational loop (build, reconcile, replay, deploy guards,
462
+ gates) are untouched.
463
+
464
+ **The one-time transition cost (Phase C):** the workers directory
465
+ shrinks to a ~10-line entry, the engine arrives as a pinned package,
466
+ and the flip deploys behind the standing gate protocol with instant
467
+ rollback to the previous worker version. After the flip, the
468
+ deployment repository contains only: the profile (which is the
469
+ publisher's own data, half-extracted already), the theme, the entire
470
+ user plane (unchanged), wrangler configuration (unchanged), the entry,
471
+ the whitepaper and CI. The repository gets smaller, not bigger, and
472
+ the deploy command remains what it is today.
473
+
474
+ **The new discipline — and why it is a net reduction of concern:**
475
+ engine upgrades arrive as deliberate version bumps instead of
476
+ entangled commits, the port-purity lint prevents infrastructure
477
+ leakage regressions for everyone including this deployment, and the
478
+ conformance suites hold the behavior the reference deployment depends
479
+ on. The configuration surface that other clouds require (adapters,
480
+ model policy, infrastructure code) never exists here, because the
481
+ reference is the default.