noteconnection 1.7.0 → 1.9.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 (328) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +260 -1626
  3. package/dist/src/agent_workspace.contract.parity.test.js +159 -0
  4. package/dist/src/agent_workspace.frontend.test.js +10388 -0
  5. package/dist/src/agent_workspace.locale.contract.test.js +95 -0
  6. package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
  7. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  8. package/dist/src/appimage.patchelf.test.js +113 -0
  9. package/dist/src/appimage.portability.test.js +156 -0
  10. package/dist/src/backend/FileLoader.js +18 -4
  11. package/dist/src/backend/FileLoader.test.js +125 -0
  12. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  13. package/dist/src/backend/GraphBuilder.js +66 -18
  14. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  15. package/dist/src/backend/GraphMetrics.js +0 -3
  16. package/dist/src/backend/ResourceIdentity.js +155 -0
  17. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  18. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  19. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  20. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  21. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  22. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  23. package/dist/src/backend/build_dag.js +0 -1
  24. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  25. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  26. package/dist/src/copy.assets.contract.test.js +130 -0
  27. package/dist/src/core/Graph.js +138 -42
  28. package/dist/src/core/Graph.test.js +74 -0
  29. package/dist/src/core/NoteConnection.js +2 -2
  30. package/dist/src/core/PathBridge.js +293 -5
  31. package/dist/src/core/ResourceReference.js +17 -0
  32. package/dist/src/desktop.godot.pack.test.js +142 -0
  33. package/dist/src/desktop.runtime.graph.test.js +66 -0
  34. package/dist/src/export/WorkspaceExportBundle.js +1174 -0
  35. package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
  36. package/dist/src/export/index.js +18 -0
  37. package/dist/src/export/types.js +2 -0
  38. package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
  39. package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
  40. package/dist/src/foundation.release.evidence.contract.test.js +524 -0
  41. package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
  42. package/dist/src/frontend/README.md +260 -1626
  43. package/dist/src/frontend/agent_workspace.js +6011 -0
  44. package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
  45. package/dist/src/frontend/analysis.js +31 -4
  46. package/dist/src/frontend/app.js +2178 -62
  47. package/dist/src/frontend/focus_mode_interactions.js +33 -0
  48. package/dist/src/frontend/godot_future_path_renderer.js +540 -0
  49. package/dist/src/frontend/godot_tree_interactions.js +178 -0
  50. package/dist/src/frontend/graph_state.mjs +105 -0
  51. package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
  52. package/dist/src/frontend/i18n.mjs +186 -0
  53. package/dist/src/frontend/index.html +672 -268
  54. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  55. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  56. package/dist/src/frontend/layout_gpu.js +12 -4
  57. package/dist/src/frontend/libs/path_core.js +158 -42
  58. package/dist/src/frontend/locales/en.json +753 -5
  59. package/dist/src/frontend/locales/zh.json +753 -5
  60. package/dist/src/frontend/main.mjs +60 -0
  61. package/dist/src/frontend/markdown_runtime.js +827 -0
  62. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  63. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  64. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  65. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  66. package/dist/src/frontend/notemd.css +49 -0
  67. package/dist/src/frontend/notemd.html +7 -1
  68. package/dist/src/frontend/notemd.js +64 -0
  69. package/dist/src/frontend/path.html +113 -2
  70. package/dist/src/frontend/path_app.js +2108 -130
  71. package/dist/src/frontend/path_layout.mjs +143 -0
  72. package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
  73. package/dist/src/frontend/path_modules_bridge.js +486 -0
  74. package/dist/src/frontend/path_state.mjs +118 -0
  75. package/dist/src/frontend/path_styles.css +146 -0
  76. package/dist/src/frontend/path_worker_bridge.mjs +85 -0
  77. package/dist/src/frontend/reader.js +393 -33
  78. package/dist/src/frontend/runtime_bridge.js +67 -54
  79. package/dist/src/frontend/runtime_bridge.mjs +279 -0
  80. package/dist/src/frontend/settings.js +130 -12
  81. package/dist/src/frontend/simulationWorker.js +1 -1
  82. package/dist/src/frontend/source_manager.js +297 -22
  83. package/dist/src/frontend/storage_provider.js +661 -71
  84. package/dist/src/frontend/styles.css +2814 -72
  85. package/dist/src/frontend/workbench_state.mjs +101 -0
  86. package/dist/src/frontend/workspace_panes.js +10272 -0
  87. package/dist/src/frontend.locale.contract.test.js +62 -0
  88. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  89. package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
  90. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  91. package/dist/src/index.js +6 -2
  92. package/dist/src/index.knowledge-root.test.js +118 -0
  93. package/dist/src/indexing/IndexLifecycle.js +217 -0
  94. package/dist/src/indexing/IndexLifecycle.test.js +73 -0
  95. package/dist/src/indexing/SegmentBuilder.js +64 -0
  96. package/dist/src/indexing/UnitBuilder.js +48 -0
  97. package/dist/src/indexing/types.js +2 -0
  98. package/dist/src/knowledge.api.contract.test.js +172 -0
  99. package/dist/src/knowledge_projection.contract.test.js +134 -0
  100. package/dist/src/knowledge_projection_store.test.js +200 -0
  101. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  102. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  103. package/dist/src/learning/KnowledgeLearningPlatform.js +11181 -0
  104. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
  105. package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
  106. package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
  107. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
  108. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
  109. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  110. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  111. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  112. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  113. package/dist/src/learning/agentConversationExecution.js +211 -0
  114. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  115. package/dist/src/learning/agentConversationSerialization.js +266 -0
  116. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  117. package/dist/src/learning/agentResponseBudget.js +179 -0
  118. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  119. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  120. package/dist/src/learning/answerReleaseReview.js +5260 -0
  121. package/dist/src/learning/answerReleaseReview.test.js +4174 -0
  122. package/dist/src/learning/answerTaskPlan.js +473 -0
  123. package/dist/src/learning/api.js +2 -0
  124. package/dist/src/learning/conversationComposer.js +1721 -0
  125. package/dist/src/learning/conversationComposer.test.js +3220 -0
  126. package/dist/src/learning/domains/ConversationManager.js +53 -0
  127. package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
  128. package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
  129. package/dist/src/learning/domains/MasteryEngine.js +387 -0
  130. package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
  131. package/dist/src/learning/domains/QualityEvaluator.js +307 -0
  132. package/dist/src/learning/domains/TutorRouter.js +313 -0
  133. package/dist/src/learning/domains/index.js +33 -0
  134. package/dist/src/learning/domains/types.js +7 -0
  135. package/dist/src/learning/errors.js +29 -0
  136. package/dist/src/learning/evidenceContextAssembler.js +1368 -0
  137. package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
  138. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  139. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  140. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  141. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  142. package/dist/src/learning/graphAnswerFacts.js +94 -0
  143. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  144. package/dist/src/learning/graphAnswerPlan.js +908 -0
  145. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  146. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  147. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  148. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  149. package/dist/src/learning/graphClaimMatcher.js +104 -0
  150. package/dist/src/learning/graphConditionedContext.js +109 -0
  151. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  152. package/dist/src/learning/graphContextAssembler.js +860 -0
  153. package/dist/src/learning/graphContextAssembler.test.js +1033 -0
  154. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  155. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  156. package/dist/src/learning/identityMetadata.test.js +26 -0
  157. package/dist/src/learning/index.js +29 -0
  158. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  159. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  160. package/dist/src/learning/queryBackend.js +1922 -0
  161. package/dist/src/learning/queryBackend.test.js +976 -0
  162. package/dist/src/learning/ragContextPack.js +356 -0
  163. package/dist/src/learning/ragContextPack.test.js +311 -0
  164. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  165. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  166. package/dist/src/learning/ragPublicText.js +101 -0
  167. package/dist/src/learning/ragPublicText.test.js +57 -0
  168. package/dist/src/learning/ragSufficiencyJudge.js +171 -0
  169. package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
  170. package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
  171. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
  172. package/dist/src/learning/requestNormalization.js +304 -0
  173. package/dist/src/learning/requestNormalization.test.js +101 -0
  174. package/dist/src/learning/runtimeCapability.js +4677 -0
  175. package/dist/src/learning/runtimeCapability.test.js +3635 -0
  176. package/dist/src/learning/store.js +1344 -0
  177. package/dist/src/learning/store.test.js +1425 -0
  178. package/dist/src/learning/tutorAdapter.js +2 -0
  179. package/dist/src/learning/types.js +2 -0
  180. package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
  181. package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
  182. package/dist/src/learning/workspaceHydration.js +168 -0
  183. package/dist/src/learning/workspaceHydration.test.js +30 -0
  184. package/dist/src/lfs.asset.policy.contract.test.js +153 -0
  185. package/dist/src/license.policy.contract.test.js +71 -0
  186. package/dist/src/markdown/MarkdownGateway.js +4 -0
  187. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  188. package/dist/src/memory/MemoryGovernance.js +74 -0
  189. package/dist/src/memory/MemoryGovernance.test.js +46 -0
  190. package/dist/src/memory/types.js +2 -0
  191. package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
  192. package/dist/src/middleware/SseResponseWriter.js +122 -0
  193. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  194. package/dist/src/middleware/auth.js +38 -0
  195. package/dist/src/middleware/auth.test.js +33 -0
  196. package/dist/src/middleware/body-parser.js +45 -0
  197. package/dist/src/middleware/cors.js +44 -0
  198. package/dist/src/middleware/index.js +22 -0
  199. package/dist/src/middleware/request-trace.js +96 -0
  200. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  201. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  202. package/dist/src/mobile.artifact.contract.test.js +144 -0
  203. package/dist/src/mobile.budget.contract.test.js +90 -0
  204. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  205. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  206. package/dist/src/mobile.identity.contract.test.js +66 -0
  207. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  208. package/dist/src/mobile.identity.corpus.test.js +40 -0
  209. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  210. package/dist/src/mobile.pipeline.test.js +11 -1
  211. package/dist/src/mobile.profile.contract.test.js +225 -0
  212. package/dist/src/mobile.semantic.parity.test.js +92 -0
  213. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  214. package/dist/src/notemd/AppConfigToml.js +6 -4
  215. package/dist/src/notemd/ContentGenerator.js +4 -9
  216. package/dist/src/notemd/FileProcessor.js +4 -9
  217. package/dist/src/notemd/MermaidProcessor.js +400 -50
  218. package/dist/src/notemd/NotemdService.js +506 -26
  219. package/dist/src/notemd/PromptManager.js +15 -0
  220. package/dist/src/notemd/Translator.js +4 -9
  221. package/dist/src/notemd/cli/commands.js +357 -0
  222. package/dist/src/notemd/cli/dispatcher.js +225 -0
  223. package/dist/src/notemd/cli/index.js +169 -0
  224. package/dist/src/notemd/cli/parser.js +68 -0
  225. package/dist/src/notemd/cli/types.js +2 -0
  226. package/dist/src/notemd/constants.js +43 -0
  227. package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
  228. package/dist/src/notemd/diagram/diagramSpec.js +79 -0
  229. package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
  230. package/dist/src/notemd/diagram/intent.js +95 -0
  231. package/dist/src/notemd/diagram/planner.js +71 -0
  232. package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
  233. package/dist/src/notemd/diagram/types.js +18 -0
  234. package/dist/src/notemd/index.js +26 -0
  235. package/dist/src/notemd/operations/capabilityManifest.js +23 -0
  236. package/dist/src/notemd/operations/cliContracts.js +17 -0
  237. package/dist/src/notemd/operations/configProfileCommands.js +85 -0
  238. package/dist/src/notemd/operations/registry.contract.test.js +95 -0
  239. package/dist/src/notemd/operations/registry.js +991 -0
  240. package/dist/src/notemd/operations/types.js +2 -0
  241. package/dist/src/notemd/progressReporter.js +9 -0
  242. package/dist/src/notemd/providerDiagnostics.js +220 -0
  243. package/dist/src/notemd/providerProfiles.js +42 -0
  244. package/dist/src/notemd/providerTemplates.js +231 -0
  245. package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
  246. package/dist/src/notemd/search/SearchManager.js +13 -0
  247. package/dist/src/notemd/search/SearchProvider.js +2 -0
  248. package/dist/src/notemd/search/TavilyProvider.js +44 -0
  249. package/dist/src/notemd.agent.manifest.test.js +85 -0
  250. package/dist/src/notemd.api.contract.test.js +14 -1
  251. package/dist/src/notemd.app_config_toml.test.js +2 -1
  252. package/dist/src/notemd.batch.workflow.test.js +117 -0
  253. package/dist/src/notemd.cli.e2e.test.js +136 -0
  254. package/dist/src/notemd.core.test.js +51 -0
  255. package/dist/src/notemd.diagram.pipeline.test.js +233 -0
  256. package/dist/src/notemd.providerTemplates.test.js +34 -0
  257. package/dist/src/notemd.server.integration.test.js +262 -39
  258. package/dist/src/notemd.workflow.pipeline.test.js +162 -0
  259. package/dist/src/pathbridge.handshake.contract.test.js +45 -2
  260. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  261. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  262. package/dist/src/pathmode.background.contract.test.js +69 -0
  263. package/dist/src/pathmode.settings.api.contract.test.js +9 -0
  264. package/dist/src/pkg.sidecar.contract.test.js +9 -3
  265. package/dist/src/platform/ExportProfile.js +86 -0
  266. package/dist/src/platform/MobileBudget.js +11 -0
  267. package/dist/src/platform/PlatformCapabilities.js +59 -0
  268. package/dist/src/platform/PlatformCapabilities.test.js +36 -0
  269. package/dist/src/platform/RenderMaterializer.js +33 -0
  270. package/dist/src/platform/RenderMaterializer.test.js +32 -0
  271. package/dist/src/query_backend.external_http.integration.test.js +410 -0
  272. package/dist/src/reader_renderer.js +404 -3
  273. package/dist/src/reader_renderer.test.js +87 -0
  274. package/dist/src/release.godot.mirror.contract.test.js +97 -0
  275. package/dist/src/resources/ResourceRegistry.js +263 -0
  276. package/dist/src/resources/ResourceRegistry.test.js +97 -0
  277. package/dist/src/resources/types.js +2 -0
  278. package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
  279. package/dist/src/routes/index.js +19 -0
  280. package/dist/src/routes/knowledge.js +981 -0
  281. package/dist/src/routes/knowledgePayload.js +185 -0
  282. package/dist/src/routes/knowledgePayload.test.js +53 -0
  283. package/dist/src/routes/markdown.js +295 -0
  284. package/dist/src/routes/notemd.js +1321 -0
  285. package/dist/src/routes/registry.contract.test.js +133 -0
  286. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  287. package/dist/src/routes/render.js +248 -0
  288. package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
  289. package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
  290. package/dist/src/routes/settings.js +6 -0
  291. package/dist/src/routes/staticFiles.js +94 -0
  292. package/dist/src/routes/types.js +2 -0
  293. package/dist/src/runtime.capabilities.test.js +18 -2
  294. package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
  295. package/dist/src/server.js +10342 -1325
  296. package/dist/src/server.migration.test.js +584 -10
  297. package/dist/src/server.port.fallback.contract.test.js +63 -0
  298. package/dist/src/session/SessionStateStore.js +81 -0
  299. package/dist/src/session/SessionStateStore.test.js +58 -0
  300. package/dist/src/session/types.js +2 -0
  301. package/dist/src/settings.runtime.contract.test.js +50 -0
  302. package/dist/src/shared/types.contract.test.js +107 -0
  303. package/dist/src/shared/types.js +22 -0
  304. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  305. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  306. package/dist/src/sidecar.replacement.boundary.contract.test.js +131 -0
  307. package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
  308. package/dist/src/simulation.worker.offline.test.js +104 -0
  309. package/dist/src/source_manager.loadflow.test.js +46 -0
  310. package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
  311. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  312. package/dist/src/storage.provider.contract.test.js +152 -1
  313. package/dist/src/tauri.frontend.build.contract.test.js +68 -0
  314. package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
  315. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  316. package/dist/src/utils/RuntimePaths.js +10 -13
  317. package/dist/src/utils/RuntimePaths.test.js +27 -0
  318. package/dist/src/utils/platform.js +153 -0
  319. package/dist/src/windows.installer.build.test.js +109 -0
  320. package/dist/src/windows.installer.payload.test.js +76 -0
  321. package/dist/src/windows.installer.runtime.test.js +69 -0
  322. package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
  323. package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
  324. package/dist/src/workflows/types.js +2 -0
  325. package/dist/src/workspace/WorkspaceRegistry.js +135 -0
  326. package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
  327. package/dist/src/workspace/types.js +2 -0
  328. package/package.json +80 -15
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.iterateRagEvidenceClauses = iterateRagEvidenceClauses;
4
+ exports.segmentRagEvidenceClauses = segmentRagEvidenceClauses;
5
+ exports.scoreRagEvidenceClause = scoreRagEvidenceClause;
6
+ function normalizeWhitespace(value) {
7
+ return String(value || '').replace(/\s+/gu, ' ').trim();
8
+ }
9
+ function isClauseBoundary(source, index) {
10
+ const character = source[index];
11
+ if (/\r|\n|;/u.test(character)) {
12
+ return true;
13
+ }
14
+ if (character === '.' && /[\d\s=+\-(]/u.test(source[index - 1] || ' ') && /\d/u.test(source[index + 1] || '')) {
15
+ return false;
16
+ }
17
+ return /[.!?。!?;]/u.test(character);
18
+ }
19
+ /**
20
+ * Splits source evidence at discourse boundaries while retaining decimal numbers and
21
+ * mathematical notation. The caller still owns filtering and public-text naturalization.
22
+ */
23
+ function* iterateRagEvidenceClauses(value) {
24
+ const source = String(value || '');
25
+ if (!source) {
26
+ return;
27
+ }
28
+ let start = 0;
29
+ for (let index = 0; index < source.length; index += 1) {
30
+ if (!isClauseBoundary(source, index)) {
31
+ continue;
32
+ }
33
+ const includeBoundary = /[.!?。!?]/u.test(source[index]);
34
+ const clause = normalizeWhitespace(source.slice(start, includeBoundary ? index + 1 : index));
35
+ if (clause) {
36
+ yield clause;
37
+ }
38
+ start = index + 1;
39
+ }
40
+ const remainder = normalizeWhitespace(source.slice(start));
41
+ if (remainder) {
42
+ yield remainder;
43
+ }
44
+ }
45
+ function segmentRagEvidenceClauses(value) {
46
+ return Array.from(iterateRagEvidenceClauses(value));
47
+ }
48
+ function delimiterBalance(value) {
49
+ const pairs = { '(': ')', '[': ']', '{': '}', '(': ')', '[': ']', '{': '}' };
50
+ const closing = new Set(Object.values(pairs));
51
+ const stack = [];
52
+ for (const character of value) {
53
+ if (pairs[character]) {
54
+ stack.push(pairs[character]);
55
+ }
56
+ else if (closing.has(character) && stack.pop() !== character) {
57
+ return false;
58
+ }
59
+ }
60
+ return stack.length === 0;
61
+ }
62
+ function mathDensity(value) {
63
+ const mathTokens = value.match(/(?:\b\d+(?:\.\d+)?\b|[=<>±×÷∑∫√]|\b(?:sin|cos|log|exp)\b)/giu) || [];
64
+ return Math.min(1, mathTokens.length / Math.max(6, value.length / 24));
65
+ }
66
+ function documentaryPenalty(value) {
67
+ return /\b(?:this (?:document|section|table)|the following|as requested|we will|must follow|ignore this)\b/iu.test(value)
68
+ || /(?:本文档|下表|如下|按照您的要求|忽略本节)/u.test(value)
69
+ ? 0.35
70
+ : 0;
71
+ }
72
+ function scoreRagEvidenceClause(value) {
73
+ const clause = normalizeWhitespace(value);
74
+ const hasTerminalPunctuation = /[.!?。!?]$/u.test(clause);
75
+ const hasBalancedDelimiters = delimiterBalance(clause);
76
+ const density = mathDensity(clause);
77
+ const penalty = documentaryPenalty(clause);
78
+ const lengthScore = clause.length < 8
79
+ ? -0.3
80
+ : clause.length <= 420
81
+ ? 0.25
82
+ : -Math.min(0.25, (clause.length - 420) / 2400);
83
+ const score = Math.max(0, Math.min(1, 0.35
84
+ + (hasTerminalPunctuation ? 0.15 : -0.08)
85
+ + (hasBalancedDelimiters ? 0.15 : -0.3)
86
+ + Math.min(0.2, density * 0.2)
87
+ + lengthScore
88
+ - penalty));
89
+ return {
90
+ score: Number(score.toFixed(4)),
91
+ hasTerminalPunctuation,
92
+ hasBalancedDelimiters,
93
+ mathDensity: Number(density.toFixed(4)),
94
+ documentaryPenalty: penalty,
95
+ };
96
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ragEvidenceQuality_1 = require("./ragEvidenceQuality");
4
+ describe('ragEvidenceQuality', () => {
5
+ test('segments prose without splitting decimal mathematical values', () => {
6
+ expect((0, ragEvidenceQuality_1.segmentRagEvidenceClauses)('The coefficient is 0.75; heat transfer follows the wall.')).toEqual([
7
+ 'The coefficient is 0.75',
8
+ 'heat transfer follows the wall.',
9
+ ]);
10
+ });
11
+ test('scores complete balanced mathematical evidence above documentary prose', () => {
12
+ const evidence = (0, ragEvidenceQuality_1.scoreRagEvidenceClause)('The thermal flux is q = kA(T1 - T2) / L, so thickness changes the exchange rate.');
13
+ const documentary = (0, ragEvidenceQuality_1.scoreRagEvidenceClause)('This document will explain the following table as requested.');
14
+ expect(evidence.hasBalancedDelimiters).toBe(true);
15
+ expect(evidence.mathDensity).toBeGreaterThan(0);
16
+ expect(evidence.score).toBeGreaterThan(documentary.score);
17
+ expect(documentary.documentaryPenalty).toBeGreaterThan(0);
18
+ });
19
+ test('preserves leading decimal measurements without joining numbered sentences', () => {
20
+ expect((0, ragEvidenceQuality_1.segmentRagEvidenceClauses)('The offset is -.25 ms. The duration is .5 s; 1. Next observation.')).toEqual([
21
+ 'The offset is -.25 ms.', 'The duration is .5 s', '1.', 'Next observation.',
22
+ ]);
23
+ });
24
+ test('penalizes unbalanced mathematical fragments', () => {
25
+ const quality = (0, ragEvidenceQuality_1.scoreRagEvidenceClause)('The flux is q = kA(T1 - T2 / L.');
26
+ expect(quality.hasBalancedDelimiters).toBe(false);
27
+ expect(quality.score).toBeLessThan(0.5);
28
+ });
29
+ });
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.omitFencedMarkdownPayload = omitFencedMarkdownPayload;
4
+ exports.extractPublicMermaidEvidenceLabels = extractPublicMermaidEvidenceLabels;
5
+ exports.naturalizeRagPublicEvidenceClause = naturalizeRagPublicEvidenceClause;
6
+ exports.shouldRejectPublicEvidenceClause = shouldRejectPublicEvidenceClause;
7
+ exports.shouldRejectCompareProcedureEvidenceClause = shouldRejectCompareProcedureEvidenceClause;
8
+ const answerTaskPlan_1 = require("./answerTaskPlan");
9
+ function normalizeWhitespace(value) {
10
+ return String(value || '').replace(/\s+/g, ' ').trim();
11
+ }
12
+ function omitFencedMarkdownPayload(value) {
13
+ return String(value || '')
14
+ .replace(/```[\s\S]*?```/gu, ' ')
15
+ .replace(/```[\s\S]*$/u, ' ');
16
+ }
17
+ function normalizeMermaidLabel(value) {
18
+ return normalizeWhitespace(String(value || '')
19
+ .replace(/<br\s*\/?>/giu, ' ')
20
+ .replace(/\\n/gu, ' ')
21
+ .replace(/["`*_~#|{}]/gu, ' '));
22
+ }
23
+ /**
24
+ * Converts diagram node labels into evidence text while keeping Mermaid syntax out of public answers.
25
+ */
26
+ function extractPublicMermaidEvidenceLabels(value) {
27
+ const labels = [];
28
+ const append = (candidate) => {
29
+ const label = normalizeMermaidLabel(candidate);
30
+ if (label && !labels.includes(label)) {
31
+ labels.push(label);
32
+ }
33
+ };
34
+ const source = String(value || '');
35
+ const fences = source.matchAll(/```mermaid\s*([\s\S]*?)(?:```|$)/giu);
36
+ for (const fence of fences) {
37
+ const body = String(fence[1] || '');
38
+ body.replace(/\[([^\]]+)\]/gu, (_match, label) => {
39
+ append(label);
40
+ return '';
41
+ });
42
+ body.replace(/"([^"]+)"/gu, (_match, label) => {
43
+ append(label);
44
+ return '';
45
+ });
46
+ }
47
+ return labels;
48
+ }
49
+ const LEADING_SOURCE_LABEL_PATTERN = /^(?:(?:prerequisites?|preconditions?|requirements?|background|context|mechanism|reasoning boundary|downstream checks?|downstream consequences?|failure modes?|mitigation(?: neighbor)?|graph caveat|caveat|evidence|summary|note|material science)\s*[:\uFF1A-]\s*|(?:核心概念(?:及其数学基础)?|材料科学|技术参数)(?:\s*[:\uFF1A-]\s*|\s+))/iu;
50
+ const PRESERVED_LEADING_LABEL_PATTERN = /^(?:step|phase|stage|section)\s*\d+\s*[:\uFF1A-]/iu;
51
+ function naturalizeRagPublicEvidenceClause(value) {
52
+ let normalized = normalizeWhitespace(omitFencedMarkdownPayload(value)
53
+ .replace(/^\s*[-+*]\s+/gmu, '')
54
+ .replace(/\s+\*\s+(?=\$|\*\*|[\u3400-\u9fff])/gu, ' ')
55
+ .replace(/\*\*([^*]+)\*\*/gu, '$1')
56
+ .replace(/([+\-]\/)\s+(?=\d)/gu, '$1')
57
+ .replace(/(\d)\.\s+(?=\d)/gu, '$1.')
58
+ .replace(/^(?:#{1,6})\s+/u, ''));
59
+ const tableStart = normalized.search(/\s\|\s*[^|]+\s*\|/u);
60
+ if (tableStart >= 0) {
61
+ normalized = normalizeWhitespace(normalized.slice(0, tableStart));
62
+ }
63
+ if (!normalized || PRESERVED_LEADING_LABEL_PATTERN.test(normalized)) {
64
+ return normalized;
65
+ }
66
+ for (let pass = 0; pass < 3; pass += 1) {
67
+ const next = normalizeWhitespace(normalized.replace(LEADING_SOURCE_LABEL_PATTERN, ''));
68
+ if (!next || next === normalized) {
69
+ break;
70
+ }
71
+ normalized = next;
72
+ if (PRESERVED_LEADING_LABEL_PATTERN.test(normalized)) {
73
+ break;
74
+ }
75
+ }
76
+ return normalized;
77
+ }
78
+ function shouldRejectPublicEvidenceClause(value) {
79
+ const normalized = normalizeWhitespace(value);
80
+ // A bare wiki link identifies a note, but supplies no factual statement for answer coverage.
81
+ return /^(?:(?:\d+[.)]|[-*+])?\s*\[\[[^\]]+\]\][\s,;、,;.!。]*)+$/u.test(normalized)
82
+ || /\b(?:distractor|must not guide|do not use|ignore this (?:section|evidence)|must (?:compare|resolve)|before publishing)\b/iu.test(normalized)
83
+ || /\b(?:this|the)\s+(?:clause|sentence|paragraph)\b[^.!?]{0,120}\bpublic\s+(?:definition|answer)\s+budget\b/iu.test(normalized)
84
+ || /\b(?:the following table|the table below)\b/iu.test(normalized)
85
+ || /(?:下表|以下表格|表中)(?:列出|展示|给出|包含)/u.test(normalized)
86
+ || /(?:参数\s*\(Parameter\)|Parameter).{0,160}(?:单位\s*\(Unit\)|Unit).{0,160}:---/iu.test(normalized)
87
+ || /(?:遵从您的指示|所有推理过程|最终输出|仅基于标题|根据您的要求生成|本技术文档旨在)/u.test(normalized);
88
+ }
89
+ function shouldRejectCompareProcedureEvidenceClause(value, query) {
90
+ const normalizedClause = normalizeWhitespace(value).toLowerCase();
91
+ const normalizedQuery = normalizeWhitespace(query).toLowerCase();
92
+ if (!normalizedClause) {
93
+ return false;
94
+ }
95
+ if ((0, answerTaskPlan_1.isProcedureRequest)(normalizedQuery)) {
96
+ return false;
97
+ }
98
+ return /^(?:(?:procedure|workflow|runbook)\s*[:\uFF1A-]|(?:step\s*\d+|steps?|步骤\s*\d+)\b)/u.test(normalizedClause)
99
+ || /\b(?:follow|execute|perform)\s+(?:this|the following)\s+(?:procedure|workflow|steps?)\b/u.test(normalizedClause)
100
+ || /\bprocedural\b.{0,80}\bsequence\b/u.test(normalizedClause);
101
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ragPublicText_1 = require("./ragPublicText");
4
+ const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
5
+ describe('ragPublicText', () => {
6
+ test('retains numbered procedure evidence for a how-should request', () => {
7
+ expect((0, ragPublicText_1.shouldRejectCompareProcedureEvidenceClause)('Step 1: Validate the candidate.', 'How should the index be replaced?')).toBe(false);
8
+ expect((0, ragPublicText_1.shouldRejectCompareProcedureEvidenceClause)('Step 1: Validate the candidate.', 'Compare the two indexes.')).toBe(true);
9
+ });
10
+ test.each(['[[Checkpoint]]', '[[Checkpoint]] [[Mutation log]]', '1. [[Checkpoint]] 2. [[Mutation log]]'])('rejects link-only navigation as factual evidence: %s', text => {
11
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)(text)).toBe(true);
12
+ });
13
+ test('preserves factual prose that contains a wiki link', () => {
14
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('A [[Mutation log]] records an ordered sequence of changes.')).toBe(false);
15
+ });
16
+ test('comparison composition selects source facts instead of bare wiki links', async () => {
17
+ const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
18
+ await platform.ingestKnowledge({ documents: [
19
+ { documentId: 'checkpoint', sourcePath: 'test/checkpoint.md', content: '# Checkpoint\nA checkpoint stores the complete state at a checkpoint. [[Mutation log]]' },
20
+ { documentId: 'mutation-log', sourcePath: 'test/mutation-log.md', content: '# Mutation Log\nA mutation log records an ordered sequence of state changes. [[Checkpoint]]' },
21
+ ] });
22
+ const response = await platform.agentConversation({ message: 'Compare Checkpoint and Mutation Log', persistMemory: false });
23
+ expect(response.answer).toMatch(/complete state|ordered sequence/i);
24
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)(response.answer)).toBe(false);
25
+ });
26
+ test('removes Markdown list and bold-label scaffolding before public composition', () => {
27
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('* **Quantitative analysis**: pressure follows P = rho g h.'))
28
+ .toBe('Quantitative analysis: pressure follows P = rho g h.');
29
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('* $T$ is the temperature field.'))
30
+ .toBe('$T$ is the temperature field.');
31
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('A value * B value remains mathematical.'))
32
+ .toBe('A value * B value remains mathematical.');
33
+ });
34
+ test('removes markdown headings and table scaffolding while preserving the factual lead', () => {
35
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('### Technical specifications The glass density is about 2500 kg/m³. | Parameter | Value | | :--- | :--- | | density | 2500 |')).toBe('Technical specifications The glass density is about 2500 kg/m³.');
36
+ });
37
+ test('rejects authoring instructions and evidence-control prose in Chinese and English', () => {
38
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('所有推理过程以英文进行,最终输出为简体中文。')).toBe(true);
39
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('Operators must resolve the active owner before publishing.')).toBe(true);
40
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('The glass wall conducts heat into the environment.')).toBe(false);
41
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('This clause is intentionally beyond the public definition budget and should remain internal.')).toBe(true);
42
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('The response budget limits serialized bytes.')).toBe(false);
43
+ });
44
+ test('removes fenced diagram payloads instead of exposing renderer source', () => {
45
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('Heat moves by conduction and convection. ```mermaid graph TD A --> B ```')).toBe('Heat moves by conduction and convection.');
46
+ });
47
+ test('rejects flattened table introductions after Markdown extraction', () => {
48
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('下表列出了标准温度和压力下的典型技术参数。参数 Parameter 密度 2500 999.8 kg/m³ 单位 Unit。')).toBe(true);
49
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('The following table lists typical parameters. Parameter Density Value Unit.')).toBe(true);
50
+ expect((0, ragPublicText_1.shouldRejectPublicEvidenceClause)('参数 (Parameter) 钠钙玻璃 水 单位 (Unit) :--- :--- 密度 2500 999.8 kg/m³。')).toBe(true);
51
+ });
52
+ test('removes flattened section labels while retaining their factual sentence', () => {
53
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('核心概念及其数学基础:水杯系统通过传导、对流和辐射与环境交换热量。')).toBe('水杯系统通过传导、对流和辐射与环境交换热量。');
54
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('Material science: Glass is an amorphous solid without long-range order.')).toBe('Glass is an amorphous solid without long-range order.');
55
+ expect((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)('核心概念及其数学基础 水杯系统通过传导、对流和辐射与环境交换热量。')).toBe('水杯系统通过传导、对流和辐射与环境交换热量。');
56
+ });
57
+ });
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reviewRagContextSufficiency = reviewRagContextSufficiency;
4
+ function clampUnit(value) {
5
+ if (!Number.isFinite(value)) {
6
+ return 0;
7
+ }
8
+ return Number(Math.max(0, Math.min(1, value)).toFixed(4));
9
+ }
10
+ function hasCitation(fragment) {
11
+ return Array.isArray(fragment.citationIds) && fragment.citationIds.some((citationId) => String(citationId || '').trim());
12
+ }
13
+ function textHasSubstance(fragment) {
14
+ return String(fragment.text || '').trim().length >= 24;
15
+ }
16
+ function hasDirectSupport(fragments) {
17
+ return fragments.some((fragment) => fragment.role === 'direct_support' && hasCitation(fragment) && textHasSubstance(fragment));
18
+ }
19
+ function hasDocumentAugmentation(fragments) {
20
+ return fragments.some((fragment) => ((fragment.role === 'parent_context' || fragment.role === 'adjacent_context')
21
+ && fragment.sourceBoundary === 'full_document'
22
+ && textHasSubstance(fragment)));
23
+ }
24
+ function hasGraphEvidence(fragments) {
25
+ return fragments.some((fragment) => fragment.role === 'graph_neighbor_support' && hasCitation(fragment) && textHasSubstance(fragment));
26
+ }
27
+ function hasConflictEvidence(fragments) {
28
+ return fragments.some((fragment) => fragment.role === 'conflict' && textHasSubstance(fragment));
29
+ }
30
+ function hasIncompleteSourceScan(pack) {
31
+ return pack.sourceDecisions.some(decision => decision.status === 'source_window_unavailable'
32
+ && String(decision.reason || '').startsWith('runtime_'));
33
+ }
34
+ function hasUnavailableGraphNeighborSourceWindow(pack) {
35
+ return pack.sourceDecisions.some((decision) => (decision.status === 'source_window_unavailable'
36
+ && String(decision.reason || '').includes('graph_neighbor_support')));
37
+ }
38
+ function hasBudgetViolation(pack) {
39
+ return pack.sourceDecisions.some((decision) => (decision.status === 'fragment_dropped'
40
+ && (decision.reason === 'max_total_chars_exceeded' || decision.reason === 'max_fragments_exceeded')));
41
+ }
42
+ function buildDeterministicReview(params) {
43
+ const fragments = Array.isArray(params.contextPack.fragments) ? params.contextPack.fragments : [];
44
+ const directSupport = hasDirectSupport(fragments);
45
+ const documentAugmentation = hasDocumentAugmentation(fragments);
46
+ const graphEvidence = hasGraphEvidence(fragments);
47
+ const conflictEvidence = hasConflictEvidence(fragments);
48
+ const graphNeighborSourceUnavailable = hasUnavailableGraphNeighborSourceWindow(params.contextPack);
49
+ const budgetViolation = hasBudgetViolation(params.contextPack);
50
+ const reasons = [];
51
+ if (!directSupport) {
52
+ reasons.push('missing_direct_support');
53
+ }
54
+ if (!documentAugmentation) {
55
+ reasons.push('document_augmentation_missing');
56
+ }
57
+ const graphNeighborEvidenceMissing = Boolean(params.graphContext && (!graphEvidence || graphNeighborSourceUnavailable) && ((params.graphContext.predecessorWindow?.length || 0) > 0
58
+ || (params.graphContext.successorWindow?.length || 0) > 0));
59
+ if (graphNeighborEvidenceMissing) {
60
+ reasons.push('graph_neighbor_evidence_missing');
61
+ }
62
+ if (conflictEvidence) {
63
+ reasons.push('conflict_evidence_present');
64
+ }
65
+ if (budgetViolation) {
66
+ reasons.push('context_budget_dropped_fragments');
67
+ }
68
+ const incompleteSourceScan = hasIncompleteSourceScan(params.contextPack);
69
+ if (incompleteSourceScan)
70
+ reasons.push('source_scan_incomplete');
71
+ if (!directSupport) {
72
+ return {
73
+ reviewedAt: String(params.reviewedAt || new Date().toISOString()),
74
+ status: 'insufficient',
75
+ score: 0.2,
76
+ reasons,
77
+ deterministic: true,
78
+ recoveryAttempted: false,
79
+ llmJudgeUsed: false,
80
+ degradationState: 'insufficient_evidence',
81
+ };
82
+ }
83
+ let score = 0.58;
84
+ if (documentAugmentation) {
85
+ score += 0.24;
86
+ }
87
+ if (graphEvidence) {
88
+ score += 0.08;
89
+ }
90
+ if (!budgetViolation) {
91
+ score += 0.06;
92
+ }
93
+ if (conflictEvidence) {
94
+ score -= 0.18;
95
+ }
96
+ score = clampUnit(score);
97
+ const status = score >= 0.75
98
+ && documentAugmentation
99
+ && !conflictEvidence
100
+ && !graphNeighborEvidenceMissing
101
+ && !incompleteSourceScan
102
+ ? 'sufficient'
103
+ : 'borderline';
104
+ return {
105
+ reviewedAt: String(params.reviewedAt || new Date().toISOString()),
106
+ status,
107
+ score,
108
+ reasons,
109
+ deterministic: true,
110
+ recoveryAttempted: false,
111
+ llmJudgeUsed: false,
112
+ degradationState: status === 'sufficient'
113
+ ? 'none'
114
+ : conflictEvidence
115
+ ? 'conflict'
116
+ : 'partial_coverage',
117
+ };
118
+ }
119
+ function mergeLlmJudgeReview(deterministicReview, judgeReview) {
120
+ if (!judgeReview) {
121
+ return deterministicReview;
122
+ }
123
+ const nextStatus = judgeReview.status === 'sufficient'
124
+ || judgeReview.status === 'borderline'
125
+ || judgeReview.status === 'insufficient'
126
+ ? judgeReview.status
127
+ : deterministicReview.status;
128
+ const nextScore = Number.isFinite(judgeReview.score)
129
+ ? clampUnit(Number(judgeReview.score))
130
+ : deterministicReview.score;
131
+ const nextReasons = Array.isArray(judgeReview.reasons) && judgeReview.reasons.length > 0
132
+ ? judgeReview.reasons.map((reason) => String(reason || '').trim()).filter(Boolean)
133
+ : deterministicReview.reasons;
134
+ return {
135
+ ...deterministicReview,
136
+ ...judgeReview,
137
+ status: nextStatus,
138
+ score: nextScore,
139
+ reasons: nextReasons,
140
+ deterministic: false,
141
+ llmJudgeUsed: true,
142
+ };
143
+ }
144
+ async function reviewRagContextSufficiency(params) {
145
+ const deterministicReview = buildDeterministicReview(params);
146
+ if (deterministicReview.status !== 'borderline'
147
+ || params.allowLlmJudge !== true
148
+ || typeof params.llmJudge !== 'function'
149
+ || hasIncompleteSourceScan(params.contextPack)) {
150
+ return deterministicReview;
151
+ }
152
+ try {
153
+ const judgeReview = await params.llmJudge({
154
+ signal: params.signal,
155
+ query: params.query,
156
+ contextPack: params.contextPack,
157
+ graphContext: params.graphContext,
158
+ });
159
+ return mergeLlmJudgeReview(deterministicReview, judgeReview);
160
+ }
161
+ catch (error) {
162
+ return {
163
+ ...deterministicReview,
164
+ reasons: [
165
+ ...deterministicReview.reasons,
166
+ `llm_judge_failed:${String(error?.message || error || 'unknown')}`,
167
+ ],
168
+ llmJudgeUsed: false,
169
+ };
170
+ }
171
+ }
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ragSufficiencyJudge_1 = require("./ragSufficiencyJudge");
4
+ function makeFragment(overrides = {}) {
5
+ const text = overrides.text || 'A water glass is a transparent drinking vessel that contains water.';
6
+ return {
7
+ fragmentId: overrides.fragmentId || `fragment_${overrides.role || 'direct_support'}`,
8
+ role: overrides.role || 'direct_support',
9
+ text,
10
+ atomId: overrides.atomId || 'atom_water_glass',
11
+ documentId: overrides.documentId || 'doc_water_glass',
12
+ sourcePath: overrides.sourcePath || 'Knowledge_Base/test/water-glass.md',
13
+ title: overrides.title || 'Water Glass',
14
+ headingPath: Array.isArray(overrides.headingPath) ? overrides.headingPath : ['Water Glass'],
15
+ startOffset: overrides.startOffset,
16
+ endOffset: overrides.endOffset,
17
+ startLine: overrides.startLine,
18
+ endLine: overrides.endLine,
19
+ charCount: text.length,
20
+ tokenEstimate: Math.ceil(text.length / 4),
21
+ truncated: overrides.truncated === true,
22
+ truncationReason: overrides.truncationReason,
23
+ citationIds: Array.isArray(overrides.citationIds) ? overrides.citationIds : ['evidence_water_glass'],
24
+ relationEdgeIds: Array.isArray(overrides.relationEdgeIds) ? overrides.relationEdgeIds : [],
25
+ score: Number.isFinite(overrides.score) ? Number(overrides.score) : 0.8,
26
+ sourceBoundary: overrides.sourceBoundary || 'direct_span_only',
27
+ };
28
+ }
29
+ function makePack(fragments) {
30
+ return {
31
+ query: 'what is water glass?',
32
+ generatedAt: '2026-07-05T00:00:00.000Z',
33
+ sourceBoundary: fragments.some((fragment) => fragment.sourceBoundary === 'full_document')
34
+ ? 'full_document'
35
+ : 'direct_span_only',
36
+ budget: {
37
+ maxFragments: 8,
38
+ maxCharsPerFragment: 800,
39
+ maxTotalChars: 2400,
40
+ },
41
+ fragments,
42
+ sourceDecisions: [],
43
+ totalCharCount: fragments.reduce((sum, fragment) => sum + fragment.charCount, 0),
44
+ tokenEstimate: fragments.reduce((sum, fragment) => sum + fragment.tokenEstimate, 0),
45
+ };
46
+ }
47
+ describe('reviewRagContextSufficiency', () => {
48
+ test('marks direct citation plus document augmentation as sufficient without using LLM review', async () => {
49
+ const llmJudge = jest.fn();
50
+ const review = await (0, ragSufficiencyJudge_1.reviewRagContextSufficiency)({
51
+ query: 'what is water glass?',
52
+ contextPack: makePack([
53
+ makeFragment({
54
+ role: 'direct_support',
55
+ text: 'A water glass is a transparent drinking vessel that contains water.',
56
+ }),
57
+ makeFragment({
58
+ role: 'parent_context',
59
+ text: '## Definition\n\nA water glass is a transparent drinking vessel that contains water.\n\nThe vessel boundary and water surface define the observed optical behavior.',
60
+ sourceBoundary: 'full_document',
61
+ }),
62
+ ]),
63
+ llmJudge,
64
+ });
65
+ expect(review.status).toBe('sufficient');
66
+ expect(review.score).toBeGreaterThanOrEqual(0.75);
67
+ expect(review.deterministic).toBe(true);
68
+ expect(review.llmJudgeUsed).toBe(false);
69
+ expect(llmJudge).not.toHaveBeenCalled();
70
+ });
71
+ test('marks missing direct support as insufficient instead of allowing fluent overreach', async () => {
72
+ const review = await (0, ragSufficiencyJudge_1.reviewRagContextSufficiency)({
73
+ query: 'what is water glass?',
74
+ contextPack: makePack([
75
+ makeFragment({
76
+ role: 'background',
77
+ text: 'Background note about liquids and containers.',
78
+ citationIds: [],
79
+ }),
80
+ ]),
81
+ });
82
+ expect(review.status).toBe('insufficient');
83
+ expect(review.degradationState).toBe('insufficient_evidence');
84
+ expect(review.reasons).toContain('missing_direct_support');
85
+ });
86
+ test('keeps direct-span-only answers borderline so callers can recover once', async () => {
87
+ const review = await (0, ragSufficiencyJudge_1.reviewRagContextSufficiency)({
88
+ query: 'what is water glass?',
89
+ contextPack: makePack([
90
+ makeFragment({
91
+ role: 'direct_support',
92
+ text: 'A water glass is a transparent drinking vessel that contains water.',
93
+ }),
94
+ ]),
95
+ });
96
+ expect(review.status).toBe('borderline');
97
+ expect(review.degradationState).toBe('partial_coverage');
98
+ expect(review.reasons).toEqual(expect.arrayContaining([
99
+ 'document_augmentation_missing',
100
+ ]));
101
+ });
102
+ test('degrades graph evidence when graph-neighbor source windows are unavailable', async () => {
103
+ const pack = makePack([
104
+ makeFragment({
105
+ role: 'direct_support',
106
+ text: 'A brittle glass vessel is stiff and transparent but has low impact tolerance.',
107
+ documentId: 'doc_brittle_glass',
108
+ sourcePath: 'Knowledge_Base/test/brittle-glass.md',
109
+ }),
110
+ makeFragment({
111
+ role: 'parent_context',
112
+ text: '# Brittle Glass Vessel\n\nA brittle glass vessel is stiff and transparent but has low impact tolerance.',
113
+ documentId: 'doc_brittle_glass',
114
+ sourcePath: 'Knowledge_Base/test/brittle-glass.md',
115
+ sourceBoundary: 'full_document',
116
+ }),
117
+ makeFragment({
118
+ role: 'graph_neighbor_support',
119
+ text: 'Missing neighbor evidence should not be treated as complete graph evidence.',
120
+ atomId: 'atom_missing_neighbor',
121
+ documentId: 'doc_missing_neighbor',
122
+ sourcePath: 'Knowledge_Base/test/missing-neighbor.md',
123
+ title: 'Missing Neighbor Evidence',
124
+ sourceBoundary: 'direct_span_only',
125
+ }),
126
+ ]);
127
+ pack.sourceDecisions = [
128
+ {
129
+ documentId: 'doc_brittle_glass',
130
+ sourcePath: 'Knowledge_Base/test/brittle-glass.md',
131
+ sourceBoundary: 'full_document',
132
+ status: 'read',
133
+ },
134
+ {
135
+ documentId: 'doc_missing_neighbor',
136
+ sourcePath: 'Knowledge_Base/test/missing-neighbor.md',
137
+ sourceBoundary: 'direct_span_only',
138
+ status: 'source_window_unavailable',
139
+ reason: 'source_resolver_returned_no_content:graph_neighbor_support',
140
+ },
141
+ ];
142
+ const review = await (0, ragSufficiencyJudge_1.reviewRagContextSufficiency)({
143
+ query: 'compare brittle glass vessel with missing neighbor evidence',
144
+ contextPack: pack,
145
+ graphContext: {
146
+ anchorAtomId: 'atom_brittle_glass',
147
+ anchorTitle: 'Brittle Glass Vessel',
148
+ anchorDocumentId: 'doc_brittle_glass',
149
+ predecessorWindow: [],
150
+ successorWindow: [
151
+ {
152
+ atomId: 'atom_missing_neighbor',
153
+ title: 'Missing Neighbor Evidence',
154
+ relationKind: 'analogy',
155
+ confidence: 0.91,
156
+ },
157
+ ],
158
+ supportingAtomIds: ['atom_missing_neighbor'],
159
+ supportingTitles: ['Missing Neighbor Evidence'],
160
+ relationKinds: ['analogy'],
161
+ relationSummaries: [],
162
+ knowledgePointRelations: [],
163
+ temporalValidity: {
164
+ checkedAt: '2026-07-05T00:00:00.000Z',
165
+ allPointsValid: true,
166
+ warningReasons: [],
167
+ invalidKnowledgePointTitles: [],
168
+ edgeKinds: [],
169
+ details: [],
170
+ },
171
+ },
172
+ });
173
+ expect(review.status).toBe('borderline');
174
+ expect(review.degradationState).toBe('partial_coverage');
175
+ expect(review.reasons).toContain('graph_neighbor_evidence_missing');
176
+ });
177
+ });