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,1368 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assembleRagEvidenceContext = assembleRagEvidenceContext;
4
+ const ragContextPack_1 = require("./ragContextPack");
5
+ const graphConditionedContext_1 = require("./graphConditionedContext");
6
+ const ragEvidenceQuality_1 = require("./ragEvidenceQuality");
7
+ const DEFAULT_PARAGRAPH_WINDOW = 5;
8
+ const MAX_GRAPH_NEIGHBOR_DOCUMENT_CONTEXT_FRAGMENTS = 2;
9
+ const COMPARABLE_QUANTITY_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:count|limit|threshold|budget|quota|capacity|size|window|attempts|retries))\s+(?:is|are|=|:)\s*(-?\d+(?:\.\d+)?)\b/gi;
10
+ const COMPARABLE_DATE_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:date|year|deadline|cutoff|cut-off|version|release|revision|effective))\s+(?:is|=|:)\s*(\d{4}(?:-\d{2}-\d{2})?)\b/gi;
11
+ const COMPARABLE_STATE_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:status|state|mode|flag|policy|availability|setting|gate|switch))\s+(?:is|=|:)\s*(enabled|disabled|active|inactive|available|unavailable|supported|unsupported|allowed|blocked|required|optional|open|closed|on|off)\b/gi;
12
+ const COMPARABLE_LOCATION_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:location|site|region|zone|room|rack|slot|bay))\s+(?:is|=|:)\s*([a-z0-9][a-z0-9 /_.-]{1,80}?)(?=\.|,|;|\n|$)/gi;
13
+ const COMPARABLE_IDENTITY_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:owner|assignee|contact|maintainer|team|group))\s+(?:is|=|:)\s*([a-z][a-z0-9 &/_.-]{1,80}?)(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
14
+ const COMPARABLE_ENDPOINT_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:endpoint|url|uri|route))\s+(?:is|=|:)\s*((?:https?:\/\/|\/|[a-z0-9][a-z0-9._-]*\/)[a-z0-9/?#&=._~:%+\-/]*?[a-z0-9/#&=_~:%+\-/])(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
15
+ const COMPARABLE_DEPENDENCY_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:dependency|package|provider|driver|runtime|library|module|plugin|adapter))\s+(?:is|are|=|:)\s*((?:@[a-z0-9._-]+\/)?[a-z0-9][a-z0-9+.#/_@ -]{0,79}?)(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
16
+ const COMPARABLE_FORMAT_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:format|schema|encoding|serialization|content type|mime type))\s+(?:is|are|=|:)\s*([a-z0-9][a-z0-9+.#/_ -]{0,79}?)(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
17
+ const COMPARABLE_PROTOCOL_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:protocol|transport protocol|wire protocol))\s+(?:is|are|=|:)\s*([a-z0-9][a-z0-9+.#/_ -]{0,79}?)(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
18
+ const COMPARABLE_VERSION_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:version|revision))\s+(?:is|are|=|:)\s*((?:v\s*)?\d+(?:\.\d+){1,4}(?:[-+._][a-z0-9]+)?|v\s*\d+(?:[-+._][a-z0-9]+)?)(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
19
+ const COMPARABLE_PORT_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:port|listener port|service port))\s+(?:is|are|=|:)\s*(\d{1,5})(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
20
+ const COMPARABLE_STATUS_CODE_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?(?:http status code|response status code|status code))\s+(?:is|are|=|:)\s*(\d{3})(?=\s+(?:in|for|on|under|within)\s+|\.|,|;|\n|$)/gi;
21
+ const COMPARABLE_STATE_VALUE_GROUPS = {
22
+ enabled: 'enabled_disabled',
23
+ disabled: 'enabled_disabled',
24
+ active: 'active_inactive',
25
+ inactive: 'active_inactive',
26
+ available: 'available_unavailable',
27
+ unavailable: 'available_unavailable',
28
+ supported: 'supported_unsupported',
29
+ unsupported: 'supported_unsupported',
30
+ allowed: 'allowed_blocked',
31
+ blocked: 'allowed_blocked',
32
+ required: 'required_optional',
33
+ optional: 'required_optional',
34
+ open: 'open_closed',
35
+ closed: 'open_closed',
36
+ on: 'on_off',
37
+ off: 'on_off',
38
+ };
39
+ const COMPARABLE_TEMPORAL_SCOPE_GROUPS = {
40
+ current: 'current',
41
+ active: 'current',
42
+ present: 'current',
43
+ latest: 'current',
44
+ historical: 'historical',
45
+ historic: 'historical',
46
+ legacy: 'historical',
47
+ previous: 'historical',
48
+ archived: 'historical',
49
+ deprecated: 'historical',
50
+ superseded: 'historical',
51
+ planned: 'planned',
52
+ future: 'planned',
53
+ upcoming: 'planned',
54
+ scheduled: 'planned',
55
+ };
56
+ const COMPARABLE_TEMPORAL_SCOPE_PATTERN = /\b(current|active|present|latest|historical|historic|legacy|previous|archived|deprecated|superseded|planned|future|upcoming|scheduled)\b/i;
57
+ const COMPARABLE_ENVIRONMENT_SCOPE_ALIASES = {
58
+ production: 'production',
59
+ prod: 'production',
60
+ staging: 'staging',
61
+ stage: 'staging',
62
+ development: 'development',
63
+ dev: 'development',
64
+ test: 'test',
65
+ testing: 'test',
66
+ qa: 'qa',
67
+ uat: 'uat',
68
+ sandbox: 'sandbox',
69
+ local: 'local',
70
+ preview: 'preview',
71
+ canary: 'canary',
72
+ };
73
+ const COMPARABLE_ENVIRONMENT_SCOPE_PATTERN = /\b(?:in|for|on|under|within)\s+(?:the\s+)?(production|prod|staging|stage|development|dev|test|testing|qa|uat|sandbox|local|preview|canary)(?:\s+(?:environment|env|deployment|cluster|workspace|tenant|runtime))?\b|\b(production|staging|development|test|testing|qa|uat|sandbox|local|preview|canary)\s+(?:environment|env|deployment|cluster|workspace|tenant|runtime)\b/i;
74
+ const COMPARABLE_VERSION_SCOPE_PATTERN = /\b(?:in|for|on|under|within)\s+(?:the\s+)?(?:version|ver\.?|v)\s*([0-9]+(?:\.[0-9]+){0,3}(?:[-+._][a-z0-9]+)?)\b|\b(?:version|ver\.?|v)\s*([0-9]+(?:\.[0-9]+){0,3}(?:[-+._][a-z0-9]+)?)\b/i;
75
+ const COMPARABLE_PLATFORM_SCOPE_ALIASES = {
76
+ windows: 'windows',
77
+ win32: 'windows',
78
+ macos: 'macos',
79
+ mac: 'macos',
80
+ linux: 'linux',
81
+ android: 'android',
82
+ ios: 'ios',
83
+ web: 'web',
84
+ desktop: 'desktop',
85
+ mobile: 'mobile',
86
+ };
87
+ const COMPARABLE_PLATFORM_SCOPE_PATTERN = /\b(?:in|for|on|under|within)\s+(?:the\s+)?(windows|win32|macos|mac|linux|android|ios|web|desktop|mobile)(?:\s+(?:platform|os|runtime|client|app|build|target))?\b|\b(windows|win32|macos|mac|linux|android|ios|web|desktop|mobile)\s+(?:platform|os|runtime|client|app|build|target)\b/i;
88
+ const COMPARABLE_TIME_SCOPE_PATTERN = /\b(?:in|during|on|as of)\s+(\d{4}(?:-\d{2}(?:-\d{2})?)?)\b/i;
89
+ const MEASUREMENT_UNIT_GROUPS = [
90
+ { aliases: ['B', 'byte', 'bytes', '字节'], dimension: 'information', scale: 1 },
91
+ { aliases: ['b', 'bit', 'bits', '比特'], dimension: 'information', scale: 1 / 8 },
92
+ { aliases: ['kB', 'kilobyte', 'kilobytes'], dimension: 'information', scale: 1000 },
93
+ { aliases: ['MB', 'megabyte', 'megabytes', '兆字节'], dimension: 'information', scale: 1e6 },
94
+ { aliases: ['Mb', 'megabit', 'megabits'], dimension: 'information', scale: 1e6 / 8 },
95
+ { aliases: ['GB', 'gigabyte', 'gigabytes'], dimension: 'information', scale: 1e9 },
96
+ { aliases: ['KiB', 'kibibyte', 'kibibytes'], dimension: 'information', scale: 1024 },
97
+ { aliases: ['MiB', 'mebibyte', 'mebibytes'], dimension: 'information', scale: 1024 ** 2 },
98
+ { aliases: ['GiB', 'gibibyte', 'gibibytes'], dimension: 'information', scale: 1024 ** 3 },
99
+ { aliases: ['m', 'meter', 'meters', 'metre', 'metres', '米'], dimension: 'length', scale: 1 },
100
+ { aliases: ['cm', '厘米'], dimension: 'length', scale: 1e-2 },
101
+ { aliases: ['mm', '毫米'], dimension: 'length', scale: 1e-3 },
102
+ { aliases: ['um', 'µm', 'μm', '微米'], dimension: 'length', scale: 1e-6 },
103
+ { aliases: ['nm', '纳米'], dimension: 'length', scale: 1e-9 },
104
+ { aliases: ['kg', '千克', '公斤'], dimension: 'mass', scale: 1 },
105
+ { aliases: ['g', 'gram', 'grams', '克'], dimension: 'mass', scale: 1e-3 },
106
+ { aliases: ['mg', '毫克'], dimension: 'mass', scale: 1e-6 },
107
+ { aliases: ['s', 'second', 'seconds', '秒'], dimension: 'duration', scale: 1 },
108
+ { aliases: ['ms', 'millisecond', 'milliseconds', '毫秒'], dimension: 'duration', scale: 1e-3 },
109
+ { aliases: ['us', 'µs', 'μs', '微秒'], dimension: 'duration', scale: 1e-6 },
110
+ { aliases: ['min', 'minute', 'minutes', '分钟'], dimension: 'duration', scale: 60 },
111
+ { aliases: ['h', 'hour', 'hours', '小时'], dimension: 'duration', scale: 3600 },
112
+ { aliases: ['d', 'day', 'days', '天', '日'], dimension: 'duration', scale: 86400 },
113
+ { aliases: ['Hz', 'hz', 'hertz', '赫兹'], dimension: 'frequency', scale: 1 },
114
+ { aliases: ['kHz', 'khz', '千赫兹'], dimension: 'frequency', scale: 1000 },
115
+ { aliases: ['K', 'kelvin', '开尔文'], dimension: 'temperature', scale: 1 },
116
+ { aliases: ['C', 'c', '°C', '°c', '℃', '摄氏度'], dimension: 'temperature', scale: 1, offset: 273.15 },
117
+ { aliases: ['deg', 'degree', 'degrees', '度'], dimension: 'angle', scale: Math.PI / 180 },
118
+ { aliases: ['rad', 'radian', 'radians', '弧度'], dimension: 'angle', scale: 1 },
119
+ { aliases: ['%'], dimension: 'ratio', scale: 0.01 },
120
+ ];
121
+ const MEASUREMENT_UNITS = new Map(MEASUREMENT_UNIT_GROUPS.flatMap(group => group.aliases.map(alias => [alias, group])));
122
+ const MEASUREMENT_UNIT_PATTERN = Array.from(MEASUREMENT_UNITS.keys()).sort((left, right) => right.length - left.length).join('|');
123
+ const MEASUREMENT_NUMBER_PATTERN = /[+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
124
+ const MEASUREMENT_PREFIX_PATTERNS = [
125
+ /(?<![\p{L}\p{N}])([\p{L}][\p{L}\p{N} _-]{1,100}?)(?:\s+(?:is|are)\s+|\s*[:=]\s*)(not\s+)?/u,
126
+ /(?<![\p{L}\p{N}])([\p{L}][\p{L}\p{N} _-]{1,100}?)\s*(?:(并不是|不是|不为|不等于|并非)|是|为|等于|:)\s*/u,
127
+ ];
128
+ const MEASUREMENT_FACT_PATTERNS = MEASUREMENT_PREFIX_PATTERNS.map(prefix => new RegExp(prefix.source + /(?:(?:\+\s*\/\s*-|±)\s*)?/.source + '(' + MEASUREMENT_NUMBER_PATTERN.source + ')' + /\s*/.source
129
+ + '(' + MEASUREMENT_UNIT_PATTERN + ')' + /(?![a-z0-9_])/.source, 'giu'));
130
+ const MEASUREMENT_UNIT_SUFFIX_PATTERN = new RegExp('^\\s*(?:' + MEASUREMENT_UNIT_PATTERN + ')(?![a-z0-9_])', 'iu');
131
+ const CHINESE_SCOPE_TERMS = {
132
+ 当前: ' current ', 目前: ' current ', 现行: ' current ', 历史: ' historical ', 旧版: ' historical ',
133
+ 计划: ' planned ', 未来: ' planned ', 生产环境: ' production environment ', 测试环境: ' test environment ',
134
+ 开发环境: ' development environment ', 预发环境: ' staging environment ', 预生产环境: ' staging environment ',
135
+ 版本: ' version ', 安卓平台: ' android platform ', 桌面平台: ' desktop platform ', 移动平台: ' mobile platform ',
136
+ };
137
+ const CHINESE_SCOPE_PATTERN = new RegExp(Object.keys(CHINESE_SCOPE_TERMS).sort((a, b) => b.length - a.length).join('|'), 'gu');
138
+ function normalizeScopeLanguage(value) {
139
+ return value.replace(CHINESE_SCOPE_PATTERN, term => CHINESE_SCOPE_TERMS[term])
140
+ .replace(/(\d{4})年(?:(\d{1,2})月)?(?:(\d{1,2})日)?/gu, (_match, year, month, day) => (` in ${year}${month ? `-${month.padStart(2, '0')}` : ''}${day ? `-${day.padStart(2, '0')}` : ''} `));
141
+ }
142
+ function normalizeWhitespace(value) {
143
+ return String(value || '').replace(/\s+/g, ' ').trim();
144
+ }
145
+ function finishEvidenceFragment(fragment, execution) {
146
+ if (!execution)
147
+ return fragment;
148
+ execution.recordFragment();
149
+ if (fragment.text.length <= execution.maxFragmentChars)
150
+ return fragment;
151
+ const text = fragment.text.slice(0, execution.maxFragmentChars);
152
+ return {
153
+ ...fragment, text, charCount: text.length, tokenEstimate: (0, ragContextPack_1.estimateRagTokenCount)(text),
154
+ truncated: true, truncationReason: 'runtime_fragment_chars_limit',
155
+ };
156
+ }
157
+ function sanitizeFragmentPart(value) {
158
+ return normalizeWhitespace(value)
159
+ .replace(/[^a-zA-Z0-9_-]+/g, '_')
160
+ .replace(/^_+|_+$/g, '')
161
+ .slice(0, 80) || 'fragment';
162
+ }
163
+ function splitSourceLines(content, execution) {
164
+ const normalizedContent = String(content || '');
165
+ if (!normalizedContent) {
166
+ return [];
167
+ }
168
+ const records = [];
169
+ const newline = /\r\n|\n|\r/g;
170
+ let cursor = 0;
171
+ let delimiter;
172
+ while ((delimiter = newline.exec(normalizedContent)) !== null) {
173
+ execution?.checkSourceLineCount(records.length + 1);
174
+ records.push({
175
+ lineNumber: records.length + 1,
176
+ text: normalizedContent.slice(cursor, delimiter.index),
177
+ startOffset: cursor,
178
+ endOffset: delimiter.index,
179
+ });
180
+ cursor = delimiter.index + delimiter[0].length;
181
+ }
182
+ execution?.checkSourceLineCount(records.length + 1);
183
+ records.push({ lineNumber: records.length + 1, text: normalizedContent.slice(cursor), startOffset: cursor, endOffset: normalizedContent.length });
184
+ return records;
185
+ }
186
+ function isTableLine(text) {
187
+ const trimmed = String(text || '').trim();
188
+ return trimmed.startsWith('|') && trimmed.endsWith('|');
189
+ }
190
+ function parseMarkdownBlocks(content, execution) {
191
+ const sourceLines = splitSourceLines(content, execution);
192
+ const blocks = [];
193
+ const headingStack = [];
194
+ let pendingLines = [];
195
+ let pendingKind = 'paragraph';
196
+ let pendingHeadingPath = [];
197
+ let inCodeFence = false;
198
+ const currentHeadingPath = () => headingStack.map((heading) => heading.title);
199
+ const flushPending = () => {
200
+ if (pendingLines.length <= 0) {
201
+ return;
202
+ }
203
+ const text = pendingLines.map((line) => line.text).join('\n').trim();
204
+ if (text) {
205
+ const first = pendingLines[0];
206
+ const last = pendingLines[pendingLines.length - 1];
207
+ blocks.push({
208
+ kind: pendingKind,
209
+ text,
210
+ startOffset: first.startOffset,
211
+ endOffset: last.endOffset,
212
+ startLine: first.lineNumber,
213
+ endLine: last.lineNumber,
214
+ headingPath: [...pendingHeadingPath],
215
+ });
216
+ }
217
+ pendingLines = [];
218
+ pendingKind = 'paragraph';
219
+ pendingHeadingPath = currentHeadingPath();
220
+ };
221
+ sourceLines.forEach((line) => {
222
+ execution?.assertActive();
223
+ const rawText = String(line.text || '');
224
+ const trimmed = rawText.trim();
225
+ const fenceLine = /^```/.test(trimmed);
226
+ if (fenceLine) {
227
+ if (!inCodeFence) {
228
+ flushPending();
229
+ pendingKind = 'code';
230
+ pendingHeadingPath = currentHeadingPath();
231
+ pendingLines = [line];
232
+ inCodeFence = true;
233
+ return;
234
+ }
235
+ pendingLines.push(line);
236
+ inCodeFence = false;
237
+ flushPending();
238
+ return;
239
+ }
240
+ if (inCodeFence) {
241
+ pendingLines.push(line);
242
+ return;
243
+ }
244
+ if (!trimmed) {
245
+ flushPending();
246
+ return;
247
+ }
248
+ const headingMatch = /^(#{1,6})\s+(.+?)\s*$/.exec(trimmed);
249
+ if (headingMatch) {
250
+ flushPending();
251
+ const level = headingMatch[1].length;
252
+ const title = normalizeWhitespace(headingMatch[2].replace(/#+\s*$/, ''));
253
+ while (headingStack.length > 0 && headingStack[headingStack.length - 1].level >= level) {
254
+ headingStack.pop();
255
+ }
256
+ headingStack.push({ level, title });
257
+ blocks.push({
258
+ kind: 'heading',
259
+ text: trimmed,
260
+ startOffset: line.startOffset,
261
+ endOffset: line.endOffset,
262
+ startLine: line.lineNumber,
263
+ endLine: line.lineNumber,
264
+ headingPath: currentHeadingPath(),
265
+ });
266
+ pendingHeadingPath = currentHeadingPath();
267
+ return;
268
+ }
269
+ const nextKind = isTableLine(trimmed) ? 'table' : 'paragraph';
270
+ if (pendingLines.length > 0 && pendingKind !== nextKind) {
271
+ flushPending();
272
+ }
273
+ if (pendingLines.length <= 0) {
274
+ pendingKind = nextKind;
275
+ pendingHeadingPath = currentHeadingPath();
276
+ }
277
+ pendingLines.push(line);
278
+ });
279
+ flushPending();
280
+ return blocks;
281
+ }
282
+ function spanHasUsableOffsets(span, sourceLength) {
283
+ return Number.isFinite(span.startOffset)
284
+ && Number.isFinite(span.endOffset)
285
+ && span.startOffset >= 0
286
+ && span.endOffset >= span.startOffset
287
+ && span.startOffset <= sourceLength;
288
+ }
289
+ function blocksContainSnippet(blocks, snippet) {
290
+ if (!snippet) {
291
+ return true;
292
+ }
293
+ return normalizeWhitespace(blocks.map((block) => block.text).join(' ')).includes(snippet);
294
+ }
295
+ function blocksForEvidence(blocks, span, content) {
296
+ const snippet = normalizeWhitespace(span.snippet);
297
+ const lineMatches = Number.isFinite(span.startLine) && Number.isFinite(span.endLine) && span.startLine > 0
298
+ ? blocks.filter((block) => block.endLine >= span.startLine && block.startLine <= span.endLine)
299
+ : [];
300
+ if (spanHasUsableOffsets(span, content.length)) {
301
+ const endOffset = Math.min(span.endOffset, content.length);
302
+ const matches = blocks.filter((block) => block.endOffset >= span.startOffset && block.startOffset <= endOffset);
303
+ if (matches.length > 0) {
304
+ if (!blocksContainSnippet(matches, snippet) && blocksContainSnippet(lineMatches, snippet)) {
305
+ return lineMatches;
306
+ }
307
+ return matches;
308
+ }
309
+ }
310
+ if (lineMatches.length > 0) {
311
+ return lineMatches;
312
+ }
313
+ if (snippet) {
314
+ const normalizedBlocks = blocks.filter((block) => normalizeWhitespace(block.text).includes(snippet));
315
+ if (normalizedBlocks.length > 0) {
316
+ return normalizedBlocks;
317
+ }
318
+ }
319
+ return [];
320
+ }
321
+ function sameHeadingPath(a, b) {
322
+ return a.length === b.length && a.every((part, index) => part === b[index]);
323
+ }
324
+ function buildSectionBlocks(blocks, evidenceBlocks, paragraphWindow) {
325
+ if (evidenceBlocks.length <= 0) {
326
+ return [];
327
+ }
328
+ const headingPath = evidenceBlocks[0].headingPath;
329
+ if (headingPath.length > 0) {
330
+ const sectionBlocks = blocks.filter((block) => sameHeadingPath(block.headingPath, headingPath));
331
+ if (sectionBlocks.length > 0) {
332
+ return sectionBlocks;
333
+ }
334
+ }
335
+ const firstIndex = blocks.indexOf(evidenceBlocks[0]);
336
+ const lastIndex = blocks.indexOf(evidenceBlocks[evidenceBlocks.length - 1]);
337
+ if (firstIndex < 0 || lastIndex < 0) {
338
+ return evidenceBlocks;
339
+ }
340
+ const start = Math.max(0, firstIndex - paragraphWindow);
341
+ const end = Math.min(blocks.length - 1, lastIndex + paragraphWindow);
342
+ return blocks.slice(start, end + 1);
343
+ }
344
+ function sourceBlockKey(block) {
345
+ return `${block.startOffset}:${block.endOffset}:${block.text}`;
346
+ }
347
+ function mergeBlocks(blocks) {
348
+ const seen = new Set();
349
+ const merged = [];
350
+ blocks.forEach((block) => {
351
+ const key = sourceBlockKey(block);
352
+ if (seen.has(key)) {
353
+ return;
354
+ }
355
+ seen.add(key);
356
+ merged.push(block);
357
+ });
358
+ return merged.sort((a, b) => a.startOffset - b.startOffset);
359
+ }
360
+ function fragmentTextFromBlocks(blocks) {
361
+ return mergeBlocks(blocks)
362
+ .map((block) => block.text)
363
+ .filter(Boolean)
364
+ .join('\n\n')
365
+ .trim();
366
+ }
367
+ function normalizeComparableFactSubject(value) {
368
+ return normalizeWhitespace(value)
369
+ .toLowerCase()
370
+ .replace(/^(the|a|an)\s+/i, '')
371
+ .replace(/[^\p{L}\p{N}]+/gu, ' ')
372
+ .trim();
373
+ }
374
+ function comparableFactSentenceTail(blockText, match) {
375
+ const matchIndex = typeof match.index === 'number' ? match.index : -1;
376
+ if (matchIndex < 0) {
377
+ return '';
378
+ }
379
+ const tail = String(blockText || '').slice(matchIndex + String(match[0] || '').length);
380
+ const boundary = /[!?。!?;;\r\n]|\.(?!\d)/u.exec(tail);
381
+ return normalizeWhitespace(boundary ? tail.slice(0, boundary.index) : tail);
382
+ }
383
+ function comparableFactTemporalScopeKey(subjectLabel, sentenceTail) {
384
+ const scopedText = `${normalizeWhitespace(subjectLabel)} ${normalizeWhitespace(sentenceTail)}`;
385
+ const match = COMPARABLE_TEMPORAL_SCOPE_PATTERN.exec(scopedText);
386
+ if (!match) {
387
+ return null;
388
+ }
389
+ return COMPARABLE_TEMPORAL_SCOPE_GROUPS[String(match[1] || '').toLowerCase()] || null;
390
+ }
391
+ function comparableFactEnvironmentScopeKey(subjectLabel, sentenceTail) {
392
+ const scopedText = `${normalizeWhitespace(subjectLabel)} ${normalizeWhitespace(sentenceTail)}`;
393
+ const match = COMPARABLE_ENVIRONMENT_SCOPE_PATTERN.exec(scopedText);
394
+ if (!match) {
395
+ return null;
396
+ }
397
+ const environmentLabel = String(match[1] || match[2] || '').toLowerCase();
398
+ return COMPARABLE_ENVIRONMENT_SCOPE_ALIASES[environmentLabel] || null;
399
+ }
400
+ function comparableFactVersionScopeKey(subjectLabel, sentenceTail) {
401
+ const scopedText = `${normalizeWhitespace(subjectLabel)} ${normalizeWhitespace(sentenceTail)}`;
402
+ const match = COMPARABLE_VERSION_SCOPE_PATTERN.exec(scopedText);
403
+ if (!match) {
404
+ return null;
405
+ }
406
+ const versionLabel = normalizeWhitespace(match[1] || match[2] || '').toLowerCase();
407
+ if (!/^[0-9]+(?:\.[0-9]+){0,3}(?:[-+._][a-z0-9]+)?$/.test(versionLabel)) {
408
+ return null;
409
+ }
410
+ return versionLabel;
411
+ }
412
+ function comparableFactPlatformScopeKey(subjectLabel, sentenceTail) {
413
+ const scopedText = `${normalizeWhitespace(subjectLabel)} ${normalizeWhitespace(sentenceTail)}`;
414
+ const match = COMPARABLE_PLATFORM_SCOPE_PATTERN.exec(scopedText);
415
+ if (!match) {
416
+ return null;
417
+ }
418
+ const platformLabel = String(match[1] || match[2] || '').toLowerCase();
419
+ return COMPARABLE_PLATFORM_SCOPE_ALIASES[platformLabel] || null;
420
+ }
421
+ function comparableFactScopeKeys(subjectLabel, sentenceTail) {
422
+ subjectLabel = normalizeScopeLanguage(subjectLabel);
423
+ sentenceTail = normalizeScopeLanguage(sentenceTail);
424
+ const scopeKeys = [];
425
+ const temporalScopeKey = comparableFactTemporalScopeKey(subjectLabel, sentenceTail);
426
+ if (temporalScopeKey) {
427
+ scopeKeys.push(`temporal:${temporalScopeKey}`);
428
+ }
429
+ const environmentScopeKey = comparableFactEnvironmentScopeKey(subjectLabel, sentenceTail);
430
+ if (environmentScopeKey) {
431
+ scopeKeys.push(`environment:${environmentScopeKey}`);
432
+ }
433
+ const versionScopeKey = comparableFactVersionScopeKey(subjectLabel, sentenceTail);
434
+ if (versionScopeKey) {
435
+ scopeKeys.push(`version:${versionScopeKey}`);
436
+ }
437
+ const platformScopeKey = comparableFactPlatformScopeKey(subjectLabel, sentenceTail);
438
+ if (platformScopeKey) {
439
+ scopeKeys.push(`platform:${platformScopeKey}`);
440
+ }
441
+ const timeScope = COMPARABLE_TIME_SCOPE_PATTERN.exec(`${subjectLabel} ${sentenceTail}`)?.[1];
442
+ if (timeScope)
443
+ scopeKeys.push(`time:${timeScope}`);
444
+ return scopeKeys.sort();
445
+ }
446
+ function comparableFactSubjectKey(subjectLabel, scopeKeys) {
447
+ subjectLabel = normalizeScopeLanguage(subjectLabel);
448
+ const scopedSubjectLabel = scopeKeys.some((scopeKey) => scopeKey.startsWith('temporal:'))
449
+ ? normalizeWhitespace(subjectLabel).replace(COMPARABLE_TEMPORAL_SCOPE_PATTERN, '')
450
+ : subjectLabel;
451
+ const subjectKey = normalizeComparableFactSubject(scopedSubjectLabel
452
+ .replace(COMPARABLE_ENVIRONMENT_SCOPE_PATTERN, '')
453
+ .replace(COMPARABLE_PLATFORM_SCOPE_PATTERN, '')
454
+ .replace(COMPARABLE_VERSION_SCOPE_PATTERN, '')
455
+ .replace(COMPARABLE_TIME_SCOPE_PATTERN, ''));
456
+ return scopeKeys.length > 0 && subjectKey
457
+ ? `${subjectKey}@scope:${scopeKeys.join('+')}`
458
+ : subjectKey;
459
+ }
460
+ function measurementScopeKeys(text) {
461
+ const normalized = normalizeScopeLanguage(text);
462
+ const keys = new Set();
463
+ for (const pattern of [COMPARABLE_TEMPORAL_SCOPE_PATTERN, COMPARABLE_ENVIRONMENT_SCOPE_PATTERN,
464
+ COMPARABLE_VERSION_SCOPE_PATTERN, COMPARABLE_PLATFORM_SCOPE_PATTERN, COMPARABLE_TIME_SCOPE_PATTERN]) {
465
+ for (const match of normalized.matchAll(new RegExp(pattern.source, 'gi'))) {
466
+ comparableFactScopeKeys('', match[0]).forEach(key => keys.add(key));
467
+ }
468
+ }
469
+ // A coordinated qualifier ("in production or staging") is not a single scope.
470
+ if (Array.from(keys).some(key => key.startsWith('environment:'))) {
471
+ for (const word of normalized.toLowerCase().match(/\b[a-z]+\b/g) || []) {
472
+ const environment = COMPARABLE_ENVIRONMENT_SCOPE_ALIASES[word];
473
+ if (environment)
474
+ keys.add(`environment:${environment}`);
475
+ }
476
+ }
477
+ if (Array.from(keys).some(key => key.startsWith('platform:'))) {
478
+ for (const word of normalized.toLowerCase().match(/\b[a-z0-9]+\b/g) || []) {
479
+ const platform = COMPARABLE_PLATFORM_SCOPE_ALIASES[word];
480
+ if (platform)
481
+ keys.add(`platform:${platform}`);
482
+ }
483
+ }
484
+ const dimensions = new Set();
485
+ for (const key of keys) {
486
+ const dimension = key.slice(0, key.indexOf(':'));
487
+ if (dimensions.has(dimension))
488
+ return null;
489
+ dimensions.add(dimension);
490
+ }
491
+ return Array.from(keys).sort();
492
+ }
493
+ function measurementHeadingScopeKeys(headingPath) {
494
+ const byDimension = new Map();
495
+ for (const heading of headingPath) {
496
+ const keys = measurementScopeKeys(`in ${heading}`);
497
+ if (!keys)
498
+ return null;
499
+ for (const key of keys)
500
+ byDimension.set(key.slice(0, key.indexOf(':')), key);
501
+ }
502
+ return Array.from(byDimension.values()).sort();
503
+ }
504
+ function measurementAssertionScopeKeys(headingKeys, paragraphKeys, clauseKeys) {
505
+ const byDimension = new Map();
506
+ for (const key of [...headingKeys, ...paragraphKeys, ...clauseKeys]) {
507
+ byDimension.set(key.slice(0, key.indexOf(':')), key);
508
+ }
509
+ return Array.from(byDimension.values()).sort();
510
+ }
511
+ function standaloneMeasurementScopeKeys(clause) {
512
+ const normalized = normalizeScopeLanguage(clause).replace(/[.::。]+$/u, '').trim();
513
+ const keys = measurementScopeKeys(`in ${normalized}`);
514
+ if (!keys?.length)
515
+ return null;
516
+ const remainder = `in ${normalized}`
517
+ .replace(COMPARABLE_TEMPORAL_SCOPE_PATTERN, '')
518
+ .replace(COMPARABLE_ENVIRONMENT_SCOPE_PATTERN, '')
519
+ .replace(COMPARABLE_VERSION_SCOPE_PATTERN, '')
520
+ .replace(COMPARABLE_PLATFORM_SCOPE_PATTERN, '')
521
+ .replace(COMPARABLE_TIME_SCOPE_PATTERN, '')
522
+ .replace(/\b(?:in|for|on|under|within|during|as of|the)\b/gi, '').trim();
523
+ return remainder ? null : keys;
524
+ }
525
+ function normalizeComparableDateValue(value) {
526
+ const normalized = normalizeWhitespace(value);
527
+ const dateMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(normalized);
528
+ if (dateMatch) {
529
+ const year = Number(dateMatch[1]);
530
+ const month = Number(dateMatch[2]);
531
+ const day = Number(dateMatch[3]);
532
+ if (year >= 1000 && year <= 2999 && month >= 1 && month <= 12 && day >= 1 && day <= 31) {
533
+ return `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}`;
534
+ }
535
+ return null;
536
+ }
537
+ const yearMatch = /^(\d{4})$/.exec(normalized);
538
+ if (yearMatch) {
539
+ const year = Number(yearMatch[1]);
540
+ if (year >= 1000 && year <= 2999) {
541
+ return yearMatch[1];
542
+ }
543
+ }
544
+ return null;
545
+ }
546
+ function normalizeComparableStateValue(value) {
547
+ const valueKey = normalizeWhitespace(value).toLowerCase();
548
+ const groupKey = COMPARABLE_STATE_VALUE_GROUPS[valueKey];
549
+ if (!valueKey || !groupKey) {
550
+ return null;
551
+ }
552
+ return { valueKey, groupKey };
553
+ }
554
+ function normalizeComparableLocationValue(value) {
555
+ return normalizeWhitespace(value)
556
+ .toLowerCase()
557
+ .replace(/^(the|a|an)\s+/i, '')
558
+ .replace(/[^a-z0-9]+/g, ' ')
559
+ .trim();
560
+ }
561
+ function normalizeComparableIdentityValue(value) {
562
+ return normalizeWhitespace(value)
563
+ .toLowerCase()
564
+ .replace(/^(the|a|an)\s+/i, '')
565
+ .replace(/[^a-z0-9]+/g, ' ')
566
+ .trim();
567
+ }
568
+ function normalizeComparableEndpointValue(value) {
569
+ const normalized = normalizeWhitespace(value)
570
+ .toLowerCase()
571
+ .replace(/^['"`]+|['"`]+$/g, '');
572
+ return normalized.length > 1
573
+ ? normalized.replace(/\/+$/g, '')
574
+ : normalized;
575
+ }
576
+ function normalizeComparableDependencyValue(value) {
577
+ return normalizeWhitespace(value)
578
+ .toLowerCase()
579
+ .replace(/^['"`]+|['"`]+$/g, '')
580
+ .replace(/^(the|a|an)\s+/i, '')
581
+ .replace(/[^a-z0-9+.#/@_-]+/g, ' ')
582
+ .replace(/\s+/g, ' ')
583
+ .trim();
584
+ }
585
+ function normalizeComparableFormatValue(value) {
586
+ return normalizeWhitespace(value)
587
+ .toLowerCase()
588
+ .replace(/^['"`]+|['"`]+$/g, '')
589
+ .replace(/^(the|a|an)\s+/i, '')
590
+ .replace(/[^a-z0-9+.#/_-]+/g, ' ')
591
+ .replace(/\s+/g, ' ')
592
+ .trim();
593
+ }
594
+ function normalizeComparableProtocolValue(value) {
595
+ return normalizeWhitespace(value)
596
+ .toLowerCase()
597
+ .replace(/^['"`]+|['"`]+$/g, '')
598
+ .replace(/^(the|a|an)\s+/i, '')
599
+ .replace(/[^a-z0-9+.#/_-]+/g, ' ')
600
+ .replace(/\s+/g, ' ')
601
+ .trim();
602
+ }
603
+ function normalizeComparableVersionValue(value) {
604
+ return normalizeWhitespace(value)
605
+ .toLowerCase()
606
+ .replace(/^['"`]+|['"`]+$/g, '')
607
+ .replace(/^v\s*/i, '')
608
+ .replace(/\s+/g, '')
609
+ .trim();
610
+ }
611
+ function normalizeComparablePortValue(value) {
612
+ const port = Number(normalizeWhitespace(value));
613
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
614
+ return null;
615
+ }
616
+ return String(port);
617
+ }
618
+ function normalizeComparableStatusCodeValue(value) {
619
+ const statusCode = Number(normalizeWhitespace(value));
620
+ if (!Number.isInteger(statusCode) || statusCode < 100 || statusCode > 599) {
621
+ return null;
622
+ }
623
+ return String(statusCode);
624
+ }
625
+ function extractComparableEvidenceFacts(params) {
626
+ if (params.block.kind === 'heading' || params.block.kind === 'code') {
627
+ return [];
628
+ }
629
+ const facts = [];
630
+ const appendFact = (fact) => {
631
+ params.execution?.recordSourceFact();
632
+ facts.push(fact);
633
+ };
634
+ const headingKeys = measurementHeadingScopeKeys(params.block.headingPath);
635
+ let paragraphKeys = [];
636
+ for (const clause of (0, ragEvidenceQuality_1.iterateRagEvidenceClauses)(params.block.text)) {
637
+ params.execution?.assertActive();
638
+ const inheritedKeys = paragraphKeys;
639
+ // Only an immediately preceding standalone qualifier is unambiguous.
640
+ paragraphKeys = standaloneMeasurementScopeKeys(clause) || [];
641
+ const clauseKeys = measurementScopeKeys(clause);
642
+ if (!headingKeys || !clauseKeys)
643
+ continue;
644
+ if (/\b(?:approximately|roughly|about|at least|at most|between|range)\b|大约|约为|至少|至多|范围/iu.test(clause))
645
+ continue;
646
+ const scopeKeys = measurementAssertionScopeKeys(headingKeys, inheritedKeys, clauseKeys);
647
+ for (const pattern of MEASUREMENT_FACT_PATTERNS) {
648
+ for (const match of clause.matchAll(pattern)) {
649
+ params.execution?.assertActive();
650
+ const tail = clause.slice(match.index + match[0].length);
651
+ if (/^\s*(?:[\/^*]|(?:[-–—~~]|to|至|到)\s*[+-]?\d)/iu.test(tail))
652
+ continue;
653
+ const subjectLabel = normalizeWhitespace(match[1]);
654
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
655
+ const tolerance = /(?:\btolerance|公差|容差)$/iu.test(subjectLabel);
656
+ // A named tolerance defines a half-width; an uncertain observation does not define an exact value.
657
+ if (/±|\+\s*\/\s*-/u.test(clause)
658
+ && (!tolerance || !/±|\+\s*\/\s*-/u.test(match[0])))
659
+ continue;
660
+ // SI symbol case is significant: µM is not µm, nor Ms milliseconds.
661
+ const unit = MEASUREMENT_UNITS.get(match[4])
662
+ || (match[4].length > 2 ? MEASUREMENT_UNITS.get(match[4].toLowerCase()) : undefined);
663
+ if (!subjectKey || !unit)
664
+ continue;
665
+ const converted = Number(match[3]) * unit.scale + (tolerance ? 0 : (unit.offset || 0));
666
+ if (!Number.isFinite(converted) || (tolerance && converted < 0))
667
+ continue;
668
+ // Significant digits remove conversion noise without rounding tiny measurements to zero.
669
+ const magnitude = Number(converted.toPrecision(15));
670
+ const relation = match[2] ? 'not_equal' : 'equal';
671
+ const dimension = tolerance ? `tolerance:${unit.dimension}` : unit.dimension;
672
+ appendFact({
673
+ subjectKey, subjectLabel,
674
+ valueKey: `${dimension}:${relation}:${magnitude}`,
675
+ valueLabel: `${match[2] || ''}${match[3]} ${match[4]}`,
676
+ factKind: 'measurement', measurement: { dimension, magnitude, relation },
677
+ block: params.block, citationIds: params.citationIds, item: params.item,
678
+ });
679
+ }
680
+ }
681
+ }
682
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_QUANTITY_FACT_PATTERN)) {
683
+ if (MEASUREMENT_UNIT_SUFFIX_PATTERN.test(params.block.text.slice(match.index + match[0].length)))
684
+ continue;
685
+ const subjectLabel = normalizeWhitespace(match[1]);
686
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
687
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
688
+ const value = Number(match[2]);
689
+ if (!subjectKey || !Number.isFinite(value)) {
690
+ continue;
691
+ }
692
+ appendFact({
693
+ subjectKey,
694
+ subjectLabel,
695
+ valueKey: `${Number(value.toFixed(12))}`,
696
+ valueLabel: match[2],
697
+ factKind: 'quantity',
698
+ block: params.block,
699
+ citationIds: params.citationIds,
700
+ item: params.item,
701
+ });
702
+ }
703
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_DATE_FACT_PATTERN)) {
704
+ const subjectLabel = normalizeWhitespace(match[1]);
705
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
706
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
707
+ const valueKey = normalizeComparableDateValue(match[2]);
708
+ if (!subjectKey || !valueKey) {
709
+ continue;
710
+ }
711
+ appendFact({
712
+ subjectKey,
713
+ subjectLabel,
714
+ valueKey,
715
+ valueLabel: match[2],
716
+ factKind: 'date',
717
+ block: params.block,
718
+ citationIds: params.citationIds,
719
+ item: params.item,
720
+ });
721
+ }
722
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_STATE_FACT_PATTERN)) {
723
+ const subjectLabel = normalizeWhitespace(match[1]);
724
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
725
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
726
+ const stateValue = normalizeComparableStateValue(match[2]);
727
+ if (!subjectKey || !stateValue) {
728
+ continue;
729
+ }
730
+ appendFact({
731
+ subjectKey: `${subjectKey}:${stateValue.groupKey}`,
732
+ subjectLabel,
733
+ valueKey: stateValue.valueKey,
734
+ valueLabel: match[2],
735
+ factKind: 'state',
736
+ block: params.block,
737
+ citationIds: params.citationIds,
738
+ item: params.item,
739
+ });
740
+ }
741
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_LOCATION_FACT_PATTERN)) {
742
+ const subjectLabel = normalizeWhitespace(match[1]);
743
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, `${normalizeWhitespace(match[2])} ${comparableFactSentenceTail(params.block.text, match)}`);
744
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
745
+ const valueKey = normalizeComparableLocationValue(match[2]);
746
+ if (!subjectKey || !valueKey) {
747
+ continue;
748
+ }
749
+ appendFact({
750
+ subjectKey,
751
+ subjectLabel,
752
+ valueKey,
753
+ valueLabel: normalizeWhitespace(match[2]),
754
+ factKind: 'location',
755
+ block: params.block,
756
+ citationIds: params.citationIds,
757
+ item: params.item,
758
+ });
759
+ }
760
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_IDENTITY_FACT_PATTERN)) {
761
+ const subjectLabel = normalizeWhitespace(match[1]);
762
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, `${normalizeWhitespace(match[2])} ${comparableFactSentenceTail(params.block.text, match)}`);
763
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
764
+ const valueKey = normalizeComparableIdentityValue(match[2]);
765
+ if (!subjectKey || !valueKey) {
766
+ continue;
767
+ }
768
+ appendFact({
769
+ subjectKey,
770
+ subjectLabel,
771
+ valueKey,
772
+ valueLabel: normalizeWhitespace(match[2]),
773
+ factKind: 'identity',
774
+ block: params.block,
775
+ citationIds: params.citationIds,
776
+ item: params.item,
777
+ });
778
+ }
779
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_ENDPOINT_FACT_PATTERN)) {
780
+ const subjectLabel = normalizeWhitespace(match[1]);
781
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
782
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
783
+ const valueKey = normalizeComparableEndpointValue(match[2]);
784
+ if (!subjectKey || !valueKey) {
785
+ continue;
786
+ }
787
+ appendFact({
788
+ subjectKey,
789
+ subjectLabel,
790
+ valueKey,
791
+ valueLabel: normalizeWhitespace(match[2]),
792
+ factKind: 'endpoint',
793
+ block: params.block,
794
+ citationIds: params.citationIds,
795
+ item: params.item,
796
+ });
797
+ }
798
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_DEPENDENCY_FACT_PATTERN)) {
799
+ const subjectLabel = normalizeWhitespace(match[1]);
800
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
801
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
802
+ const valueKey = normalizeComparableDependencyValue(match[2]);
803
+ if (!subjectKey || !valueKey) {
804
+ continue;
805
+ }
806
+ appendFact({
807
+ subjectKey,
808
+ subjectLabel,
809
+ valueKey,
810
+ valueLabel: normalizeWhitespace(match[2]),
811
+ factKind: 'dependency',
812
+ block: params.block,
813
+ citationIds: params.citationIds,
814
+ item: params.item,
815
+ });
816
+ }
817
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_FORMAT_FACT_PATTERN)) {
818
+ const subjectLabel = normalizeWhitespace(match[1]);
819
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
820
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
821
+ const valueKey = normalizeComparableFormatValue(match[2]);
822
+ if (!subjectKey || !valueKey) {
823
+ continue;
824
+ }
825
+ appendFact({
826
+ subjectKey,
827
+ subjectLabel,
828
+ valueKey,
829
+ valueLabel: normalizeWhitespace(match[2]),
830
+ factKind: 'format',
831
+ block: params.block,
832
+ citationIds: params.citationIds,
833
+ item: params.item,
834
+ });
835
+ }
836
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_PROTOCOL_FACT_PATTERN)) {
837
+ const subjectLabel = normalizeWhitespace(match[1]);
838
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
839
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
840
+ const valueKey = normalizeComparableProtocolValue(match[2]);
841
+ if (!subjectKey || !valueKey) {
842
+ continue;
843
+ }
844
+ appendFact({
845
+ subjectKey,
846
+ subjectLabel,
847
+ valueKey,
848
+ valueLabel: normalizeWhitespace(match[2]),
849
+ factKind: 'protocol',
850
+ block: params.block,
851
+ citationIds: params.citationIds,
852
+ item: params.item,
853
+ });
854
+ }
855
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_VERSION_FACT_PATTERN)) {
856
+ const subjectLabel = normalizeWhitespace(match[1]);
857
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
858
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
859
+ const valueKey = normalizeComparableVersionValue(match[2]);
860
+ if (!subjectKey || !valueKey) {
861
+ continue;
862
+ }
863
+ appendFact({
864
+ subjectKey,
865
+ subjectLabel,
866
+ valueKey,
867
+ valueLabel: normalizeWhitespace(match[2]),
868
+ factKind: 'version',
869
+ block: params.block,
870
+ citationIds: params.citationIds,
871
+ item: params.item,
872
+ });
873
+ }
874
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_PORT_FACT_PATTERN)) {
875
+ const subjectLabel = normalizeWhitespace(match[1]);
876
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
877
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
878
+ const valueKey = normalizeComparablePortValue(match[2]);
879
+ if (!subjectKey || !valueKey) {
880
+ continue;
881
+ }
882
+ appendFact({
883
+ subjectKey,
884
+ subjectLabel,
885
+ valueKey,
886
+ valueLabel: match[2],
887
+ factKind: 'port',
888
+ block: params.block,
889
+ citationIds: params.citationIds,
890
+ item: params.item,
891
+ });
892
+ }
893
+ for (const match of String(params.block.text || '').matchAll(COMPARABLE_STATUS_CODE_FACT_PATTERN)) {
894
+ const subjectLabel = normalizeWhitespace(match[1]);
895
+ const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
896
+ const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
897
+ const valueKey = normalizeComparableStatusCodeValue(match[2]);
898
+ if (!subjectKey || !valueKey) {
899
+ continue;
900
+ }
901
+ appendFact({
902
+ subjectKey,
903
+ subjectLabel,
904
+ valueKey,
905
+ valueLabel: match[2],
906
+ factKind: 'status_code',
907
+ block: params.block,
908
+ citationIds: params.citationIds,
909
+ item: params.item,
910
+ });
911
+ }
912
+ return facts;
913
+ }
914
+ function buildBlockCitationMap(group, blocks, source) {
915
+ const citationIdsByBlock = new Map();
916
+ group.entries.forEach(({ item }) => {
917
+ itemEvidenceSpans(item).forEach((span) => {
918
+ blocksForEvidence(blocks, span, source.content).forEach((block) => {
919
+ const key = sourceBlockKey(block);
920
+ const citationIds = citationIdsByBlock.get(key) || new Set();
921
+ citationIds.add(span.id);
922
+ citationIdsByBlock.set(key, citationIds);
923
+ });
924
+ });
925
+ });
926
+ return citationIdsByBlock;
927
+ }
928
+ function extractComparableEvidenceFactsFromBlockEntries(entries, citationIdsByBlock, execution) {
929
+ return entries
930
+ .sort((left, right) => left.block.startOffset - right.block.startOffset)
931
+ .flatMap(({ block, item }) => extractComparableEvidenceFacts({
932
+ execution,
933
+ block,
934
+ item,
935
+ citationIds: Array.from(citationIdsByBlock.get(sourceBlockKey(block)) || []),
936
+ }));
937
+ }
938
+ function selectRepresentativeGroupItem(group) {
939
+ const rankedEntries = group.entries.slice().sort((left, right) => {
940
+ if (left.directRole !== right.directRole) {
941
+ return left.directRole === 'direct_support' ? -1 : 1;
942
+ }
943
+ return Number(right.item.score || 0) - Number(left.item.score || 0);
944
+ });
945
+ return rankedEntries[0]?.item || null;
946
+ }
947
+ function buildEvidenceItemMap(group, blocks, source) {
948
+ const itemByBlock = new Map();
949
+ group.entries.forEach(({ item }) => {
950
+ itemEvidenceSpans(item).forEach((span) => {
951
+ blocksForEvidence(blocks, span, source.content).forEach((block) => {
952
+ const key = sourceBlockKey(block);
953
+ const previous = itemByBlock.get(key);
954
+ if (!previous || Number(item.score || 0) > Number(previous.score || 0)) {
955
+ itemByBlock.set(key, item);
956
+ }
957
+ });
958
+ });
959
+ });
960
+ return itemByBlock;
961
+ }
962
+ function collectSelectedContextComparableFacts(group, source, paragraphWindow, blocks, execution) {
963
+ const citationIdsByBlock = buildBlockCitationMap(group, blocks, source);
964
+ const selectedBlocks = new Map();
965
+ group.entries
966
+ .filter((entry) => entry.expandDocumentContext)
967
+ .forEach(({ item }) => {
968
+ itemEvidenceSpans(item).forEach((span) => {
969
+ const evidenceBlocks = blocksForEvidence(blocks, span, source.content);
970
+ buildSectionBlocks(blocks, evidenceBlocks, paragraphWindow).forEach((block) => {
971
+ selectedBlocks.set(sourceBlockKey(block), { block, item });
972
+ });
973
+ });
974
+ });
975
+ return extractComparableEvidenceFactsFromBlockEntries(Array.from(selectedBlocks.values()), citationIdsByBlock, execution);
976
+ }
977
+ function collectFullDocumentComparableFacts(group, source, blocks, execution) {
978
+ const fallbackItem = selectRepresentativeGroupItem(group);
979
+ if (!fallbackItem) {
980
+ return [];
981
+ }
982
+ const citationIdsByBlock = buildBlockCitationMap(group, blocks, source);
983
+ const evidenceItemByBlock = buildEvidenceItemMap(group, blocks, source);
984
+ return extractComparableEvidenceFactsFromBlockEntries(blocks.map((block) => ({
985
+ block,
986
+ item: evidenceItemByBlock.get(sourceBlockKey(block)) || fallbackItem,
987
+ })), citationIdsByBlock, execution);
988
+ }
989
+ function comparableFactDocumentKey(fact) {
990
+ return `${fact.item.atom.documentId}\n${fact.item.atom.sourcePath}`;
991
+ }
992
+ function comparableEvidenceFactsConflict(left, right) {
993
+ if (left.subjectKey !== right.subjectKey || left.factKind !== right.factKind)
994
+ return false;
995
+ if (left.factKind === 'measurement' && right.factKind === 'measurement') {
996
+ if (left.measurement.dimension !== right.measurement.dimension)
997
+ return false;
998
+ const sameMagnitude = left.measurement.magnitude === right.measurement.magnitude;
999
+ if (left.measurement.relation !== right.measurement.relation)
1000
+ return sameMagnitude;
1001
+ return left.measurement.relation === 'equal' && !sameMagnitude;
1002
+ }
1003
+ return left.valueKey !== right.valueKey;
1004
+ }
1005
+ function buildConflictFragments(group, facts, paragraphWindow, execution) {
1006
+ const fragments = [];
1007
+ const seenConflicts = new Set();
1008
+ facts.forEach((left, leftIndex) => {
1009
+ facts.slice(leftIndex + 1).forEach((right) => {
1010
+ if (!comparableEvidenceFactsConflict(left, right)) {
1011
+ return;
1012
+ }
1013
+ const blockDistance = Math.abs(left.block.startLine - right.block.startLine);
1014
+ const sameScopedSection = left.block.headingPath.length > 0
1015
+ && sameHeadingPath(left.block.headingPath, right.block.headingPath);
1016
+ if (!sameScopedSection && blockDistance > Math.max(2, paragraphWindow)) {
1017
+ return;
1018
+ }
1019
+ const orderedValues = [left.valueKey, right.valueKey].sort();
1020
+ const conflictKey = `${left.subjectKey}:${left.factKind}:${orderedValues[0]}:${orderedValues[1]}`;
1021
+ if (seenConflicts.has(conflictKey)) {
1022
+ return;
1023
+ }
1024
+ seenConflicts.add(conflictKey);
1025
+ const firstBlock = left.block.startOffset <= right.block.startOffset ? left.block : right.block;
1026
+ const lastBlock = left.block.endOffset >= right.block.endOffset ? left.block : right.block;
1027
+ const citationIds = Array.from(new Set([
1028
+ ...left.citationIds,
1029
+ ...right.citationIds,
1030
+ ...itemEvidenceSpans(left.item).map((span) => span.id),
1031
+ ...itemEvidenceSpans(right.item).map((span) => span.id),
1032
+ ].filter(Boolean)));
1033
+ const conflictBlockTexts = Array.from(new Map([left.block, right.block].map((block) => [sourceBlockKey(block), block.text])).values());
1034
+ const text = [
1035
+ `Conflicting evidence for ${left.subjectLabel}:`,
1036
+ ...conflictBlockTexts,
1037
+ ].join('\n');
1038
+ fragments.push(finishEvidenceFragment({
1039
+ fragmentId: `rag_conflict_${sanitizeFragmentPart(group.documentId)}_${fragments.length + 1}`,
1040
+ role: 'conflict',
1041
+ text,
1042
+ atomId: left.item.atom.id,
1043
+ documentId: group.documentId,
1044
+ sourcePath: group.sourcePath,
1045
+ title: left.item.atom.title,
1046
+ headingPath: [...left.block.headingPath],
1047
+ startOffset: firstBlock.startOffset,
1048
+ endOffset: lastBlock.endOffset,
1049
+ startLine: firstBlock.startLine,
1050
+ endLine: lastBlock.endLine,
1051
+ charCount: text.length,
1052
+ tokenEstimate: (0, ragContextPack_1.estimateRagTokenCount)(text),
1053
+ truncated: false,
1054
+ citationIds,
1055
+ relationEdgeIds: Array.from(new Set([
1056
+ ...left.item.relationPath.map((edge) => edge.id),
1057
+ ...right.item.relationPath.map((edge) => edge.id),
1058
+ ])),
1059
+ score: Number(Math.max(Number(left.item.score || 0), Number(right.item.score || 0)).toFixed(4)),
1060
+ sourceBoundary: 'full_document',
1061
+ }, execution));
1062
+ });
1063
+ });
1064
+ return fragments;
1065
+ }
1066
+ function buildCrossDocumentConflictFragments(facts, execution) {
1067
+ const orderedFacts = facts.slice().sort((left, right) => {
1068
+ const sourceDelta = String(left.item.atom.sourcePath || '').localeCompare(String(right.item.atom.sourcePath || ''));
1069
+ if (sourceDelta !== 0) {
1070
+ return sourceDelta;
1071
+ }
1072
+ return left.block.startOffset - right.block.startOffset;
1073
+ });
1074
+ const fragments = [];
1075
+ const seenConflicts = new Set();
1076
+ orderedFacts.forEach((left, leftIndex) => {
1077
+ execution?.assertActive();
1078
+ orderedFacts.slice(leftIndex + 1).forEach((right) => {
1079
+ if (comparableFactDocumentKey(left) === comparableFactDocumentKey(right)) {
1080
+ return;
1081
+ }
1082
+ if (!comparableEvidenceFactsConflict(left, right)) {
1083
+ return;
1084
+ }
1085
+ const orderedSourceKeys = [comparableFactDocumentKey(left), comparableFactDocumentKey(right)].sort();
1086
+ const orderedValues = [left.valueKey, right.valueKey].sort();
1087
+ const conflictKey = `${left.subjectKey}:${left.factKind}:${orderedSourceKeys[0]}:${orderedSourceKeys[1]}:${orderedValues[0]}:${orderedValues[1]}`;
1088
+ if (seenConflicts.has(conflictKey)) {
1089
+ return;
1090
+ }
1091
+ seenConflicts.add(conflictKey);
1092
+ const citationIds = Array.from(new Set([
1093
+ ...left.citationIds,
1094
+ ...right.citationIds,
1095
+ ...itemEvidenceSpans(left.item).map((span) => span.id),
1096
+ ...itemEvidenceSpans(right.item).map((span) => span.id),
1097
+ ].filter(Boolean)));
1098
+ const text = [
1099
+ `Conflicting evidence for ${left.subjectLabel} across documents:`,
1100
+ `${left.item.atom.title}: ${left.block.text}`,
1101
+ `${right.item.atom.title}: ${right.block.text}`,
1102
+ ].join('\n');
1103
+ fragments.push(finishEvidenceFragment({
1104
+ fragmentId: `rag_conflict_cross_document_${sanitizeFragmentPart(left.item.atom.documentId)}_${sanitizeFragmentPart(right.item.atom.documentId)}_${fragments.length + 1}`,
1105
+ role: 'conflict',
1106
+ text,
1107
+ atomId: left.item.atom.id,
1108
+ documentId: `cross_document_conflict_${sanitizeFragmentPart(left.item.atom.documentId)}_${sanitizeFragmentPart(right.item.atom.documentId)}`,
1109
+ sourcePath: `${left.item.atom.sourcePath} | ${right.item.atom.sourcePath}`,
1110
+ title: `${left.item.atom.title} / ${right.item.atom.title}`,
1111
+ headingPath: [],
1112
+ charCount: text.length,
1113
+ tokenEstimate: (0, ragContextPack_1.estimateRagTokenCount)(text),
1114
+ truncated: false,
1115
+ citationIds,
1116
+ relationEdgeIds: Array.from(new Set([
1117
+ ...left.item.relationPath.map((edge) => edge.id),
1118
+ ...right.item.relationPath.map((edge) => edge.id),
1119
+ ])),
1120
+ score: Number(Math.max(Number(left.item.score || 0), Number(right.item.score || 0)).toFixed(4)),
1121
+ sourceBoundary: 'full_document',
1122
+ }, execution));
1123
+ });
1124
+ });
1125
+ return fragments;
1126
+ }
1127
+ function limitGraphNeighborDocumentContextFragments(fragments) {
1128
+ const graphNeighborContextFragments = fragments
1129
+ .map((fragment, index) => ({ fragment, index }))
1130
+ .filter((entry) => (entry.fragment.role === 'graph_neighbor_support'
1131
+ && entry.fragment.sourceBoundary === 'full_document'))
1132
+ .sort((left, right) => {
1133
+ const scoreDelta = Number(right.fragment.score || 0) - Number(left.fragment.score || 0);
1134
+ if (Math.abs(scoreDelta) > 0.0001) {
1135
+ return scoreDelta;
1136
+ }
1137
+ return left.index - right.index;
1138
+ });
1139
+ const selectedContextFragmentIds = new Set(graphNeighborContextFragments
1140
+ .slice(0, MAX_GRAPH_NEIGHBOR_DOCUMENT_CONTEXT_FRAGMENTS)
1141
+ .map((entry) => entry.fragment.fragmentId));
1142
+ return fragments.filter((fragment) => (fragment.role !== 'graph_neighbor_support'
1143
+ || fragment.sourceBoundary !== 'full_document'
1144
+ || selectedContextFragmentIds.has(fragment.fragmentId)));
1145
+ }
1146
+ function buildDirectFragment(item, span, index, role = 'direct_support', execution) {
1147
+ const text = normalizeWhitespace(String(span.snippet || item.atom.content || item.atom.title || ''));
1148
+ return finishEvidenceFragment({
1149
+ fragmentId: `${role === 'graph_neighbor_support' ? 'rag_graph_neighbor' : 'rag_direct'}_${sanitizeFragmentPart(item.atom.documentId)}_${sanitizeFragmentPart(span.id || String(index + 1))}`,
1150
+ role,
1151
+ text,
1152
+ atomId: item.atom.id,
1153
+ documentId: item.atom.documentId,
1154
+ sourcePath: item.atom.sourcePath,
1155
+ title: item.atom.title,
1156
+ headingPath: Array.isArray(item.atom.metadata?.sectionPath) ? [...item.atom.metadata.sectionPath] : [],
1157
+ startOffset: Number.isFinite(span.startOffset) ? span.startOffset : undefined,
1158
+ endOffset: Number.isFinite(span.endOffset) ? span.endOffset : undefined,
1159
+ startLine: Number.isFinite(span.startLine) ? span.startLine : undefined,
1160
+ endLine: Number.isFinite(span.endLine) ? span.endLine : undefined,
1161
+ charCount: text.length,
1162
+ tokenEstimate: (0, ragContextPack_1.estimateRagTokenCount)(text),
1163
+ truncated: false,
1164
+ citationIds: [span.id],
1165
+ relationEdgeIds: item.relationPath.map((edge) => edge.id),
1166
+ score: Number(Number(item.score || 0).toFixed(4)),
1167
+ sourceBoundary: 'direct_span_only',
1168
+ }, execution);
1169
+ }
1170
+ function groupItemsByDocument(items, graphNeighborItems = []) {
1171
+ const groups = new Map();
1172
+ const appendItem = (item, index, directRole, expandDocumentContext) => {
1173
+ const documentId = String(item.atom.documentId || `document_${index + 1}`).trim();
1174
+ const sourcePath = String(item.atom.sourcePath || '').trim();
1175
+ const key = `${documentId}\n${sourcePath}`;
1176
+ let group = groups.get(key);
1177
+ if (!group) {
1178
+ group = {
1179
+ documentId,
1180
+ sourcePath,
1181
+ entries: [],
1182
+ };
1183
+ groups.set(key, group);
1184
+ }
1185
+ group.entries.push({
1186
+ item,
1187
+ directRole,
1188
+ expandDocumentContext,
1189
+ });
1190
+ };
1191
+ items.forEach((item, index) => appendItem(item, index, 'direct_support', true));
1192
+ graphNeighborItems.forEach((item, index) => appendItem(item, index, 'graph_neighbor_support', true));
1193
+ return Array.from(groups.values());
1194
+ }
1195
+ function itemEvidenceSpans(item) {
1196
+ return Array.isArray(item.evidenceSpans) ? item.evidenceSpans.filter(Boolean) : [];
1197
+ }
1198
+ async function resolveDocumentSource(group, sourceResolver) {
1199
+ if (!sourceResolver) {
1200
+ return null;
1201
+ }
1202
+ const atomIds = Array.from(new Set(group.entries.map((entry) => entry.item.atom.id).filter(Boolean)));
1203
+ const citationIds = Array.from(new Set(group.entries.flatMap((entry) => itemEvidenceSpans(entry.item).map((span) => span.id)).filter(Boolean)));
1204
+ const source = await sourceResolver({
1205
+ documentId: group.documentId,
1206
+ sourcePath: group.sourcePath,
1207
+ atomIds,
1208
+ citationIds,
1209
+ });
1210
+ if (!source || (!source.unavailableReason && !String(source.content || '').trim())) {
1211
+ return null;
1212
+ }
1213
+ return {
1214
+ ...source,
1215
+ documentId: String(source.documentId || group.documentId),
1216
+ sourcePath: String(source.sourcePath || group.sourcePath),
1217
+ content: String(source.content || ''),
1218
+ };
1219
+ }
1220
+ function buildParentFragments(group, source, paragraphWindow, blocks, execution) {
1221
+ const parentDrafts = new Map();
1222
+ group.entries
1223
+ .filter((entry) => entry.expandDocumentContext)
1224
+ .forEach(({ item, directRole }) => {
1225
+ const fragmentRole = directRole === 'graph_neighbor_support' ? 'graph_neighbor_support' : 'parent_context';
1226
+ itemEvidenceSpans(item).forEach((span) => {
1227
+ const evidenceBlocks = blocksForEvidence(blocks, span, source.content);
1228
+ if (evidenceBlocks.length <= 0) {
1229
+ return;
1230
+ }
1231
+ const sectionBlocks = buildSectionBlocks(blocks, evidenceBlocks, paragraphWindow);
1232
+ if (sectionBlocks.length <= 0) {
1233
+ return;
1234
+ }
1235
+ const headingPath = evidenceBlocks[0].headingPath.length > 0
1236
+ ? evidenceBlocks[0].headingPath
1237
+ : (Array.isArray(item.atom.metadata?.sectionPath) ? item.atom.metadata.sectionPath : []);
1238
+ const parentKey = `${fragmentRole}\n${group.documentId}\n${group.sourcePath}\n${headingPath.join('/') || 'local_window'}`;
1239
+ let draft = parentDrafts.get(parentKey);
1240
+ if (!draft) {
1241
+ draft = {
1242
+ key: parentKey,
1243
+ role: fragmentRole,
1244
+ item,
1245
+ documentId: group.documentId,
1246
+ sourcePath: group.sourcePath,
1247
+ headingPath: [...headingPath],
1248
+ blocks: [],
1249
+ citationIds: new Set(),
1250
+ relationEdgeIds: new Set(),
1251
+ score: 0,
1252
+ };
1253
+ parentDrafts.set(parentKey, draft);
1254
+ }
1255
+ draft.blocks.push(...sectionBlocks);
1256
+ draft.citationIds.add(span.id);
1257
+ item.relationPath.forEach((edge) => draft?.relationEdgeIds.add(edge.id));
1258
+ draft.score = Math.max(draft.score, Number(item.score || 0));
1259
+ });
1260
+ });
1261
+ return Array.from(parentDrafts.values()).map((draft, index) => {
1262
+ const blocksForFragment = mergeBlocks(draft.blocks);
1263
+ const text = fragmentTextFromBlocks(blocksForFragment);
1264
+ const first = blocksForFragment[0];
1265
+ const last = blocksForFragment[blocksForFragment.length - 1];
1266
+ const fragmentPrefix = draft.role === 'graph_neighbor_support'
1267
+ ? 'rag_graph_neighbor_context'
1268
+ : 'rag_parent';
1269
+ return finishEvidenceFragment({
1270
+ fragmentId: `${fragmentPrefix}_${sanitizeFragmentPart(draft.documentId)}_${index + 1}`,
1271
+ role: draft.role,
1272
+ text,
1273
+ atomId: draft.item.atom.id,
1274
+ documentId: draft.documentId,
1275
+ sourcePath: draft.sourcePath,
1276
+ title: draft.item.atom.title,
1277
+ headingPath: [...draft.headingPath],
1278
+ startOffset: first?.startOffset,
1279
+ endOffset: last?.endOffset,
1280
+ startLine: first?.startLine,
1281
+ endLine: last?.endLine,
1282
+ charCount: text.length,
1283
+ tokenEstimate: (0, ragContextPack_1.estimateRagTokenCount)(text),
1284
+ truncated: false,
1285
+ citationIds: Array.from(draft.citationIds),
1286
+ relationEdgeIds: Array.from(draft.relationEdgeIds),
1287
+ score: Number(Number(draft.score || 0).toFixed(4)),
1288
+ sourceBoundary: 'full_document',
1289
+ }, execution);
1290
+ }).filter((fragment) => fragment.text.length > 0);
1291
+ }
1292
+ async function assembleRagEvidenceContext(params) {
1293
+ const paragraphWindow = Math.floor(Math.max(0, Math.min(20, Number(params.paragraphWindow ?? DEFAULT_PARAGRAPH_WINDOW))));
1294
+ const decisions = [];
1295
+ const rawFragments = [];
1296
+ const fullDocumentComparableFacts = [];
1297
+ const execution = params.execution;
1298
+ let readFullDocument = false;
1299
+ const groups = groupItemsByDocument(Array.isArray(params.items) ? params.items : [], Array.isArray(params.graphNeighborItems) ? params.graphNeighborItems : []);
1300
+ for (const group of groups) {
1301
+ await execution?.yieldCheckpoint();
1302
+ try {
1303
+ group.entries.forEach(entry => {
1304
+ itemEvidenceSpans(entry.item).forEach((span, spanIndex) => {
1305
+ rawFragments.push(buildDirectFragment(entry.item, span, rawFragments.length + spanIndex, entry.directRole, execution));
1306
+ });
1307
+ });
1308
+ const source = await resolveDocumentSource(group, params.sourceResolver);
1309
+ execution?.assertActive();
1310
+ if (!source || source.unavailableReason) {
1311
+ const unavailableRoles = Array.from(new Set(group.entries.map(entry => entry.directRole))).join(',');
1312
+ decisions.push({
1313
+ documentId: group.documentId, sourcePath: group.sourcePath,
1314
+ sourceBoundary: 'direct_span_only', status: 'source_window_unavailable',
1315
+ reason: source?.unavailableReason || `source_resolver_returned_no_content:${unavailableRoles}`,
1316
+ });
1317
+ continue;
1318
+ }
1319
+ readFullDocument = true;
1320
+ const blocks = parseMarkdownBlocks(source.content, execution);
1321
+ rawFragments.push(...buildParentFragments(group, source, paragraphWindow, blocks, execution));
1322
+ const selectedFacts = collectSelectedContextComparableFacts(group, source, paragraphWindow, blocks, execution);
1323
+ fullDocumentComparableFacts.push(...collectFullDocumentComparableFacts(group, source, blocks, execution));
1324
+ rawFragments.push(...buildConflictFragments(group, selectedFacts, paragraphWindow, execution));
1325
+ decisions.push({
1326
+ documentId: group.documentId, sourcePath: group.sourcePath,
1327
+ sourceBoundary: 'full_document', status: 'read', charsRead: source.content.length,
1328
+ });
1329
+ }
1330
+ catch (error) {
1331
+ if (!execution || !execution.isResourceLimit(error))
1332
+ throw error;
1333
+ decisions.push({
1334
+ documentId: group.documentId, sourcePath: group.sourcePath,
1335
+ sourceBoundary: 'direct_span_only', status: 'source_window_unavailable', reason: error.code,
1336
+ });
1337
+ if (error.code === 'runtime_fragment_limit')
1338
+ break;
1339
+ }
1340
+ }
1341
+ try {
1342
+ rawFragments.push(...buildCrossDocumentConflictFragments(fullDocumentComparableFacts, execution));
1343
+ }
1344
+ catch (error) {
1345
+ if (!execution || !execution.isResourceLimit(error))
1346
+ throw error;
1347
+ decisions.push({
1348
+ documentId: 'cross_document_conflicts', sourcePath: '',
1349
+ sourceBoundary: 'direct_span_only', status: 'source_window_unavailable', reason: error.code,
1350
+ });
1351
+ }
1352
+ execution?.assertActive();
1353
+ const candidateFragments = limitGraphNeighborDocumentContextFragments(rawFragments);
1354
+ const graphConditioning = (0, graphConditionedContext_1.conditionRagFragmentsByGraphPlan)({
1355
+ fragments: candidateFragments,
1356
+ graphAnswerPlan: params.graphAnswerPlan,
1357
+ });
1358
+ return (0, ragContextPack_1.buildRagContextPack)({
1359
+ query: params.query,
1360
+ generatedAt: params.generatedAt,
1361
+ sourceBoundary: readFullDocument ? 'full_document' : 'direct_span_only',
1362
+ fragments: candidateFragments,
1363
+ sourceDecisions: decisions,
1364
+ budget: params.budget,
1365
+ fragmentOrder: graphConditioning.fragmentOrder,
1366
+ graphConditioning: graphConditioning.trace,
1367
+ });
1368
+ }