@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,485 @@
1
+ # Normative RAG Redesign — Learning from the ETSI Experience
2
+
3
+ *Primary source: Al Masoud, Arazzi, Germani, Nocera (Univ. Pavia + CEI),
4
+ "Exploring Structural Complexity in Normative RAG with Graph-based approaches:
5
+ A case study on the ETSI Standards", arXiv:2604.09868, Jan 2026.
6
+ Secondary primaries only where they corroborate a specific claim (cited inline).
7
+ This supersedes the structure/graph sections of RESEARCH-SOTA-2026.md and
8
+ ROADMAP-SOTA.md for retrieval design. 2026-08-27.*
9
+
10
+ ---
11
+
12
+ ## 0. Why this paper is the authority for us
13
+
14
+ It is the only published empirical study of RAG **on industrial standards**
15
+ (ETSI EN 301 489-X, ≈50 documents, ≈3000 pages, 800+ synthetic Q&A with
16
+ witness-string golden chunks). Co-authored with CEI (Italian Electrotechnical
17
+ Committee) — a standards body, not a vendor lab. Their problem statement is
18
+ ours word-for-word:
19
+
20
+ > standards are highly cross-referential, semi-structured, and make use of
21
+ > specialized formal vocabulary… dense text embeddings… overlook [precise
22
+ > keywords] in favor of fuzzier semantic similarity… parent-child (and
23
+ > sibling-to-sibling) dynamics between chunks [are] a relevant factor.
24
+
25
+ They evaluate **lightweight, low-latency** modules only — no GNN training,
26
+ no agentic loops in the measured stack. That matches our Cloudflare /
27
+ cost-first constraint. Their conclusions are measured, not hyped. We treat
28
+ them as load-bearing.
29
+
30
+ ---
31
+
32
+ ## 1. Their Information Model (the contract we must match)
33
+
34
+ ```
35
+ IG = (IU, E) InfoUnits + Edges
36
+ IU node = {title, body}
37
+ E = P ∪ C Parthood ∪ Citation
38
+ ```
39
+
40
+ | Relation | Semantics | Cardinality |
41
+ |---|---|---|
42
+ | **P (parthood)** | document→section, section→subsection; section code prefix (`4.1` parent of `4.1.2`) | tree (≤1 parent) |
43
+ | **C (citation)** | internal (same doc, section-only mention) or external (doc name ± section) | many-to-many |
44
+ | Ancestry | transitive closure of P; same publication ⇔ share common ancestor | derived |
45
+
46
+ Construction rules that matter:
47
+
48
+ 1. **ToC → ordered InfoUnits**, then P from section-code prefix geometry.
49
+ 2. **Oversized sections may split** — children of the original section
50
+ (Structured + Chunks). Flat chunking alone is the baseline they beat.
51
+ 3. **Tabular sections are exempted from being chunked.** Atomic units.
52
+ 4. **Empty-body InfoUnits are valid** (a section title that immediately
53
+ opens a subsection; a top-level document node).
54
+ 5. **Citation resolve heuristic:** section-only → internal; doc-name-only →
55
+ document; both → that section of that document.
56
+ 6. They explicitly flag the **IEC Smart Standards** machine-readable
57
+ framework as the upgrade path when content is no longer PDF-scraped —
58
+ i.e. our Metanorma/#592 direction, named from the standards world.
59
+
60
+ ---
61
+
62
+ ## 2. Their modules and measured outcomes (the only numbers that matter)
63
+
64
+ Eight configurations × three K values. Variants: Vanilla (flat 300-word
65
+ chunks) vs Structured (official section hierarchy) vs Structured+Chunks
66
+ (hierarchy, split when oversized). Modules stacked on top.
67
+
68
+ | Module | What it does | Measured effect on ETSI corpus |
69
+ |---|---|---|
70
+ | **Structure preservation** (P in the index) | section hierarchy as the chunk boundary | **↑ precision, ↑ MRR; recall ≈ flat (not significant)** |
71
+ | **Structured + Chunks** | hierarchy + split oversized sections | **overall best compromise** |
72
+ | **BM25 prefilter → dense rerank → RRF** | sparse first (exact jargon), dense for meaning, fuse | **↑ precision, ↑ MRR; recall unchanged** (expected — fusion reorders, doesn't recover) |
73
+ | **Embedding smoothing** `em ← α·em + (1-α)·mean(N(u))` | blend each node embedding with parent/children/siblings/citation neighbors; lightweight alternative to GNN graph-embeddings | **slight ↑ recall** — the only module that moved recall |
74
+ | **Neighbor expansion + graph re-rank** (seed → neighbors, hub penalty) | post-retrieval graph walk | **not effective** — scoring function inadequate for the domain |
75
+
76
+ Their conclusion, verbatim force:
77
+
78
+ > the methods we have tested mostly improve the **precision** of retrieval,
79
+ > and **structure-preservation with chunking** seems to be the overall best
80
+ > compromise.
81
+ >
82
+ > Neighbor expansion… does not seem to be effective, indicating that more
83
+ > work is needed…
84
+ >
85
+ > Smoothing slightly improves recall… promising way of embedding relational
86
+ > information into the index.
87
+
88
+ Future work they name: multi-hop synthesis across distant passages / across
89
+ documents; hybrid solutions for that class; evaluation on broader Q&A with
90
+ more complex link structure.
91
+
92
+ ---
93
+
94
+ ## 3. Audit of OIML SMART AI against the ETSI stack
95
+
96
+ ### 3.1 What we already get right (keep, do not rebuild)
97
+
98
+ | ETSI requirement | Our status | Evidence |
99
+ |---|---|---|
100
+ | Structure-preserving chunk boundaries | ✅ clause-boundary sections from Metanorma HTML/adoc | `ingest/parse.py`, `chunk.py` |
101
+ | Structured + Chunks (split oversized) | ✅ `split_long` on section text | `chunk.py` |
102
+ | Dense + lexical RRF | ⚠️ partial — see 3.2 | `hybrid.ts` + `pipeline.ts` post-rerank RRF |
103
+ | Cross-encoder rerank | ✅ bge-reranker-base | beyond their Granite-only dense |
104
+ | Document-level citation / supersession graph | ✅ successor, part_of (doc↔family), defines | `ingest/graph.py`, D1 registry |
105
+ | Edition/authority steering | ✅ derived active edition (status field lies) | beyond ETSI scope; matches 2026 freshness scoring |
106
+ | Contextual enrichment | ✅ 99.4% corpus | Anthropic recipe; they have none — we are ahead on context-in-embedding |
107
+ | Machine-readable source path | 🟡 hand-rolled; #592 is the contract | they name IEC Smart Standards; we have Metanorma |
108
+ | Generation-side grounding | ✅ quote anchors, CRAG, reflection, faithfulness judges | out of their retrieval-only scope |
109
+ | Don't over-invest neighbor expansion | ✅ graph lane is terminology-only (`defined_terms→defines→doc_numbers`) | aligns with their negative result |
110
+
111
+ ### 3.2 Gaps the ETSI evidence says are material (ordered by measured impact)
112
+
113
+ #### G-ETSI-1 — Lexical retrieval is a post-filter, not a prefilter 【CRITICAL】
114
+
115
+ **ETSI:** BM25 is the *first* query-time stage — high-recall, low-latency
116
+ prune of the full corpus on exact keywords (standards jargon), *then* dense
117
+ rerank, *then* RRF.
118
+
119
+ **Us:** `keywordRank` + `rrfFuse` run **only over the dense top-K already
120
+ retrieved** (`pipeline.ts` after Vectorize). If dense never recalled the
121
+ chunk, lexical cannot recover it. We re-order; we do not recall.
122
+
123
+ Vectorize has no sparse vectors (platform fact). The fix is not "wait for
124
+ Vectorize" — it is a **corpus-wide inverted index we own**:
125
+
126
+ - D1 FTS5 over `chunk_id + text` (or a dedicated terms table), OR
127
+ - build posting lists at ingest into KV/R2, query in-worker.
128
+
129
+ BM25 (or BM25-ish with real IDF from corpus stats) returns top-N ids → fetch
130
+ vectors/metadata → union with dense top-K → RRF → cross-encoder. This is
131
+ exactly their II-B5→6→7 cascade, and it is the single highest-leverage
132
+ gap their numbers identify for a standards corpus.
133
+
134
+ #### G-ETSI-2 — No section-level parthood in the retrieval graph 【HIGH】
135
+
136
+ **ETSI InfoModel:** every InfoUnit participates in P; ancestry is
137
+ queryable; siblings and parents are first-class neighbors for smoothing
138
+ and (attempted) expansion.
139
+
140
+ **Us:** `clause_anchor` is a **string on chunk metadata**. The D1 graph has
141
+ doc↔family `part_of` and concept `defines`, but **not**
142
+ `clause:R-60-1:2021:4.1 —part_of→ clause:R-60-1:2021:4`. Parent/sibling
143
+ geometry is not traversable at query time and cannot feed smoothing.
144
+
145
+ Fix at ingest: for every chunk with anchor `A.B.C`, emit
146
+ `part_of` edges up the anchor tree + a `section` node per unique anchor.
147
+ Empty-body section nodes (title-only parents) are valid per ETSI.
148
+
149
+ #### G-ETSI-3 — No internal citation edges 【HIGH】
150
+
151
+ **ETSI:** C is half the edge set. "§4.1 (see also §6.3)" and "as required
152
+ by OIML R 76-1:2006 §3.5" are first-class. Resolve heuristic is simple and
153
+ domain-correct.
154
+
155
+ **Us:** relaton gives *document-level* bibliographic edges. Clause-body
156
+ mentions of other clauses/documents are not extracted into C. The graph
157
+ cannot answer "what does this clause require me to also read?"
158
+
159
+ Fix at ingest: citation mention parser over chunk text (section-id /
160
+ docidentifier patterns we already normalize via pubid-ish regexes) →
161
+ resolve against the section-node index from G-ETSI-2 → `cites` edges.
162
+ External unresolved mentions stay as string-valued edge targets (public
163
+ projection rule already forbids leaking ISO titles).
164
+
165
+ #### G-ETSI-4 — No embedding smoothing 【HIGH — only measured recall lever】
166
+
167
+ **ETSI eq. (10):**
168
+ `em_j ← α·em_j + (1-α)·mean({em_n : n ∈ N(j)})`
169
+ where N = parent ∪ children ∪ siblings ∪ in/out citations.
170
+
171
+ This is the **only module that moved recall**. It is offline (index-time),
172
+ O(|E|) once per build, no GNN, no query latency. It is a drop-in after
173
+ G-ETSI-2/3 give us real neighbors.
174
+
175
+ Implementation: after embed, one or two smoothing iterations over the
176
+ section graph, write smoothed vectors to Vectorize (or a parallel index
177
+ for A/B). α ≈ 0.7–0.85 (keep self-dominant). Do **not** smooth across
178
+ family boundaries or superseded editions.
179
+
180
+ #### G-ETSI-5 — Tables still flattened 【HIGH — they exempt them】
181
+
182
+ **ETSI:** "Tabular sections are exempted from being chunked." Atomic.
183
+
184
+ **Us:** G1 prototype extracts 10k typed tables (adoc-first) into
185
+ `artifacts/table-chunks.jsonl` — **not in the live index**. Prose pipeline
186
+ still linearizes tables into clause text.
187
+
188
+ Ship G1: upsert `chunk_type=table` rows as first-class InfoUnits with
189
+ parthood to their parent clause. Do not split table rows across chunks.
190
+ Re-enrichment cost ≈$50 is the gate, not the design.
191
+
192
+ #### G-ETSI-6 — Precision-first retrieval metrics under-weighted 【MED】
193
+
194
+ **ETSI primary charts:** AP@K, MRR@K, R@K — and their wins are on **AP and
195
+ MRR**, not recall.
196
+
197
+ **Us:** `retrieval.mjs` hit@5 (recall-ish), golden citation_any, RAGAS
198
+ faithfulness/relevancy/precision (generation-side). We under-measure the
199
+ axis their methods actually move.
200
+
201
+ Add AP@K / MRR@K on the retrieval suite with witness-style golden spans
202
+ (we can derive from golden cases' expected citations). Report them on
203
+ every retrieval change. Stop treating recall@5 as the only retrieval KPI.
204
+
205
+ #### G-ETSI-7 — Neighbor expansion scoring 【LOW — do not chase】
206
+
207
+ **ETSI:** expander + graph re-rank **failed**. Our terminology-only graph
208
+ lane is the correct restrained form. Do not build a general "expand to all
209
+ neighbors" path until a domain-adequate neighbor score is validated on
210
+ our golden set. Smoothing (G-ETSI-4) is the proven way to push relational
211
+ signal *into the vectors* instead.
212
+
213
+ ---
214
+
215
+ ## 4. Redesigned pipeline (target architecture)
216
+
217
+ ### 4.1 Offline (RDP) — once per index build
218
+
219
+ ```
220
+ OII (Metanorma model / adoc / HTML fallback)
221
+ │
222
+ ▼
223
+ ┌──────────────────────────────────────────────────────────┐
224
+ │ PARSE │
225
+ │ sections → InfoUnits {id, title, body, anchor, doc_id} │
226
+ │ tables → InfoUnits chunk_type=table (ATOMIC) │
227
+ │ formulas → InfoUnits chunk_type=equation (when typed) │
228
+ │ empty-body section nodes kept │
229
+ └──────────────────────────────────────────────────────────┘
230
+ │
231
+ ▼
232
+ ┌──────────────────────────────────────────────────────────┐
233
+ │ GRAPH │
234
+ │ P: anchor-tree part_of (clause↔clause, clause↔doc) │
235
+ │ C: internal + external cites (mention resolve) │
236
+ │ existing: successor, family part_of, defines │
237
+ │ documents registry (derived active) unchanged │
238
+ └──────────────────────────────────────────────────────────┘
239
+ │
240
+ ▼
241
+ ┌──────────────────────────────────────────────────────────┐
242
+ │ ENRICH (contextual preamble, quality-first lane) — keep │
243
+ └──────────────────────────────────────────────────────────┘
244
+ │
245
+ ▼
246
+ ┌──────────────────────────────────────────────────────────┐
247
+ │ EMBED → SMOOTH (α-blend over N(u) for 1–2 iterations) │
248
+ │ → UPSERT Vectorize (smoothed) │
249
+ │ + BUILD inverted index (D1 FTS5 / postings) for BM25 │
250
+ └──────────────────────────────────────────────────────────┘
251
+ ```
252
+
253
+ ### 4.2 Online (worker) — every question
254
+
255
+ ```
256
+ query
257
+ │
258
+ ├─ understanding (LLM) ────────── filters, terms, complexity, …
259
+ │
260
+ ├─ BM25 prefilter (FULL corpus inverted index) ── top N_bm25
261
+ │
262
+ ├─ dense Vectorize (smoothed vectors) ± metadata filter
263
+ │ + multi-query / HyDE fusion (keep)
264
+ │ + terminology graph lane (keep; restrained)
265
+ │
266
+ ├─ UNION candidate ids
267
+ │
268
+ ├─ RRF(dense-rank, bm25-rank) ← now true hybrid recall
269
+ │
270
+ ├─ cross-encoder rerank → listwise (member/complex)
271
+ │
272
+ ├─ family pin / term boost / edition steer (keep)
273
+ │
274
+ ├─ CRAG grade → optional corrective re-retrieve (keep)
275
+ │
276
+ └─ generate + quote-anchor verify + reflect (keep)
277
+ citations follow usedHits (keep)
278
+ ```
279
+
280
+ **Deliberately absent:** general neighbor-expansion re-ranker (ETSI
281
+ negative). Agentic multi-hop remains Phase-3 for the synthesis class they
282
+ flag as future work — not a substitute for the precision stack above.
283
+
284
+ ### 4.3 Mapping to #592 / Metanorma
285
+
286
+ ETSI §II: the InfoModel is dictated by PDF extraction limits; they
287
+ "envision that this simple Information Model can be extended/swapped…
288
+ when dealing with normative content that is already available in a
289
+ machine-readable format, such as is foreseen by the IEC Smart Standards
290
+ framework."
291
+
292
+ Our equivalent is the AI-serialization projection
293
+ (`docs/METANORMA-AI-SERIALIZATION.md`):
294
+
295
+ | ETSI InfoModel | #592 / ChunkRecordV2 |
296
+ |---|---|
297
+ | InfoUnit {title, body} | typed `nodes[]` (clause/table/formula/term/requirement/…) |
298
+ | P parthood | `edges[]` kind=`part_of` + breadcrumb |
299
+ | C citation | `edges[]` kind=`cites` + Relaton keys |
300
+ | section code geometry | model anchors (stable, not OCR-guessed) |
301
+ | tables atomic | `type=table` with columns/rows payload (conformance rule §8.3) |
302
+
303
+ **Hand-rolled G-ETSI-2/3/5 now is the reference implementation that #592
304
+ must emit.** We do not wait on upstream to close the retrieval gaps; we
305
+ close them with the sources we have, and the projection is the durable
306
+ contract.
307
+
308
+ ---
309
+
310
+ ## 5. Phased execution (eval-gated, ETSI-ordered)
311
+
312
+ Every phase ships only if AP@K and MRR@K on the retrieval suite move the
313
+ right direction on the golden + paraphrase probes. Recall@K is reported
314
+ but is not the gate (ETSI: structure/RRF don't move it; only smoothing
315
+ does, slightly).
316
+
317
+ ### Phase E0 — Measurement hygiene (1–2 days, no index change)
318
+ 1. Add AP@K, MRR@K, R@K to `tests/retrieval.mjs` with citation-span
319
+ matching (≥75% golden span containment — their protocol).
320
+ 2. Snapshot baselines on current production index.
321
+ 3. Stop treating hit@5 as the sole retrieval KPI in roadmap language.
322
+
323
+ ### Phase E1 — True hybrid lexical recall (G-ETSI-1) (3–5 days)
324
+ 1. Ingest: write `chunks_fts` (D1 FTS5) or posting lists from
325
+ `artifacts/chunks.jsonl` (enriched text).
326
+ 2. Query: BM25 top-N → union dense top-K → existing RRF → rerank.
327
+ 3. Gate: AP@K / MRR@K up on jargon-heavy cases (`n_LC`, part numbers,
328
+ "maximum permissible error", French/German term forms). Exact-term
329
+ paraphrase probes must not regress.
330
+
331
+ ### Phase E2 — Section graph + smoothing (G-ETSI-2/3/4) (1–2 weeks)
332
+ 1. Emit clause-level `part_of` + `cites` at graph build.
333
+ 2. Offline smooth embeddings (α sweep {0.7, 0.8, 0.9} × 1–2 iterations)
334
+ into a side index; A/B against current.
335
+ 3. Gate: recall@K up or flat with AP/MRR non-worse (smoothing is the
336
+ recall lever; do not accept AP regression).
337
+ 4. Do **not** enable neighbor-expansion re-rank in this phase.
338
+
339
+ ### Phase E3 — Atomic tables (G-ETSI-5) (re-ingest window, ≈$50)
340
+ 1. Upsert G1 table chunks; `chunk_type=table`; parent `part_of` to clause.
341
+ 2. Re-enrich + re-embed + smooth.
342
+ 3. Gate: table-value golden cases (R 60 n_LC, R 76 MPE, R 111 E2) AP/MRR
343
+ and answer correctness; no regression on prose cases.
344
+
345
+ ### Phase E4 — #592 producer path (upstream, parallel)
346
+ 1. Keep AI-serialization proposal aligned with the InfoModel above.
347
+ 2. Hand-rolled adapters remain the consumer of record until
348
+ metanorma-document emits the projection.
349
+ 3. When available: swap parse source, delete HTML/adoc recovery paths for
350
+ covered doctypes (OCP: new source = new adapter, not pipeline branches).
351
+
352
+ ### Phase E5 — Multi-hop synthesis (their future work = our G10)
353
+ Only after E1–E3 are green. Deep-research / agentic loop for questions
354
+ that need distant passages or cross-document assembly. Not a retrieval
355
+ substitute.
356
+
357
+ ### Explicitly deferred / rejected by ETSI evidence
358
+ - GNN graph embeddings (smoothing is the lightweight substitute they
359
+ validated).
360
+ - General seed-neighbor expansion re-ranker (failed on ETSI).
361
+ - Embedding-model upgrade as the primary lever (their stack used Granite;
362
+ wins came from structure + hybrid + smoothing).
363
+ - Overlap chunking (not in their design; independent 2026 evidence also
364
+ weak — not reopened here).
365
+
366
+ ---
367
+
368
+ ## 6. What changes in our public claims
369
+
370
+ - Retrieval quality story shifts from "dense + rerank + graph lane" to
371
+ **"structure-preserving index + full-corpus lexical prefilter + smoothed
372
+ dense + RRF + rerank"**, which is the ETSI-validated cascade for
373
+ standards.
374
+ - Graph story shifts from "expand at query time" to **"parthood and
375
+ citation live in the index; relational signal is baked into vectors via
376
+ smoothing; query-time expansion stays restrained (terminology)"**.
377
+ - Tables story is no longer optional polish — **atomic tables are a
378
+ normative-RAG requirement** (ETSI exempts them from chunking; STC
379
+ arXiv:2605.00318 independently shows MRR 0.36→0.59 / R@1 0.37→0.75 on
380
+ tabular structure, corroborating).
381
+ - #592 is not a nice-to-have serialization — it is the **IEC-Smart-Standards
382
+ equivalent** their methodology section already assumes as the end state.
383
+
384
+ ---
385
+
386
+ ## 7. Sources (primary only)
387
+
388
+ 1. Al Masoud, Arazzi, Germani, Nocera. *Exploring Structural Complexity in
389
+ Normative RAG with Graph-based approaches: A case study on the ETSI
390
+ Standards.* arXiv:2604.09868, 2026-01.
391
+ https://arxiv.org/abs/2604.09868
392
+ 2. Guttal et al. *Structure-Aware Chunking for Tabular Data in RAG* (STC).
393
+ arXiv:2605.00318, 2026-05. (tables atomic / row structure — corroborates
394
+ G-ETSI-5 magnitude.) https://arxiv.org/abs/2605.00318
395
+ 3. Rayo, de la Rosa, Garrido. *A hybrid approach to information retrieval
396
+ and answer generation for regulatory texts.* 2025. (dense+sparse for
397
+ regulatory IR — ETSI's cited prior for RRF.)
398
+ 4. Cormack, Clarke, Buettcher. *Reciprocal rank fusion outperforms
399
+ condorcet and individual rank learning methods.* SIGIR 2009. (RRF.)
400
+ 5. IEC. *Smart Standards – from a market and industry perspective.* 2024.
401
+ (machine-readable standards end-state ETSI points at; our #592 analogue.)
402
+
403
+ Corroborating structure-first work (not standards-specific, not used as
404
+ primary authority here): Xu et al. RDR² arXiv:2510.04293; Yu et al. SF-RAG
405
+ arXiv:2602.13647; SPIRE arXiv:2604.20849; Günther et al. late chunking
406
+ arXiv:2409.04701; Merola & Singh contextual vs late arXiv:2504.19754.
407
+
408
+ ---
409
+
410
+ ## 8. Immediate next action
411
+
412
+ Phase E0 + E1 start now. No re-ingest required for E0/E1 (FTS can be built
413
+ from existing `artifacts/chunks.jsonl` / live chunk texts). E2/E3 need an
414
+ index rebuild window and explicit go on the ≈$50 re-enrichment for E3.
415
+
416
+
417
+ ---
418
+
419
+ ## Postscript (2026-08-29): vision-unified answer contract
420
+
421
+ User decision: unify text and figure understanding in ONE vision-enabled
422
+ answer model instead of a forked vision lane.
423
+
424
+ **Model**: `@cf/zai-org/glm-5.3-flash` — natively multimodal (320B/18B
425
+ active), GLM family, flash tier, in the Workers AI catalog. Single answer
426
+ model: prose + tables/equations as text, figures as IMAGE PARTS in the
427
+ message content. Fallback ladder: qwen3.8-27b (text-only; figures degrade
428
+ to their ingest-time description). Price unconfirmed (flash-tier
429
+ expected) — eval-gate before defaulting the member lane.
430
+
431
+ **Pipeline changes**
432
+
433
+ 1. INGEST (MKO stage 2.5): figure assets → R2 public bucket at stable
434
+ unit-keyed URLs; FigurePayload.uri rewritten to the canonical URL.
435
+ One-time vision captioning of EVERY figure into `description`
436
+ (quality-first lane; moondream 3.1 or glm-5.3-flash; ≈cents for the
437
+ clean corpus) so text-only tiers and the anon lane still explain
438
+ figures.
439
+ 2. SERVE: buildMessages appends an image part per figure unit among
440
+ usedHits when the routed model is vision-capable; understanding's
441
+ figure-presence signal routes to the VL model for members.
442
+ 3. OUTPUT contract unchanged: discursive prose + `[[u:]]` references;
443
+ figure blocks render <img> (canonical URL) + description; references
444
+ validated against usedHits; payloads served from KV by unit id — the
445
+ LLM still never re-types table/equation/figure DATA (input yes,
446
+ output by reference; verbatim quotes remain anchor-checked).
447
+ 4. EVAL GATE: new golden cases ("what does Figure A.x show?") must pass
448
+ with the VL model before the member lane defaults to it; TTFT watched
449
+ (image tokens add prefill).
450
+
451
+ **Also from the same review (2026-08-29)**: answer contract v2 (SymGen-style
452
+ symbolic references, arXiv:2311.09188; validation per JSONSchemaBench
453
+ arXiv:2501.10868 — post-hoc, not constrained decoding, per
454
+ arXiv:2405.21047), monthly cost table (CF-only ~$10/mo today; Modal CPU
455
+ micro-service +$110-135/mo is the first justified step if TTFT
456
+ consistency is product-critical; GPUs $580-2,840/mo eval-gated), and the
457
+ MN 116 "consumer references & excerpts" clause to draft upstream.
458
+
459
+
460
+ ---
461
+
462
+ ## Status board (2026-08-29, end of day — the reconciled plan)
463
+
464
+ | Plan item | Status |
465
+ |---|---|
466
+ | E0 ETSI metrics (R/AP/MRR + `--repeat`) | ✅ live |
467
+ | E1 full-corpus FTS prefilter | ✅ live (R@5 +9pp) |
468
+ | E2 section graph (parthood/cites/defines in D1) | ✅ live via MKO graph (3,561 section nodes) |
469
+ | E2 embedding smoothing | ⏸ tested, inconclusive at current eval power, rolled back — revisit with `--repeat 3` baselines |
470
+ | E3 atomic typed tables — clean corpus | ✅ live (MKO: 371 table chunks) |
471
+ | E3 atomic typed tables — dirty corpus | ☐ task #20 (~$16 enrichment) |
472
+ | E4 producer-native path (#592/MN 116/MKO) | ✅ MKO live for all 36 clean docs; upstream: preface-walk PR #49, MN 116 spec PR #9, incremental re-ingest PR #48; remaining: OIML pubid flavor, relations embedding, collections, multilingual alignment |
473
+ | E5 deep-research (G10) | ◐ server v1 live (member-gated); UI pending — task #21 |
474
+ | Vision-unified answers (glm-5.3-flash default) | ◐ model live all tiers; image-parts + contract v2 pending — task #22 |
475
+ | Figure assets → R2 + vision captions | ☐ task #23 |
476
+ | Answer contract v2 (SymGen refs + blocks + validation) | ☐ task #22 — the next big quality/rendering step |
477
+ | TTFT pipeline surgery (parallelize/trim pre-generation) | ☐ **URGENT** — measured 25–32s (47s under rate-limit haze); the serial understand→grade chain is the bottleneck, not the model |
478
+ | Modal CPU micro-service | deferred (conditional on TTFT consistency after surgery) |
479
+ | glm-5.3-flash price confirmation | ☐ check spend ledger next day |
480
+ | Turnstile | blocked on user sitekey |
481
+ | 36/224 relaton families missing successor edges | upstream PRs, needs user authorization |
482
+
483
+ Priorities: 1) TTFT surgery, 2) answer contract v2, 3) figures + captions,
484
+ 4) dirty tables, 5) research UI, 6) calm-window `--repeat 3` baseline +
485
+ price check.