noteconnection 1.8.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.
- package/README.md +257 -1803
- package/dist/src/agent_workspace.contract.parity.test.js +105 -421
- package/dist/src/agent_workspace.frontend.test.js +410 -11
- package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
- package/dist/src/appimage.patchelf.test.js +113 -0
- package/dist/src/appimage.portability.test.js +156 -0
- package/dist/src/backend/FileLoader.js +18 -4
- package/dist/src/backend/FileLoader.test.js +125 -0
- package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
- package/dist/src/backend/GraphBuilder.js +66 -18
- package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
- package/dist/src/backend/GraphMetrics.js +0 -3
- package/dist/src/backend/ResourceIdentity.js +155 -0
- package/dist/src/backend/ResourceIdentity.test.js +113 -0
- package/dist/src/backend/algorithms/CycleDetection.js +0 -1
- package/dist/src/backend/algorithms/HybridEngine.js +0 -3
- package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
- package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
- package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
- package/dist/src/backend/build_dag.js +0 -1
- package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
- package/dist/src/capacitor.runtime.contract.test.js +11 -2
- package/dist/src/core/Graph.js +138 -42
- package/dist/src/core/Graph.test.js +74 -0
- package/dist/src/core/NoteConnection.js +2 -2
- package/dist/src/core/PathBridge.js +265 -2
- package/dist/src/core/ResourceReference.js +17 -0
- package/dist/src/desktop.godot.pack.test.js +142 -0
- package/dist/src/desktop.runtime.graph.test.js +66 -0
- package/dist/src/export/WorkspaceExportBundle.js +44 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
- package/dist/src/foundation.release.evidence.contract.test.js +127 -9
- package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
- package/dist/src/frontend/README.md +257 -1803
- package/dist/src/frontend/agent_workspace.js +665 -7
- package/dist/src/frontend/index.html +31 -2
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +32 -0
- package/dist/src/frontend/locales/zh.json +32 -0
- package/dist/src/frontend/mobile_budget_runtime.js +33 -0
- package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
- package/dist/src/frontend/mobile_identity_contract.js +221 -0
- package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
- package/dist/src/frontend/path.html +6 -2
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +110 -4
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +107 -13
- package/dist/src/frontend/workspace_panes.js +111 -7
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/graph.answer.operator.contract.test.js +72 -0
- package/dist/src/index.js +6 -2
- package/dist/src/index.knowledge-root.test.js +118 -0
- package/dist/src/indexing/IndexLifecycle.js +22 -0
- package/dist/src/indexing/IndexLifecycle.test.js +24 -0
- package/dist/src/knowledge.api.contract.test.js +4 -2
- package/dist/src/knowledge_projection.contract.test.js +134 -0
- package/dist/src/knowledge_projection_store.test.js +200 -0
- package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
- package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
- package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
- package/dist/src/learning/PublicAnswerContract.test.js +85 -0
- package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
- package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
- package/dist/src/learning/agentConversationExecution.js +211 -0
- package/dist/src/learning/agentConversationExecution.test.js +209 -0
- package/dist/src/learning/agentConversationSerialization.js +266 -0
- package/dist/src/learning/agentConversationSerialization.test.js +165 -0
- package/dist/src/learning/agentResponseBudget.js +179 -0
- package/dist/src/learning/agentResponseBudget.test.js +97 -0
- package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
- package/dist/src/learning/answerReleaseReview.js +1191 -250
- package/dist/src/learning/answerReleaseReview.test.js +1293 -7
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/conversationComposer.js +627 -386
- package/dist/src/learning/conversationComposer.test.js +1403 -0
- package/dist/src/learning/evidenceContextAssembler.js +312 -120
- package/dist/src/learning/graphAnswerCoverage.js +37 -0
- package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
- package/dist/src/learning/graphAnswerFacts.js +94 -0
- package/dist/src/learning/graphAnswerFacts.test.js +39 -0
- package/dist/src/learning/graphAnswerPlan.js +908 -0
- package/dist/src/learning/graphAnswerPlan.test.js +907 -0
- package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
- package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
- package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
- package/dist/src/learning/graphClaimMatcher.js +104 -0
- package/dist/src/learning/graphConditionedContext.js +109 -0
- package/dist/src/learning/graphConditionedContext.test.js +99 -0
- package/dist/src/learning/graphContextAssembler.js +3 -13
- package/dist/src/learning/graphContextAssembler.test.js +2 -2
- package/dist/src/learning/graphExpansionPolicy.js +22 -0
- package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
- package/dist/src/learning/identityMetadata.test.js +26 -0
- package/dist/src/learning/index.js +1 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +34 -10
- package/dist/src/learning/queryBackend.test.js +21 -0
- package/dist/src/learning/ragContextPack.js +115 -16
- package/dist/src/learning/ragContextPack.test.js +151 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +67 -4
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +11 -1
- package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
- package/dist/src/learning/requestNormalization.js +106 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/store.js +116 -12
- package/dist/src/learning/store.test.js +299 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
- package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/license.policy.contract.test.js +9 -4
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +28 -7
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/index.js +2 -1
- package/dist/src/mobile.android.evidence.contract.test.js +146 -0
- package/dist/src/mobile.android.signing.contract.test.js +66 -0
- package/dist/src/mobile.artifact.contract.test.js +144 -0
- package/dist/src/mobile.budget.contract.test.js +90 -0
- package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
- package/dist/src/mobile.graph.parity.contract.test.js +207 -0
- package/dist/src/mobile.identity.contract.test.js +66 -0
- package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
- package/dist/src/mobile.identity.corpus.test.js +40 -0
- package/dist/src/mobile.native.recovery.contract.test.js +64 -0
- package/dist/src/mobile.pipeline.test.js +11 -1
- package/dist/src/mobile.profile.contract.test.js +225 -0
- package/dist/src/mobile.semantic.parity.test.js +92 -0
- package/dist/src/mobile_exact_analyzer.test.js +113 -0
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/NotemdService.js +12 -17
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd.server.integration.test.js +119 -4
- package/dist/src/notemd.workflow.pipeline.test.js +1 -1
- package/dist/src/pathbridge.handshake.contract.test.js +29 -0
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/platform/ExportProfile.js +28 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +14 -0
- package/dist/src/platform/PlatformCapabilities.test.js +6 -0
- package/dist/src/query_backend.external_http.integration.test.js +2 -2
- package/dist/src/release.godot.mirror.contract.test.js +28 -4
- package/dist/src/resources/ResourceRegistry.js +40 -0
- package/dist/src/resources/ResourceRegistry.test.js +36 -0
- package/dist/src/routes/index.js +0 -4
- package/dist/src/routes/knowledge.js +46 -33
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +8 -0
- package/dist/src/routes/notemd.js +990 -234
- package/dist/src/routes/registry.contract.test.js +5 -2
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +14 -51
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/server.js +566 -1090
- package/dist/src/server.migration.test.js +417 -15
- package/dist/src/sidecar.build.lock.contract.test.js +201 -0
- package/dist/src/sidecar.freshness.contract.test.js +184 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
- package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
- package/dist/src/storage.provider.contract.test.js +152 -1
- package/dist/src/tauri.frontend.build.contract.test.js +8 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +6 -0
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/windows.installer.build.test.js +109 -0
- package/dist/src/windows.installer.payload.test.js +76 -0
- package/dist/src/windows.installer.runtime.test.js +69 -0
- package/dist/src/workspace/WorkspaceRegistry.js +13 -0
- package/package.json +32 -10
- package/dist/src/routes/data.js +0 -267
- package/dist/src/routes/diagnostics.js +0 -51
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assembleRagEvidenceContext = assembleRagEvidenceContext;
|
|
4
4
|
const ragContextPack_1 = require("./ragContextPack");
|
|
5
|
+
const graphConditionedContext_1 = require("./graphConditionedContext");
|
|
6
|
+
const ragEvidenceQuality_1 = require("./ragEvidenceQuality");
|
|
5
7
|
const DEFAULT_PARAGRAPH_WINDOW = 5;
|
|
6
8
|
const MAX_GRAPH_NEIGHBOR_DOCUMENT_CONTEXT_FRAGMENTS = 2;
|
|
7
|
-
const COMPARABLE_NUMERIC_FACT_PATTERN = /\b(?:the\s+)?([a-z][a-z0-9 -]{2,80}?)\s+(?:is|=|:)\s*(?:±|\+\/-|\+\s*\/\s*-)?\s*(-?\d+(?:\.\d+)?)\s*(mm|cm|m|um|µm|nm|kg|g|mg|s|ms|%|deg|degree|degrees|c|k)\b/gi;
|
|
8
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;
|
|
9
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;
|
|
10
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;
|
|
@@ -84,50 +85,110 @@ const COMPARABLE_PLATFORM_SCOPE_ALIASES = {
|
|
|
84
85
|
mobile: 'mobile',
|
|
85
86
|
};
|
|
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
|
+
}
|
|
87
142
|
function normalizeWhitespace(value) {
|
|
88
143
|
return String(value || '').replace(/\s+/g, ' ').trim();
|
|
89
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
|
+
}
|
|
90
157
|
function sanitizeFragmentPart(value) {
|
|
91
158
|
return normalizeWhitespace(value)
|
|
92
159
|
.replace(/[^a-zA-Z0-9_-]+/g, '_')
|
|
93
160
|
.replace(/^_+|_+$/g, '')
|
|
94
161
|
.slice(0, 80) || 'fragment';
|
|
95
162
|
}
|
|
96
|
-
function splitSourceLines(content) {
|
|
163
|
+
function splitSourceLines(content, execution) {
|
|
97
164
|
const normalizedContent = String(content || '');
|
|
98
165
|
if (!normalizedContent) {
|
|
99
166
|
return [];
|
|
100
167
|
}
|
|
101
|
-
const lines = normalizedContent.split(/\r\n|\n|\r/);
|
|
102
168
|
const records = [];
|
|
169
|
+
const newline = /\r\n|\n|\r/g;
|
|
103
170
|
let cursor = 0;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
171
|
+
let delimiter;
|
|
172
|
+
while ((delimiter = newline.exec(normalizedContent)) !== null) {
|
|
173
|
+
execution?.checkSourceLineCount(records.length + 1);
|
|
107
174
|
records.push({
|
|
108
|
-
lineNumber:
|
|
109
|
-
text:
|
|
110
|
-
startOffset,
|
|
111
|
-
endOffset,
|
|
175
|
+
lineNumber: records.length + 1,
|
|
176
|
+
text: normalizedContent.slice(cursor, delimiter.index),
|
|
177
|
+
startOffset: cursor,
|
|
178
|
+
endOffset: delimiter.index,
|
|
112
179
|
});
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
cursor = endOffset + 1;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
cursor = endOffset;
|
|
121
|
-
}
|
|
122
|
-
});
|
|
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 });
|
|
123
184
|
return records;
|
|
124
185
|
}
|
|
125
186
|
function isTableLine(text) {
|
|
126
187
|
const trimmed = String(text || '').trim();
|
|
127
188
|
return trimmed.startsWith('|') && trimmed.endsWith('|');
|
|
128
189
|
}
|
|
129
|
-
function parseMarkdownBlocks(content) {
|
|
130
|
-
const sourceLines = splitSourceLines(content);
|
|
190
|
+
function parseMarkdownBlocks(content, execution) {
|
|
191
|
+
const sourceLines = splitSourceLines(content, execution);
|
|
131
192
|
const blocks = [];
|
|
132
193
|
const headingStack = [];
|
|
133
194
|
let pendingLines = [];
|
|
@@ -158,6 +219,7 @@ function parseMarkdownBlocks(content) {
|
|
|
158
219
|
pendingHeadingPath = currentHeadingPath();
|
|
159
220
|
};
|
|
160
221
|
sourceLines.forEach((line) => {
|
|
222
|
+
execution?.assertActive();
|
|
161
223
|
const rawText = String(line.text || '');
|
|
162
224
|
const trimmed = rawText.trim();
|
|
163
225
|
const fenceLine = /^```/.test(trimmed);
|
|
@@ -306,7 +368,7 @@ function normalizeComparableFactSubject(value) {
|
|
|
306
368
|
return normalizeWhitespace(value)
|
|
307
369
|
.toLowerCase()
|
|
308
370
|
.replace(/^(the|a|an)\s+/i, '')
|
|
309
|
-
.replace(/[
|
|
371
|
+
.replace(/[^\p{L}\p{N}]+/gu, ' ')
|
|
310
372
|
.trim();
|
|
311
373
|
}
|
|
312
374
|
function comparableFactSentenceTail(blockText, match) {
|
|
@@ -315,7 +377,8 @@ function comparableFactSentenceTail(blockText, match) {
|
|
|
315
377
|
return '';
|
|
316
378
|
}
|
|
317
379
|
const tail = String(blockText || '').slice(matchIndex + String(match[0] || '').length);
|
|
318
|
-
|
|
380
|
+
const boundary = /[!?。!?;;\r\n]|\.(?!\d)/u.exec(tail);
|
|
381
|
+
return normalizeWhitespace(boundary ? tail.slice(0, boundary.index) : tail);
|
|
319
382
|
}
|
|
320
383
|
function comparableFactTemporalScopeKey(subjectLabel, sentenceTail) {
|
|
321
384
|
const scopedText = `${normalizeWhitespace(subjectLabel)} ${normalizeWhitespace(sentenceTail)}`;
|
|
@@ -356,6 +419,8 @@ function comparableFactPlatformScopeKey(subjectLabel, sentenceTail) {
|
|
|
356
419
|
return COMPARABLE_PLATFORM_SCOPE_ALIASES[platformLabel] || null;
|
|
357
420
|
}
|
|
358
421
|
function comparableFactScopeKeys(subjectLabel, sentenceTail) {
|
|
422
|
+
subjectLabel = normalizeScopeLanguage(subjectLabel);
|
|
423
|
+
sentenceTail = normalizeScopeLanguage(sentenceTail);
|
|
359
424
|
const scopeKeys = [];
|
|
360
425
|
const temporalScopeKey = comparableFactTemporalScopeKey(subjectLabel, sentenceTail);
|
|
361
426
|
if (temporalScopeKey) {
|
|
@@ -373,26 +438,89 @@ function comparableFactScopeKeys(subjectLabel, sentenceTail) {
|
|
|
373
438
|
if (platformScopeKey) {
|
|
374
439
|
scopeKeys.push(`platform:${platformScopeKey}`);
|
|
375
440
|
}
|
|
441
|
+
const timeScope = COMPARABLE_TIME_SCOPE_PATTERN.exec(`${subjectLabel} ${sentenceTail}`)?.[1];
|
|
442
|
+
if (timeScope)
|
|
443
|
+
scopeKeys.push(`time:${timeScope}`);
|
|
376
444
|
return scopeKeys.sort();
|
|
377
445
|
}
|
|
378
446
|
function comparableFactSubjectKey(subjectLabel, scopeKeys) {
|
|
447
|
+
subjectLabel = normalizeScopeLanguage(subjectLabel);
|
|
379
448
|
const scopedSubjectLabel = scopeKeys.some((scopeKey) => scopeKey.startsWith('temporal:'))
|
|
380
449
|
? normalizeWhitespace(subjectLabel).replace(COMPARABLE_TEMPORAL_SCOPE_PATTERN, '')
|
|
381
450
|
: subjectLabel;
|
|
382
|
-
const subjectKey = normalizeComparableFactSubject(scopedSubjectLabel
|
|
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, ''));
|
|
383
456
|
return scopeKeys.length > 0 && subjectKey
|
|
384
457
|
? `${subjectKey}@scope:${scopeKeys.join('+')}`
|
|
385
458
|
: subjectKey;
|
|
386
459
|
}
|
|
387
|
-
function
|
|
388
|
-
const normalized =
|
|
389
|
-
|
|
390
|
-
|
|
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
|
+
}
|
|
391
468
|
}
|
|
392
|
-
|
|
393
|
-
|
|
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
|
+
}
|
|
394
483
|
}
|
|
395
|
-
|
|
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;
|
|
396
524
|
}
|
|
397
525
|
function normalizeComparableDateValue(value) {
|
|
398
526
|
const normalized = normalizeWhitespace(value);
|
|
@@ -499,27 +627,61 @@ function extractComparableEvidenceFacts(params) {
|
|
|
499
627
|
return [];
|
|
500
628
|
}
|
|
501
629
|
const facts = [];
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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))
|
|
509
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
|
+
}
|
|
510
680
|
}
|
|
511
|
-
facts.push({
|
|
512
|
-
subjectKey,
|
|
513
|
-
subjectLabel,
|
|
514
|
-
valueKey: `${Number(value.toFixed(12))}:${unit}`,
|
|
515
|
-
valueLabel: `${match[2]} ${match[3]}`,
|
|
516
|
-
factKind: 'measurement',
|
|
517
|
-
block: params.block,
|
|
518
|
-
citationIds: params.citationIds,
|
|
519
|
-
item: params.item,
|
|
520
|
-
});
|
|
521
681
|
}
|
|
522
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;
|
|
523
685
|
const subjectLabel = normalizeWhitespace(match[1]);
|
|
524
686
|
const scopeKeys = comparableFactScopeKeys(subjectLabel, comparableFactSentenceTail(params.block.text, match));
|
|
525
687
|
const subjectKey = comparableFactSubjectKey(subjectLabel, scopeKeys);
|
|
@@ -527,7 +689,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
527
689
|
if (!subjectKey || !Number.isFinite(value)) {
|
|
528
690
|
continue;
|
|
529
691
|
}
|
|
530
|
-
|
|
692
|
+
appendFact({
|
|
531
693
|
subjectKey,
|
|
532
694
|
subjectLabel,
|
|
533
695
|
valueKey: `${Number(value.toFixed(12))}`,
|
|
@@ -546,7 +708,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
546
708
|
if (!subjectKey || !valueKey) {
|
|
547
709
|
continue;
|
|
548
710
|
}
|
|
549
|
-
|
|
711
|
+
appendFact({
|
|
550
712
|
subjectKey,
|
|
551
713
|
subjectLabel,
|
|
552
714
|
valueKey,
|
|
@@ -565,7 +727,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
565
727
|
if (!subjectKey || !stateValue) {
|
|
566
728
|
continue;
|
|
567
729
|
}
|
|
568
|
-
|
|
730
|
+
appendFact({
|
|
569
731
|
subjectKey: `${subjectKey}:${stateValue.groupKey}`,
|
|
570
732
|
subjectLabel,
|
|
571
733
|
valueKey: stateValue.valueKey,
|
|
@@ -584,7 +746,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
584
746
|
if (!subjectKey || !valueKey) {
|
|
585
747
|
continue;
|
|
586
748
|
}
|
|
587
|
-
|
|
749
|
+
appendFact({
|
|
588
750
|
subjectKey,
|
|
589
751
|
subjectLabel,
|
|
590
752
|
valueKey,
|
|
@@ -603,7 +765,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
603
765
|
if (!subjectKey || !valueKey) {
|
|
604
766
|
continue;
|
|
605
767
|
}
|
|
606
|
-
|
|
768
|
+
appendFact({
|
|
607
769
|
subjectKey,
|
|
608
770
|
subjectLabel,
|
|
609
771
|
valueKey,
|
|
@@ -622,7 +784,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
622
784
|
if (!subjectKey || !valueKey) {
|
|
623
785
|
continue;
|
|
624
786
|
}
|
|
625
|
-
|
|
787
|
+
appendFact({
|
|
626
788
|
subjectKey,
|
|
627
789
|
subjectLabel,
|
|
628
790
|
valueKey,
|
|
@@ -641,7 +803,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
641
803
|
if (!subjectKey || !valueKey) {
|
|
642
804
|
continue;
|
|
643
805
|
}
|
|
644
|
-
|
|
806
|
+
appendFact({
|
|
645
807
|
subjectKey,
|
|
646
808
|
subjectLabel,
|
|
647
809
|
valueKey,
|
|
@@ -660,7 +822,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
660
822
|
if (!subjectKey || !valueKey) {
|
|
661
823
|
continue;
|
|
662
824
|
}
|
|
663
|
-
|
|
825
|
+
appendFact({
|
|
664
826
|
subjectKey,
|
|
665
827
|
subjectLabel,
|
|
666
828
|
valueKey,
|
|
@@ -679,7 +841,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
679
841
|
if (!subjectKey || !valueKey) {
|
|
680
842
|
continue;
|
|
681
843
|
}
|
|
682
|
-
|
|
844
|
+
appendFact({
|
|
683
845
|
subjectKey,
|
|
684
846
|
subjectLabel,
|
|
685
847
|
valueKey,
|
|
@@ -698,7 +860,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
698
860
|
if (!subjectKey || !valueKey) {
|
|
699
861
|
continue;
|
|
700
862
|
}
|
|
701
|
-
|
|
863
|
+
appendFact({
|
|
702
864
|
subjectKey,
|
|
703
865
|
subjectLabel,
|
|
704
866
|
valueKey,
|
|
@@ -717,7 +879,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
717
879
|
if (!subjectKey || !valueKey) {
|
|
718
880
|
continue;
|
|
719
881
|
}
|
|
720
|
-
|
|
882
|
+
appendFact({
|
|
721
883
|
subjectKey,
|
|
722
884
|
subjectLabel,
|
|
723
885
|
valueKey,
|
|
@@ -736,7 +898,7 @@ function extractComparableEvidenceFacts(params) {
|
|
|
736
898
|
if (!subjectKey || !valueKey) {
|
|
737
899
|
continue;
|
|
738
900
|
}
|
|
739
|
-
|
|
901
|
+
appendFact({
|
|
740
902
|
subjectKey,
|
|
741
903
|
subjectLabel,
|
|
742
904
|
valueKey,
|
|
@@ -763,10 +925,11 @@ function buildBlockCitationMap(group, blocks, source) {
|
|
|
763
925
|
});
|
|
764
926
|
return citationIdsByBlock;
|
|
765
927
|
}
|
|
766
|
-
function extractComparableEvidenceFactsFromBlockEntries(entries, citationIdsByBlock) {
|
|
928
|
+
function extractComparableEvidenceFactsFromBlockEntries(entries, citationIdsByBlock, execution) {
|
|
767
929
|
return entries
|
|
768
930
|
.sort((left, right) => left.block.startOffset - right.block.startOffset)
|
|
769
931
|
.flatMap(({ block, item }) => extractComparableEvidenceFacts({
|
|
932
|
+
execution,
|
|
770
933
|
block,
|
|
771
934
|
item,
|
|
772
935
|
citationIds: Array.from(citationIdsByBlock.get(sourceBlockKey(block)) || []),
|
|
@@ -796,8 +959,7 @@ function buildEvidenceItemMap(group, blocks, source) {
|
|
|
796
959
|
});
|
|
797
960
|
return itemByBlock;
|
|
798
961
|
}
|
|
799
|
-
function collectSelectedContextComparableFacts(group, source, paragraphWindow) {
|
|
800
|
-
const blocks = parseMarkdownBlocks(source.content);
|
|
962
|
+
function collectSelectedContextComparableFacts(group, source, paragraphWindow, blocks, execution) {
|
|
801
963
|
const citationIdsByBlock = buildBlockCitationMap(group, blocks, source);
|
|
802
964
|
const selectedBlocks = new Map();
|
|
803
965
|
group.entries
|
|
@@ -810,33 +972,42 @@ function collectSelectedContextComparableFacts(group, source, paragraphWindow) {
|
|
|
810
972
|
});
|
|
811
973
|
});
|
|
812
974
|
});
|
|
813
|
-
return extractComparableEvidenceFactsFromBlockEntries(Array.from(selectedBlocks.values()), citationIdsByBlock);
|
|
975
|
+
return extractComparableEvidenceFactsFromBlockEntries(Array.from(selectedBlocks.values()), citationIdsByBlock, execution);
|
|
814
976
|
}
|
|
815
|
-
function collectFullDocumentComparableFacts(group, source) {
|
|
977
|
+
function collectFullDocumentComparableFacts(group, source, blocks, execution) {
|
|
816
978
|
const fallbackItem = selectRepresentativeGroupItem(group);
|
|
817
979
|
if (!fallbackItem) {
|
|
818
980
|
return [];
|
|
819
981
|
}
|
|
820
|
-
const blocks = parseMarkdownBlocks(source.content);
|
|
821
982
|
const citationIdsByBlock = buildBlockCitationMap(group, blocks, source);
|
|
822
983
|
const evidenceItemByBlock = buildEvidenceItemMap(group, blocks, source);
|
|
823
984
|
return extractComparableEvidenceFactsFromBlockEntries(blocks.map((block) => ({
|
|
824
985
|
block,
|
|
825
986
|
item: evidenceItemByBlock.get(sourceBlockKey(block)) || fallbackItem,
|
|
826
|
-
})), citationIdsByBlock);
|
|
987
|
+
})), citationIdsByBlock, execution);
|
|
827
988
|
}
|
|
828
989
|
function comparableFactDocumentKey(fact) {
|
|
829
990
|
return `${fact.item.atom.documentId}\n${fact.item.atom.sourcePath}`;
|
|
830
991
|
}
|
|
831
|
-
function
|
|
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) {
|
|
832
1006
|
const fragments = [];
|
|
833
1007
|
const seenConflicts = new Set();
|
|
834
1008
|
facts.forEach((left, leftIndex) => {
|
|
835
1009
|
facts.slice(leftIndex + 1).forEach((right) => {
|
|
836
|
-
if (left
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
if (left.valueKey === right.valueKey) {
|
|
1010
|
+
if (!comparableEvidenceFactsConflict(left, right)) {
|
|
840
1011
|
return;
|
|
841
1012
|
}
|
|
842
1013
|
const blockDistance = Math.abs(left.block.startLine - right.block.startLine);
|
|
@@ -864,7 +1035,7 @@ function buildConflictFragments(group, facts, paragraphWindow) {
|
|
|
864
1035
|
`Conflicting evidence for ${left.subjectLabel}:`,
|
|
865
1036
|
...conflictBlockTexts,
|
|
866
1037
|
].join('\n');
|
|
867
|
-
fragments.push({
|
|
1038
|
+
fragments.push(finishEvidenceFragment({
|
|
868
1039
|
fragmentId: `rag_conflict_${sanitizeFragmentPart(group.documentId)}_${fragments.length + 1}`,
|
|
869
1040
|
role: 'conflict',
|
|
870
1041
|
text,
|
|
@@ -887,12 +1058,12 @@ function buildConflictFragments(group, facts, paragraphWindow) {
|
|
|
887
1058
|
])),
|
|
888
1059
|
score: Number(Math.max(Number(left.item.score || 0), Number(right.item.score || 0)).toFixed(4)),
|
|
889
1060
|
sourceBoundary: 'full_document',
|
|
890
|
-
});
|
|
1061
|
+
}, execution));
|
|
891
1062
|
});
|
|
892
1063
|
});
|
|
893
1064
|
return fragments;
|
|
894
1065
|
}
|
|
895
|
-
function buildCrossDocumentConflictFragments(facts) {
|
|
1066
|
+
function buildCrossDocumentConflictFragments(facts, execution) {
|
|
896
1067
|
const orderedFacts = facts.slice().sort((left, right) => {
|
|
897
1068
|
const sourceDelta = String(left.item.atom.sourcePath || '').localeCompare(String(right.item.atom.sourcePath || ''));
|
|
898
1069
|
if (sourceDelta !== 0) {
|
|
@@ -903,14 +1074,12 @@ function buildCrossDocumentConflictFragments(facts) {
|
|
|
903
1074
|
const fragments = [];
|
|
904
1075
|
const seenConflicts = new Set();
|
|
905
1076
|
orderedFacts.forEach((left, leftIndex) => {
|
|
1077
|
+
execution?.assertActive();
|
|
906
1078
|
orderedFacts.slice(leftIndex + 1).forEach((right) => {
|
|
907
1079
|
if (comparableFactDocumentKey(left) === comparableFactDocumentKey(right)) {
|
|
908
1080
|
return;
|
|
909
1081
|
}
|
|
910
|
-
if (left
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
if (left.valueKey === right.valueKey) {
|
|
1082
|
+
if (!comparableEvidenceFactsConflict(left, right)) {
|
|
914
1083
|
return;
|
|
915
1084
|
}
|
|
916
1085
|
const orderedSourceKeys = [comparableFactDocumentKey(left), comparableFactDocumentKey(right)].sort();
|
|
@@ -931,7 +1100,7 @@ function buildCrossDocumentConflictFragments(facts) {
|
|
|
931
1100
|
`${left.item.atom.title}: ${left.block.text}`,
|
|
932
1101
|
`${right.item.atom.title}: ${right.block.text}`,
|
|
933
1102
|
].join('\n');
|
|
934
|
-
fragments.push({
|
|
1103
|
+
fragments.push(finishEvidenceFragment({
|
|
935
1104
|
fragmentId: `rag_conflict_cross_document_${sanitizeFragmentPart(left.item.atom.documentId)}_${sanitizeFragmentPart(right.item.atom.documentId)}_${fragments.length + 1}`,
|
|
936
1105
|
role: 'conflict',
|
|
937
1106
|
text,
|
|
@@ -950,7 +1119,7 @@ function buildCrossDocumentConflictFragments(facts) {
|
|
|
950
1119
|
])),
|
|
951
1120
|
score: Number(Math.max(Number(left.item.score || 0), Number(right.item.score || 0)).toFixed(4)),
|
|
952
1121
|
sourceBoundary: 'full_document',
|
|
953
|
-
});
|
|
1122
|
+
}, execution));
|
|
954
1123
|
});
|
|
955
1124
|
});
|
|
956
1125
|
return fragments;
|
|
@@ -974,9 +1143,9 @@ function limitGraphNeighborDocumentContextFragments(fragments) {
|
|
|
974
1143
|
|| fragment.sourceBoundary !== 'full_document'
|
|
975
1144
|
|| selectedContextFragmentIds.has(fragment.fragmentId)));
|
|
976
1145
|
}
|
|
977
|
-
function buildDirectFragment(item, span, index, role = 'direct_support') {
|
|
1146
|
+
function buildDirectFragment(item, span, index, role = 'direct_support', execution) {
|
|
978
1147
|
const text = normalizeWhitespace(String(span.snippet || item.atom.content || item.atom.title || ''));
|
|
979
|
-
return {
|
|
1148
|
+
return finishEvidenceFragment({
|
|
980
1149
|
fragmentId: `${role === 'graph_neighbor_support' ? 'rag_graph_neighbor' : 'rag_direct'}_${sanitizeFragmentPart(item.atom.documentId)}_${sanitizeFragmentPart(span.id || String(index + 1))}`,
|
|
981
1150
|
role,
|
|
982
1151
|
text,
|
|
@@ -996,7 +1165,7 @@ function buildDirectFragment(item, span, index, role = 'direct_support') {
|
|
|
996
1165
|
relationEdgeIds: item.relationPath.map((edge) => edge.id),
|
|
997
1166
|
score: Number(Number(item.score || 0).toFixed(4)),
|
|
998
1167
|
sourceBoundary: 'direct_span_only',
|
|
999
|
-
};
|
|
1168
|
+
}, execution);
|
|
1000
1169
|
}
|
|
1001
1170
|
function groupItemsByDocument(items, graphNeighborItems = []) {
|
|
1002
1171
|
const groups = new Map();
|
|
@@ -1038,7 +1207,7 @@ async function resolveDocumentSource(group, sourceResolver) {
|
|
|
1038
1207
|
atomIds,
|
|
1039
1208
|
citationIds,
|
|
1040
1209
|
});
|
|
1041
|
-
if (!source || !String(source.content || '').trim()) {
|
|
1210
|
+
if (!source || (!source.unavailableReason && !String(source.content || '').trim())) {
|
|
1042
1211
|
return null;
|
|
1043
1212
|
}
|
|
1044
1213
|
return {
|
|
@@ -1048,8 +1217,7 @@ async function resolveDocumentSource(group, sourceResolver) {
|
|
|
1048
1217
|
content: String(source.content || ''),
|
|
1049
1218
|
};
|
|
1050
1219
|
}
|
|
1051
|
-
function buildParentFragments(group, source, paragraphWindow) {
|
|
1052
|
-
const blocks = parseMarkdownBlocks(source.content);
|
|
1220
|
+
function buildParentFragments(group, source, paragraphWindow, blocks, execution) {
|
|
1053
1221
|
const parentDrafts = new Map();
|
|
1054
1222
|
group.entries
|
|
1055
1223
|
.filter((entry) => entry.expandDocumentContext)
|
|
@@ -1098,7 +1266,7 @@ function buildParentFragments(group, source, paragraphWindow) {
|
|
|
1098
1266
|
const fragmentPrefix = draft.role === 'graph_neighbor_support'
|
|
1099
1267
|
? 'rag_graph_neighbor_context'
|
|
1100
1268
|
: 'rag_parent';
|
|
1101
|
-
return {
|
|
1269
|
+
return finishEvidenceFragment({
|
|
1102
1270
|
fragmentId: `${fragmentPrefix}_${sanitizeFragmentPart(draft.documentId)}_${index + 1}`,
|
|
1103
1271
|
role: draft.role,
|
|
1104
1272
|
text,
|
|
@@ -1118,7 +1286,7 @@ function buildParentFragments(group, source, paragraphWindow) {
|
|
|
1118
1286
|
relationEdgeIds: Array.from(draft.relationEdgeIds),
|
|
1119
1287
|
score: Number(Number(draft.score || 0).toFixed(4)),
|
|
1120
1288
|
sourceBoundary: 'full_document',
|
|
1121
|
-
};
|
|
1289
|
+
}, execution);
|
|
1122
1290
|
}).filter((fragment) => fragment.text.length > 0);
|
|
1123
1291
|
}
|
|
1124
1292
|
async function assembleRagEvidenceContext(params) {
|
|
@@ -1126,51 +1294,75 @@ async function assembleRagEvidenceContext(params) {
|
|
|
1126
1294
|
const decisions = [];
|
|
1127
1295
|
const rawFragments = [];
|
|
1128
1296
|
const fullDocumentComparableFacts = [];
|
|
1297
|
+
const execution = params.execution;
|
|
1129
1298
|
let readFullDocument = false;
|
|
1130
1299
|
const groups = groupItemsByDocument(Array.isArray(params.items) ? params.items : [], Array.isArray(params.graphNeighborItems) ? params.graphNeighborItems : []);
|
|
1131
1300
|
for (const group of groups) {
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
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
|
+
});
|
|
1136
1307
|
});
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
.
|
|
1142
|
-
|
|
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));
|
|
1143
1325
|
decisions.push({
|
|
1144
|
-
documentId: group.documentId,
|
|
1145
|
-
|
|
1146
|
-
sourceBoundary: 'direct_span_only',
|
|
1147
|
-
status: 'source_window_unavailable',
|
|
1148
|
-
reason: unavailableRoles
|
|
1149
|
-
? `source_resolver_returned_no_content:${unavailableRoles}`
|
|
1150
|
-
: 'source_resolver_returned_no_content',
|
|
1326
|
+
documentId: group.documentId, sourcePath: group.sourcePath,
|
|
1327
|
+
sourceBoundary: 'full_document', status: 'read', charsRead: source.content.length,
|
|
1151
1328
|
});
|
|
1152
|
-
continue;
|
|
1153
1329
|
}
|
|
1154
|
-
|
|
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;
|
|
1155
1347
|
decisions.push({
|
|
1156
|
-
documentId:
|
|
1157
|
-
|
|
1158
|
-
sourceBoundary: 'full_document',
|
|
1159
|
-
status: 'read',
|
|
1160
|
-
charsRead: source.content.length,
|
|
1348
|
+
documentId: 'cross_document_conflicts', sourcePath: '',
|
|
1349
|
+
sourceBoundary: 'direct_span_only', status: 'source_window_unavailable', reason: error.code,
|
|
1161
1350
|
});
|
|
1162
|
-
rawFragments.push(...buildParentFragments(group, source, paragraphWindow));
|
|
1163
|
-
const selectedContextComparableFacts = collectSelectedContextComparableFacts(group, source, paragraphWindow);
|
|
1164
|
-
fullDocumentComparableFacts.push(...collectFullDocumentComparableFacts(group, source));
|
|
1165
|
-
rawFragments.push(...buildConflictFragments(group, selectedContextComparableFacts, paragraphWindow));
|
|
1166
1351
|
}
|
|
1167
|
-
|
|
1352
|
+
execution?.assertActive();
|
|
1353
|
+
const candidateFragments = limitGraphNeighborDocumentContextFragments(rawFragments);
|
|
1354
|
+
const graphConditioning = (0, graphConditionedContext_1.conditionRagFragmentsByGraphPlan)({
|
|
1355
|
+
fragments: candidateFragments,
|
|
1356
|
+
graphAnswerPlan: params.graphAnswerPlan,
|
|
1357
|
+
});
|
|
1168
1358
|
return (0, ragContextPack_1.buildRagContextPack)({
|
|
1169
1359
|
query: params.query,
|
|
1170
1360
|
generatedAt: params.generatedAt,
|
|
1171
1361
|
sourceBoundary: readFullDocument ? 'full_document' : 'direct_span_only',
|
|
1172
|
-
fragments:
|
|
1362
|
+
fragments: candidateFragments,
|
|
1173
1363
|
sourceDecisions: decisions,
|
|
1174
1364
|
budget: params.budget,
|
|
1365
|
+
fragmentOrder: graphConditioning.fragmentOrder,
|
|
1366
|
+
graphConditioning: graphConditioning.trace,
|
|
1175
1367
|
});
|
|
1176
1368
|
}
|