@lucern/graph-primitives 0.1.0-alpha.2
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 +29 -0
- package/dist/beliefDecay-Q_26RTc-.d.ts +72 -0
- package/dist/beliefDecay.d.ts +2 -0
- package/dist/beliefDecay.js +1628 -0
- package/dist/beliefDecay.js.map +1 -0
- package/dist/beliefEvidenceLinks-42FlR48t.d.ts +77 -0
- package/dist/beliefEvidenceLinks.d.ts +1 -0
- package/dist/beliefEvidenceLinks.js +1978 -0
- package/dist/beliefEvidenceLinks.js.map +1 -0
- package/dist/beliefLifecycle-C-AehZgF.d.ts +43 -0
- package/dist/beliefLifecycle.d.ts +1 -0
- package/dist/beliefLifecycle.js +98 -0
- package/dist/beliefLifecycle.js.map +1 -0
- package/dist/confidencePropagationDispatch.d.ts +46 -0
- package/dist/confidencePropagationDispatch.js +744 -0
- package/dist/confidencePropagationDispatch.js.map +1 -0
- package/dist/contradictions-Hdwl7zid.d.ts +71 -0
- package/dist/contradictions.d.ts +1 -0
- package/dist/contradictions.js +1557 -0
- package/dist/contradictions.js.map +1 -0
- package/dist/convex.d.ts +23 -0
- package/dist/convex.js +17 -0
- package/dist/convex.js.map +1 -0
- package/dist/edgeValidation-CeI0wc0r.d.ts +35 -0
- package/dist/edgeValidation.d.ts +2 -0
- package/dist/edgeValidation.js +307 -0
- package/dist/edgeValidation.js.map +1 -0
- package/dist/edges/contains.d.ts +6 -0
- package/dist/edges/contains.js +14 -0
- package/dist/edges/contains.js.map +1 -0
- package/dist/edges/contradicts.d.ts +6 -0
- package/dist/edges/contradicts.js +183 -0
- package/dist/edges/contradicts.js.map +1 -0
- package/dist/edges/dependsOn.d.ts +6 -0
- package/dist/edges/dependsOn.js +240 -0
- package/dist/edges/dependsOn.js.map +1 -0
- package/dist/edges/derivedFrom.d.ts +6 -0
- package/dist/edges/derivedFrom.js +14 -0
- package/dist/edges/derivedFrom.js.map +1 -0
- package/dist/edges/elaborates.d.ts +6 -0
- package/dist/edges/elaborates.js +100 -0
- package/dist/edges/elaborates.js.map +1 -0
- package/dist/edges/index.d.ts +3 -0
- package/dist/edges/index.js +556 -0
- package/dist/edges/index.js.map +1 -0
- package/dist/edges/informs.d.ts +6 -0
- package/dist/edges/informs.js +112 -0
- package/dist/edges/informs.js.map +1 -0
- package/dist/edges/propagationTypes.d.ts +39 -0
- package/dist/edges/propagationTypes.js +17 -0
- package/dist/edges/propagationTypes.js.map +1 -0
- package/dist/edges/refutes.d.ts +6 -0
- package/dist/edges/refutes.js +108 -0
- package/dist/edges/refutes.js.map +1 -0
- package/dist/edges/supports.d.ts +6 -0
- package/dist/edges/supports.js +193 -0
- package/dist/edges/supports.js.map +1 -0
- package/dist/edges/tests.d.ts +6 -0
- package/dist/edges/tests.js +14 -0
- package/dist/edges/tests.js.map +1 -0
- package/dist/edges/utils.d.ts +12 -0
- package/dist/edges/utils.js +188 -0
- package/dist/edges/utils.js.map +1 -0
- package/dist/embeddingTrigger.d.ts +24 -0
- package/dist/embeddingTrigger.js +24 -0
- package/dist/embeddingTrigger.js.map +1 -0
- package/dist/entityBridge-DMaKooYn.d.ts +59 -0
- package/dist/entityBridge.d.ts +1 -0
- package/dist/entityBridge.js +663 -0
- package/dist/entityBridge.js.map +1 -0
- package/dist/entityLifecycle-BkhRJ-XI.d.ts +69 -0
- package/dist/entityLifecycle.d.ts +1 -0
- package/dist/entityLifecycle.js +2083 -0
- package/dist/entityLifecycle.js.map +1 -0
- package/dist/entityValidation-KLZ_Xl2D.d.ts +50 -0
- package/dist/entityValidation.d.ts +3 -0
- package/dist/entityValidation.js +71 -0
- package/dist/entityValidation.js.map +1 -0
- package/dist/epistemicAnswers-DSP1slZ9.d.ts +67 -0
- package/dist/epistemicAnswers.d.ts +1 -0
- package/dist/epistemicAnswers.js +1650 -0
- package/dist/epistemicAnswers.js.map +1 -0
- package/dist/epistemicBeliefs-DtFVTp-k.d.ts +377 -0
- package/dist/epistemicBeliefs.d.ts +5 -0
- package/dist/epistemicBeliefs.js +6386 -0
- package/dist/epistemicBeliefs.js.map +1 -0
- package/dist/epistemicContractHelpers.d.ts +1 -0
- package/dist/epistemicContractHelpers.js +320 -0
- package/dist/epistemicContractHelpers.js.map +1 -0
- package/dist/epistemicContracts.d.ts +77 -0
- package/dist/epistemicContracts.js +8436 -0
- package/dist/epistemicContracts.js.map +1 -0
- package/dist/epistemicEdges-DcA8ErUG.d.ts +191 -0
- package/dist/epistemicEdges.d.ts +2 -0
- package/dist/epistemicEdges.js +2749 -0
- package/dist/epistemicEdges.js.map +1 -0
- package/dist/epistemicEvidence-Bo638XDP.d.ts +128 -0
- package/dist/epistemicEvidence.d.ts +3 -0
- package/dist/epistemicEvidence.js +3282 -0
- package/dist/epistemicEvidence.js.map +1 -0
- package/dist/epistemicHelpers-Bd9xbaib.d.ts +329 -0
- package/dist/epistemicHelpers.d.ts +4 -0
- package/dist/epistemicHelpers.js +999 -0
- package/dist/epistemicHelpers.js.map +1 -0
- package/dist/epistemicLinking-CyeLOIzN.d.ts +35 -0
- package/dist/epistemicLinking.d.ts +1 -0
- package/dist/epistemicLinking.js +1391 -0
- package/dist/epistemicLinking.js.map +1 -0
- package/dist/epistemicNodes-BpD6Koud.d.ts +167 -0
- package/dist/epistemicNodes.d.ts +2 -0
- package/dist/epistemicNodes.js +2942 -0
- package/dist/epistemicNodes.js.map +1 -0
- package/dist/epistemicQuestions-CmEeY6zQ.d.ts +214 -0
- package/dist/epistemicQuestions.d.ts +3 -0
- package/dist/epistemicQuestions.js +4993 -0
- package/dist/epistemicQuestions.js.map +1 -0
- package/dist/epistemicSources-ZazxHOK1.d.ts +25 -0
- package/dist/epistemicSources.d.ts +1 -0
- package/dist/epistemicSources.js +2025 -0
- package/dist/epistemicSources.js.map +1 -0
- package/dist/evaluators/index.d.ts +9 -0
- package/dist/evaluators/index.js +8440 -0
- package/dist/evaluators/index.js.map +1 -0
- package/dist/evaluators/lintCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/lintCheckerEvaluator.js +155 -0
- package/dist/evaluators/lintCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/sentryCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/sentryCheckerEvaluator.js +126 -0
- package/dist/evaluators/sentryCheckerEvaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +27 -0
- package/dist/evaluators/shared.js +92 -0
- package/dist/evaluators/shared.js.map +1 -0
- package/dist/evaluators/testRunnerEvaluator.d.ts +17 -0
- package/dist/evaluators/testRunnerEvaluator.js +232 -0
- package/dist/evaluators/testRunnerEvaluator.js.map +1 -0
- package/dist/evaluators/tscCheckerEvaluator.d.ts +11 -0
- package/dist/evaluators/tscCheckerEvaluator.js +189 -0
- package/dist/evaluators/tscCheckerEvaluator.js.map +1 -0
- package/dist/globalId-DKh9d_uD.d.ts +20 -0
- package/dist/globalId.d.ts +1 -0
- package/dist/globalId.js +15 -0
- package/dist/globalId.js.map +1 -0
- package/dist/graphTypes-CpgIuCdo.d.ts +52 -0
- package/dist/graphTypes.d.ts +1 -0
- package/dist/graphTypes.js +120 -0
- package/dist/graphTypes.js.map +1 -0
- package/dist/helpers-BYHIk5vU.d.ts +27 -0
- package/dist/helpers.d.ts +4 -0
- package/dist/helpers.js +313 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index-Dct1T70K.d.ts +25 -0
- package/dist/index-Dq-7R-gi.d.ts +31 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +22294 -0
- package/dist/index.js.map +1 -0
- package/dist/invariantEnforcement.d.ts +52 -0
- package/dist/invariantEnforcement.js +231 -0
- package/dist/invariantEnforcement.js.map +1 -0
- package/dist/logicalRoleInference-CJxqWi3u.d.ts +16 -0
- package/dist/logicalRoleInference.d.ts +3 -0
- package/dist/logicalRoleInference.js +64 -0
- package/dist/logicalRoleInference.js.map +1 -0
- package/dist/matcherFeedbackUtils.d.ts +33 -0
- package/dist/matcherFeedbackUtils.js +95 -0
- package/dist/matcherFeedbackUtils.js.map +1 -0
- package/dist/ontology-matching-Buhu23ss.d.ts +48 -0
- package/dist/ontology-matching.d.ts +2 -0
- package/dist/ontology-matching.js +346 -0
- package/dist/ontology-matching.js.map +1 -0
- package/dist/ontologyApproval-Ba0Jjk1k.d.ts +26 -0
- package/dist/ontologyApproval.d.ts +1 -0
- package/dist/ontologyApproval.js +78 -0
- package/dist/ontologyApproval.js.map +1 -0
- package/dist/ontologyDefinitions.d.ts +72 -0
- package/dist/ontologyDefinitions.js +635 -0
- package/dist/ontologyDefinitions.js.map +1 -0
- package/dist/ontologyHelpers.d.ts +79 -0
- package/dist/ontologyHelpers.js +81 -0
- package/dist/ontologyHelpers.js.map +1 -0
- package/dist/ontologyRegistry-B67rPJ16.d.ts +31 -0
- package/dist/ontologyRegistry.d.ts +1 -0
- package/dist/ontologyRegistry.js +296 -0
- package/dist/ontologyRegistry.js.map +1 -0
- package/dist/projectionReconciliation-CxrXYGaB.d.ts +20 -0
- package/dist/projectionReconciliation.d.ts +1 -0
- package/dist/projectionReconciliation.js +261 -0
- package/dist/projectionReconciliation.js.map +1 -0
- package/dist/projectionStaleness-CAdpIsaW.d.ts +51 -0
- package/dist/projectionStaleness.d.ts +1 -0
- package/dist/projectionStaleness.js +57 -0
- package/dist/projectionStaleness.js.map +1 -0
- package/dist/questionEvidenceLinks-BdQD0TkM.d.ts +34 -0
- package/dist/questionEvidenceLinks.d.ts +1 -0
- package/dist/questionEvidenceLinks.js +1690 -0
- package/dist/questionEvidenceLinks.js.map +1 -0
- package/dist/resolverTypes-CC8Ea2E2.d.ts +20 -0
- package/dist/resolverTypes.d.ts +4 -0
- package/dist/resolverTypes.js +3 -0
- package/dist/resolverTypes.js.map +1 -0
- package/dist/resolvers-Br1a6eLV.d.ts +14 -0
- package/dist/resolvers.d.ts +5 -0
- package/dist/resolvers.js +308 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/scopeResolverCompat.d.ts +26 -0
- package/dist/scopeResolverCompat.js +242 -0
- package/dist/scopeResolverCompat.js.map +1 -0
- package/dist/text-matching-CMn2WnVD.d.ts +40 -0
- package/dist/text-matching.d.ts +2 -0
- package/dist/text-matching.js +246 -0
- package/dist/text-matching.js.map +1 -0
- package/dist/topicOntologyResolver.d.ts +80 -0
- package/dist/topicOntologyResolver.js +67 -0
- package/dist/topicOntologyResolver.js.map +1 -0
- package/dist/topicProjectOverlay.d.ts +92 -0
- package/dist/topicProjectOverlay.js +249 -0
- package/dist/topicProjectOverlay.js.map +1 -0
- package/dist/topicScope-By_zp4tt.d.ts +34 -0
- package/dist/topicScope.d.ts +3 -0
- package/dist/topicScope.js +206 -0
- package/dist/topicScope.js.map +1 -0
- package/dist/workspaceIsolation.d.ts +44 -0
- package/dist/workspaceIsolation.js +950 -0
- package/dist/workspaceIsolation.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// ../../packages/contracts/src/text-matching.contract.ts
|
|
2
|
+
var TOKEN_SPLIT_REGEX = /[^a-z0-9]+/;
|
|
3
|
+
var NON_ALPHANUMERIC_REGEX = /[^a-z0-9]/g;
|
|
4
|
+
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
5
|
+
"the",
|
|
6
|
+
"a",
|
|
7
|
+
"an",
|
|
8
|
+
"and",
|
|
9
|
+
"or",
|
|
10
|
+
"but",
|
|
11
|
+
"in",
|
|
12
|
+
"on",
|
|
13
|
+
"at",
|
|
14
|
+
"to",
|
|
15
|
+
"for",
|
|
16
|
+
"of",
|
|
17
|
+
"with",
|
|
18
|
+
"by",
|
|
19
|
+
"from",
|
|
20
|
+
"is",
|
|
21
|
+
"it",
|
|
22
|
+
"as",
|
|
23
|
+
"be",
|
|
24
|
+
"was",
|
|
25
|
+
"are",
|
|
26
|
+
"this",
|
|
27
|
+
"that",
|
|
28
|
+
"has",
|
|
29
|
+
"had",
|
|
30
|
+
"have",
|
|
31
|
+
"not",
|
|
32
|
+
"all",
|
|
33
|
+
"can",
|
|
34
|
+
"do",
|
|
35
|
+
"its",
|
|
36
|
+
"may",
|
|
37
|
+
"will",
|
|
38
|
+
"how",
|
|
39
|
+
"what",
|
|
40
|
+
"which",
|
|
41
|
+
"who",
|
|
42
|
+
"when",
|
|
43
|
+
"where",
|
|
44
|
+
"than",
|
|
45
|
+
"then",
|
|
46
|
+
"each",
|
|
47
|
+
"into",
|
|
48
|
+
"such",
|
|
49
|
+
"any",
|
|
50
|
+
"been",
|
|
51
|
+
"if",
|
|
52
|
+
"would",
|
|
53
|
+
"about",
|
|
54
|
+
"should",
|
|
55
|
+
"these",
|
|
56
|
+
"those",
|
|
57
|
+
"their",
|
|
58
|
+
"we",
|
|
59
|
+
"our",
|
|
60
|
+
"so"
|
|
61
|
+
]);
|
|
62
|
+
function tokenizeSearchText(text) {
|
|
63
|
+
return text.toLowerCase().split(TOKEN_SPLIT_REGEX).filter((token) => token.length >= 2 && !STOP_WORDS.has(token));
|
|
64
|
+
}
|
|
65
|
+
function stemToken(word) {
|
|
66
|
+
if (word.length <= 4) {
|
|
67
|
+
return word;
|
|
68
|
+
}
|
|
69
|
+
if (word.endsWith("ation")) {
|
|
70
|
+
return word.slice(0, -5);
|
|
71
|
+
}
|
|
72
|
+
if (word.endsWith("ment")) {
|
|
73
|
+
return word.slice(0, -4);
|
|
74
|
+
}
|
|
75
|
+
if (word.endsWith("ness")) {
|
|
76
|
+
return word.slice(0, -4);
|
|
77
|
+
}
|
|
78
|
+
if (word.endsWith("ical")) {
|
|
79
|
+
return word.slice(0, -4);
|
|
80
|
+
}
|
|
81
|
+
if (word.endsWith("tion")) {
|
|
82
|
+
return word.slice(0, -4);
|
|
83
|
+
}
|
|
84
|
+
if (word.endsWith("sion")) {
|
|
85
|
+
return word.slice(0, -4);
|
|
86
|
+
}
|
|
87
|
+
if (word.endsWith("ing")) {
|
|
88
|
+
return word.slice(0, -3);
|
|
89
|
+
}
|
|
90
|
+
if (word.endsWith("ous")) {
|
|
91
|
+
return word.slice(0, -3);
|
|
92
|
+
}
|
|
93
|
+
if (word.endsWith("ive")) {
|
|
94
|
+
return word.slice(0, -3);
|
|
95
|
+
}
|
|
96
|
+
if (word.endsWith("ity")) {
|
|
97
|
+
return word.slice(0, -3);
|
|
98
|
+
}
|
|
99
|
+
if (word.endsWith("ics")) {
|
|
100
|
+
return word.slice(0, -3);
|
|
101
|
+
}
|
|
102
|
+
if (word.endsWith("ly")) {
|
|
103
|
+
return word.slice(0, -2);
|
|
104
|
+
}
|
|
105
|
+
if (word.endsWith("ed")) {
|
|
106
|
+
return word.slice(0, -2);
|
|
107
|
+
}
|
|
108
|
+
if (word.endsWith("er")) {
|
|
109
|
+
return word.slice(0, -2);
|
|
110
|
+
}
|
|
111
|
+
if (word.endsWith("es")) {
|
|
112
|
+
return word.slice(0, -2);
|
|
113
|
+
}
|
|
114
|
+
if (word.endsWith("al")) {
|
|
115
|
+
return word.slice(0, -2);
|
|
116
|
+
}
|
|
117
|
+
if (word.endsWith("ic")) {
|
|
118
|
+
return word.slice(0, -2);
|
|
119
|
+
}
|
|
120
|
+
if (word.endsWith("s") && !word.endsWith("ss")) {
|
|
121
|
+
return word.slice(0, -1);
|
|
122
|
+
}
|
|
123
|
+
return word;
|
|
124
|
+
}
|
|
125
|
+
function tokenOverlapScore(queryTokens, textTokens) {
|
|
126
|
+
if (queryTokens.length === 0 || textTokens.length === 0) {
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
const stemmedText = new Set(textTokens.map(stemToken));
|
|
130
|
+
let matchCount = 0;
|
|
131
|
+
for (const queryToken of queryTokens) {
|
|
132
|
+
const stemmedQuery = stemToken(queryToken);
|
|
133
|
+
if (stemmedText.has(stemmedQuery)) {
|
|
134
|
+
matchCount += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
for (const textToken of stemmedText) {
|
|
138
|
+
if (textToken.startsWith(stemmedQuery) || stemmedQuery.startsWith(textToken)) {
|
|
139
|
+
matchCount += 0.5;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return matchCount / queryTokens.length;
|
|
145
|
+
}
|
|
146
|
+
function bigramTokenize(text) {
|
|
147
|
+
const normalized = text.toLowerCase().replace(NON_ALPHANUMERIC_REGEX, "");
|
|
148
|
+
const bigrams = /* @__PURE__ */ new Set();
|
|
149
|
+
for (let i = 0; i < normalized.length - 1; i++) {
|
|
150
|
+
bigrams.add(normalized.slice(i, i + 2));
|
|
151
|
+
}
|
|
152
|
+
return bigrams;
|
|
153
|
+
}
|
|
154
|
+
function wordTokenize(text) {
|
|
155
|
+
return text.toLowerCase().split(TOKEN_SPLIT_REGEX).filter((token) => token.length > 1);
|
|
156
|
+
}
|
|
157
|
+
function jaccardSimilarity(setA, setB) {
|
|
158
|
+
if (setA.size === 0 && setB.size === 0) {
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
let intersectionSize = 0;
|
|
162
|
+
const smaller = setA.size <= setB.size ? setA : setB;
|
|
163
|
+
const larger = setA.size <= setB.size ? setB : setA;
|
|
164
|
+
for (const item of smaller) {
|
|
165
|
+
if (larger.has(item)) {
|
|
166
|
+
intersectionSize++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const unionSize = setA.size + setB.size - intersectionSize;
|
|
170
|
+
return unionSize === 0 ? 0 : intersectionSize / unionSize;
|
|
171
|
+
}
|
|
172
|
+
function wordOverlapScore(inputWords, typeWords) {
|
|
173
|
+
if (typeWords.length === 0) {
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
let matches = 0;
|
|
177
|
+
for (const word of typeWords) {
|
|
178
|
+
if (inputWords.includes(word)) {
|
|
179
|
+
matches++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return matches / typeWords.length;
|
|
183
|
+
}
|
|
184
|
+
function prepareLexicalQuery(query) {
|
|
185
|
+
return {
|
|
186
|
+
raw: query,
|
|
187
|
+
tokens: tokenizeSearchText(query),
|
|
188
|
+
words: wordTokenize(query),
|
|
189
|
+
bigrams: bigramTokenize(query)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function scoreLexicalSignal(query, signal) {
|
|
193
|
+
const text = signal.text?.trim();
|
|
194
|
+
if (!text) {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
switch (signal.strategy ?? "tokenOverlap") {
|
|
198
|
+
case "bigramJaccard":
|
|
199
|
+
return jaccardSimilarity(query.bigrams, bigramTokenize(text));
|
|
200
|
+
case "wordOverlap":
|
|
201
|
+
return wordOverlapScore(query.words, wordTokenize(text));
|
|
202
|
+
default:
|
|
203
|
+
return tokenOverlapScore(query.tokens, tokenizeSearchText(text));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function scoreLexicalSignals(query, signals) {
|
|
207
|
+
let weightedScore = 0;
|
|
208
|
+
let totalWeight = 0;
|
|
209
|
+
for (const signal of signals) {
|
|
210
|
+
if (!signal.text?.trim() || signal.weight <= 0) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
weightedScore += scoreLexicalSignal(query, signal) * signal.weight;
|
|
214
|
+
totalWeight += signal.weight;
|
|
215
|
+
}
|
|
216
|
+
return totalWeight === 0 ? 0 : weightedScore / totalWeight;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ../../packages/contracts/src/v1/ontologies/v1.ts
|
|
220
|
+
var MATCH_WEIGHTS = {
|
|
221
|
+
tokenOverlap: 0.35,
|
|
222
|
+
bigramSimilarity: 0.25,
|
|
223
|
+
wordOverlap: 0.2,
|
|
224
|
+
descriptionBonus: 0.2
|
|
225
|
+
};
|
|
226
|
+
function scoreEntityTypeMatch(inputText, entityType) {
|
|
227
|
+
const preparedQuery = prepareLexicalQuery(inputText);
|
|
228
|
+
const labelText = `${entityType.label} ${entityType.value}`;
|
|
229
|
+
const tokenScore = scoreLexicalSignals(preparedQuery, [
|
|
230
|
+
{ text: labelText, weight: 1, strategy: "tokenOverlap" }
|
|
231
|
+
]);
|
|
232
|
+
const labelBigrams = bigramTokenize(entityType.label);
|
|
233
|
+
const bigramScore = jaccardSimilarity(preparedQuery.bigrams, labelBigrams);
|
|
234
|
+
const labelWords = wordTokenize(labelText);
|
|
235
|
+
const wordScore = wordOverlapScore(preparedQuery.words, labelWords);
|
|
236
|
+
let descScore = 0;
|
|
237
|
+
if (entityType.description) {
|
|
238
|
+
descScore = scoreLexicalSignals(preparedQuery, [
|
|
239
|
+
{ text: entityType.description, weight: 1, strategy: "tokenOverlap" }
|
|
240
|
+
]);
|
|
241
|
+
}
|
|
242
|
+
let subtypeBonus = 0;
|
|
243
|
+
if (entityType.subtypes && entityType.subtypes.length > 0) {
|
|
244
|
+
for (const subtype of entityType.subtypes) {
|
|
245
|
+
const subtypeScore = scoreLexicalSignals(preparedQuery, [
|
|
246
|
+
{
|
|
247
|
+
text: `${subtype.label} ${subtype.value} ${subtype.description || ""}`,
|
|
248
|
+
weight: 1,
|
|
249
|
+
strategy: "tokenOverlap"
|
|
250
|
+
}
|
|
251
|
+
]);
|
|
252
|
+
subtypeBonus = Math.max(subtypeBonus, subtypeScore * 0.3);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const score = Math.min(
|
|
256
|
+
1,
|
|
257
|
+
tokenScore * MATCH_WEIGHTS.tokenOverlap + bigramScore * MATCH_WEIGHTS.bigramSimilarity + wordScore * MATCH_WEIGHTS.wordOverlap + descScore * MATCH_WEIGHTS.descriptionBonus + subtypeBonus
|
|
258
|
+
);
|
|
259
|
+
const reasons = [];
|
|
260
|
+
if (tokenScore > 0.3) {
|
|
261
|
+
reasons.push(`stem match: ${(tokenScore * 100).toFixed(0)}%`);
|
|
262
|
+
}
|
|
263
|
+
if (bigramScore > 0.3) {
|
|
264
|
+
reasons.push(`text similarity: ${(bigramScore * 100).toFixed(0)}%`);
|
|
265
|
+
}
|
|
266
|
+
if (wordScore > 0.3) {
|
|
267
|
+
reasons.push(`word match: ${(wordScore * 100).toFixed(0)}%`);
|
|
268
|
+
}
|
|
269
|
+
if (descScore > 0.2) {
|
|
270
|
+
reasons.push("description match");
|
|
271
|
+
}
|
|
272
|
+
if (subtypeBonus > 0.05) {
|
|
273
|
+
reasons.push("subtype match");
|
|
274
|
+
}
|
|
275
|
+
const reason = reasons.length > 0 ? reasons.join(", ") : "low similarity";
|
|
276
|
+
return {
|
|
277
|
+
entityType: entityType.value,
|
|
278
|
+
label: entityType.label,
|
|
279
|
+
score,
|
|
280
|
+
reason
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function rankEntityTypeMatches(inputText, entityTypes, options) {
|
|
284
|
+
const minScore = options?.minScore ?? 0.05;
|
|
285
|
+
const limit = options?.limit ?? 10;
|
|
286
|
+
const matches = entityTypes.map((et) => scoreEntityTypeMatch(inputText, et)).filter((m) => m.score >= minScore).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
287
|
+
return matches;
|
|
288
|
+
}
|
|
289
|
+
function scoreEntityConnection(nodeText, candidate, options) {
|
|
290
|
+
const preparedQuery = prepareLexicalQuery(nodeText);
|
|
291
|
+
const connectivityWeight = options?.connectivityWeight ?? 0.3;
|
|
292
|
+
const textWeight = 1 - connectivityWeight;
|
|
293
|
+
const candidateText = `${candidate.title} ${candidate.canonicalText}`;
|
|
294
|
+
const tokenScore = scoreLexicalSignals(preparedQuery, [
|
|
295
|
+
{ text: candidateText, weight: 1, strategy: "tokenOverlap" }
|
|
296
|
+
]);
|
|
297
|
+
const textScore = scoreLexicalSignals(preparedQuery, [
|
|
298
|
+
{ text: candidateText, weight: 1, strategy: "bigramJaccard" }
|
|
299
|
+
]);
|
|
300
|
+
const wordScore = scoreLexicalSignals(preparedQuery, [
|
|
301
|
+
{ text: candidateText, weight: 1, strategy: "wordOverlap" }
|
|
302
|
+
]);
|
|
303
|
+
const maxConnections = Math.max(
|
|
304
|
+
1,
|
|
305
|
+
candidate.connectedBeliefCount + candidate.connectedEvidenceCount
|
|
306
|
+
);
|
|
307
|
+
const connectivityScore = Math.min(1, maxConnections / 10);
|
|
308
|
+
const combinedTextScore = tokenScore * 0.45 + textScore * 0.35 + wordScore * 0.2;
|
|
309
|
+
const score = combinedTextScore * textWeight + connectivityScore * connectivityWeight;
|
|
310
|
+
const suggestedEdgeType = suggestEdgeType(candidate.entityType);
|
|
311
|
+
const reason = tokenScore > 0.3 ? `stem match: ${(tokenScore * 100).toFixed(0)}%` : textScore > 0.2 ? `name similarity: ${(textScore * 100).toFixed(0)}%` : wordScore > 0.2 ? `keyword match: ${(wordScore * 100).toFixed(0)}%` : `connectivity: ${candidate.connectedBeliefCount} beliefs`;
|
|
312
|
+
return {
|
|
313
|
+
entityNodeId: candidate.nodeId,
|
|
314
|
+
entityType: candidate.entityType,
|
|
315
|
+
title: candidate.title,
|
|
316
|
+
score,
|
|
317
|
+
suggestedEdgeType,
|
|
318
|
+
reason
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function suggestEdgeType(entityType) {
|
|
322
|
+
switch (entityType) {
|
|
323
|
+
case "company":
|
|
324
|
+
case "person":
|
|
325
|
+
case "investor":
|
|
326
|
+
return "contains";
|
|
327
|
+
case "function":
|
|
328
|
+
case "value_chain":
|
|
329
|
+
return "impacts";
|
|
330
|
+
default:
|
|
331
|
+
return "contains";
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function rankEntityConnections(nodeText, candidates, options) {
|
|
335
|
+
const minScore = options?.minScore ?? 0.05;
|
|
336
|
+
const limit = options?.limit ?? 10;
|
|
337
|
+
return candidates.map(
|
|
338
|
+
(c) => scoreEntityConnection(nodeText, c, {
|
|
339
|
+
connectivityWeight: options?.connectivityWeight
|
|
340
|
+
})
|
|
341
|
+
).filter((m) => m.score >= minScore).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export { rankEntityConnections, rankEntityTypeMatches, scoreEntityConnection, scoreEntityTypeMatch };
|
|
345
|
+
//# sourceMappingURL=ontology-matching.js.map
|
|
346
|
+
//# sourceMappingURL=ontology-matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/contracts/src/text-matching.contract.ts","../../../packages/contracts/src/v1/ontologies/v1.ts"],"names":[],"mappings":";AA4BA,IAAM,iBAAA,GAAoB,YAAA;AAC1B,IAAM,sBAAA,GAAyB,YAAA;AAG/B,IAAM,UAAA,uBAAiB,GAAA,CAAI;AAAA,EACzB,KAAA;AAAA,EACA,GAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGM,SAAS,mBAAmB,IAAA,EAAwB;AACzD,EAAA,OAAO,KACJ,WAAA,EAAY,CACZ,KAAA,CAAM,iBAAiB,EACvB,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,UAAU,CAAA,IAAK,CAAC,UAAA,CAAW,GAAA,CAAI,KAAK,CAAC,CAAA;AAClE;AAGO,SAAS,UAAU,IAAA,EAAsB;AAC9C,EAAA,IAAI,IAAA,CAAK,UAAU,CAAA,EAAG;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,EAAG;AAC1B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,SAAS,GAAG,CAAA,IAAK,CAAC,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AAC9C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EACzB;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,iBAAA,CACd,aACA,UAAA,EACQ;AACR,EAAA,IAAI,WAAA,CAAY,MAAA,KAAW,CAAA,IAAK,UAAA,CAAW,WAAW,CAAA,EAAG;AACvD,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,MAAM,cAAc,IAAI,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,SAAS,CAAC,CAAA;AACrD,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,MAAM,YAAA,GAAe,UAAU,UAAU,CAAA;AAEzC,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACjC,MAAA,UAAA,IAAc,CAAA;AACd,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,aAAa,WAAA,EAAa;AACnC,MAAA,IACE,UAAU,UAAA,CAAW,YAAY,KACjC,YAAA,CAAa,UAAA,CAAW,SAAS,CAAA,EACjC;AACA,QAAA,UAAA,IAAc,GAAA;AACd,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,aAAa,WAAA,CAAY,MAAA;AAClC;AAMO,SAAS,eAAe,IAAA,EAA2B;AACxD,EAAA,MAAM,aAAa,IAAA,CAAK,WAAA,EAAY,CAAE,OAAA,CAAQ,wBAAwB,EAAE,CAAA;AACxE,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,MAAA,GAAS,GAAG,CAAA,EAAA,EAAK;AAC9C,IAAA,OAAA,CAAQ,IAAI,UAAA,CAAW,KAAA,CAAM,CAAA,EAAG,CAAA,GAAI,CAAC,CAAC,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,OAAA;AACT;AAMO,SAAS,aAAa,IAAA,EAAwB;AACnD,EAAA,OAAO,IAAA,CACJ,WAAA,EAAY,CACZ,KAAA,CAAM,iBAAiB,CAAA,CACvB,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACvC;AAGO,SAAS,iBAAA,CACd,MACA,IAAA,EACQ;AACR,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,CAAA,IAAK,IAAA,CAAK,SAAS,CAAA,EAAG;AACtC,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,OAAO,IAAA,GAAO,IAAA;AAChD,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,OAAO,IAAA,GAAO,IAAA;AAE/C,EAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,IAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAG;AACpB,MAAA,gBAAA,EAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,GAAO,gBAAA;AAC1C,EAAA,OAAO,SAAA,KAAc,CAAA,GAAI,CAAA,GAAI,gBAAA,GAAmB,SAAA;AAClD;AAGO,SAAS,gBAAA,CACd,YACA,SAAA,EACQ;AACR,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,IAAA,IAAI,UAAA,CAAW,QAAA,CAAS,IAAI,CAAA,EAAG;AAC7B,MAAA,OAAA,EAAA;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,UAAU,SAAA,CAAU,MAAA;AAC7B;AAGO,SAAS,oBAAoB,KAAA,EAAqC;AACvE,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,KAAA;AAAA,IACL,MAAA,EAAQ,mBAAmB,KAAK,CAAA;AAAA,IAChC,KAAA,EAAO,aAAa,KAAK,CAAA;AAAA,IACzB,OAAA,EAAS,eAAe,KAAK;AAAA,GAC/B;AACF;AAGO,SAAS,kBAAA,CACd,OACA,MAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,EAAM,IAAA,EAAK;AAC/B,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,QAAQ,MAAA,CAAO,YAAY,cAAA;AAAgB,IACzC,KAAK,eAAA;AACH,MAAA,OAAO,iBAAA,CAAkB,KAAA,CAAM,OAAA,EAAS,cAAA,CAAe,IAAI,CAAC,CAAA;AAAA,IAC9D,KAAK,aAAA;AACH,MAAA,OAAO,gBAAA,CAAiB,KAAA,CAAM,KAAA,EAAO,YAAA,CAAa,IAAI,CAAC,CAAA;AAAA,IACzD;AACE,MAAA,OAAO,iBAAA,CAAkB,KAAA,CAAM,MAAA,EAAQ,kBAAA,CAAmB,IAAI,CAAC,CAAA;AAAA;AAErE;AAGO,SAAS,mBAAA,CACd,OACA,OAAA,EACQ;AACR,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,MAAA,CAAO,IAAA,EAAM,MAAK,IAAK,MAAA,CAAO,UAAU,CAAA,EAAG;AAC9C,MAAA;AAAA,IACF;AACA,IAAA,aAAA,IAAiB,kBAAA,CAAmB,KAAA,EAAO,MAAM,CAAA,GAAI,MAAA,CAAO,MAAA;AAC5D,IAAA,WAAA,IAAe,MAAA,CAAO,MAAA;AAAA,EACxB;AAEA,EAAA,OAAO,WAAA,KAAgB,CAAA,GAAI,CAAA,GAAI,aAAA,GAAgB,WAAA;AACjD;;;AChPA,IAAM,aAAA,GAAgB;AAAA,EACpB,YAAA,EAAc,IAAA;AAAA,EACd,gBAAA,EAAkB,IAAA;AAAA,EAClB,WAAA,EAAa,GAAA;AAAA,EACb,gBAAA,EAAkB;AACpB,CAAA;AAMO,SAAS,oBAAA,CACd,WACA,UAAA,EACiB;AACjB,EAAA,MAAM,aAAA,GAAgB,oBAAoB,SAAS,CAAA;AACnD,EAAA,MAAM,YAAY,CAAA,EAAG,UAAA,CAAW,KAAK,CAAA,CAAA,EAAI,WAAW,KAAK,CAAA,CAAA;AAEzD,EAAA,MAAM,UAAA,GAAa,oBAAoB,aAAA,EAAe;AAAA,IACpD,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,CAAA,EAAG,UAAU,cAAA;AAAe,GACxD,CAAA;AAGD,EAAA,MAAM,YAAA,GAAe,cAAA,CAAe,UAAA,CAAW,KAAK,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,iBAAA,CAAkB,aAAA,CAAc,OAAA,EAAS,YAAY,CAAA;AAGzE,EAAA,MAAM,UAAA,GAAa,aAAa,SAAS,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,aAAA,CAAc,KAAA,EAAO,UAAU,CAAA;AAGlE,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,WAAW,WAAA,EAAa;AAC1B,IAAA,SAAA,GAAY,oBAAoB,aAAA,EAAe;AAAA,MAC7C,EAAE,IAAA,EAAM,UAAA,CAAW,aAAa,MAAA,EAAQ,CAAA,EAAG,UAAU,cAAA;AAAe,KACrE,CAAA;AAAA,EACH;AAGA,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,IAAI,UAAA,CAAW,QAAA,IAAY,UAAA,CAAW,QAAA,CAAS,SAAS,CAAA,EAAG;AACzD,IAAA,KAAA,MAAW,OAAA,IAAW,WAAW,QAAA,EAAU;AACzC,MAAA,MAAM,YAAA,GAAe,oBAAoB,aAAA,EAAe;AAAA,QACtD;AAAA,UACE,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA,CAAA,EAAI,QAAQ,KAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,WAAA,IAAe,EAAE,CAAA,CAAA;AAAA,UACpE,MAAA,EAAQ,CAAA;AAAA,UACR,QAAA,EAAU;AAAA;AACZ,OACD,CAAA;AACD,MAAA,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,YAAA,GAAe,GAAG,CAAA;AAAA,IAC1D;AAAA,EACF;AAEA,EAAA,MAAM,QAAQ,IAAA,CAAK,GAAA;AAAA,IACjB,CAAA;AAAA,IACA,UAAA,GAAa,aAAA,CAAc,YAAA,GACzB,WAAA,GAAc,aAAA,CAAc,gBAAA,GAC5B,SAAA,GAAY,aAAA,CAAc,WAAA,GAC1B,SAAA,GAAY,aAAA,CAAc,gBAAA,GAC1B;AAAA,GACJ;AAGA,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,OAAA,CAAQ,KAAK,CAAA,YAAA,EAAA,CAAgB,UAAA,GAAa,KAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9D;AACA,EAAA,IAAI,cAAc,GAAA,EAAK;AACrB,IAAA,OAAA,CAAQ,KAAK,CAAA,iBAAA,EAAA,CAAqB,WAAA,GAAc,KAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,YAAY,GAAA,EAAK;AACnB,IAAA,OAAA,CAAQ,KAAK,CAAA,YAAA,EAAA,CAAgB,SAAA,GAAY,KAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,YAAY,GAAA,EAAK;AACnB,IAAA,OAAA,CAAQ,KAAK,mBAAmB,CAAA;AAAA,EAClC;AACA,EAAA,IAAI,eAAe,IAAA,EAAM;AACvB,IAAA,OAAA,CAAQ,KAAK,eAAe,CAAA;AAAA,EAC9B;AACA,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,GAAS,IAAI,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,GAAI,gBAAA;AAEzD,EAAA,OAAO;AAAA,IACL,YAAY,UAAA,CAAW,KAAA;AAAA,IACvB,OAAO,UAAA,CAAW,KAAA;AAAA,IAClB,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAMO,SAAS,qBAAA,CACd,SAAA,EACA,WAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,IAAA;AACtC,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,EAAA;AAEhC,EAAA,MAAM,OAAA,GAAU,WAAA,CACb,GAAA,CAAI,CAAC,EAAA,KAAO,oBAAA,CAAqB,SAAA,EAAW,EAAE,CAAC,CAAA,CAC/C,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,IAAS,QAAQ,CAAA,CACjC,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAA,CAChC,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA;AAEjB,EAAA,OAAO,OAAA;AACT;AAUO,SAAS,qBAAA,CACd,QAAA,EACA,SAAA,EACA,OAAA,EACuB;AACvB,EAAA,MAAM,aAAA,GAAgB,oBAAoB,QAAQ,CAAA;AAClD,EAAA,MAAM,kBAAA,GAAqB,SAAS,kBAAA,IAAsB,GAAA;AAC1D,EAAA,MAAM,aAAa,CAAA,GAAM,kBAAA;AACzB,EAAA,MAAM,gBAAgB,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,CAAA,EAAI,UAAU,aAAa,CAAA,CAAA;AACnE,EAAA,MAAM,UAAA,GAAa,oBAAoB,aAAA,EAAe;AAAA,IACpD,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,CAAA,EAAG,UAAU,cAAA;AAAe,GAC5D,CAAA;AACD,EAAA,MAAM,SAAA,GAAY,oBAAoB,aAAA,EAAe;AAAA,IACnD,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,CAAA,EAAG,UAAU,eAAA;AAAgB,GAC7D,CAAA;AACD,EAAA,MAAM,SAAA,GAAY,oBAAoB,aAAA,EAAe;AAAA,IACnD,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,CAAA,EAAG,UAAU,aAAA;AAAc,GAC3D,CAAA;AAGD,EAAA,MAAM,iBAAiB,IAAA,CAAK,GAAA;AAAA,IAC1B,CAAA;AAAA,IACA,SAAA,CAAU,uBAAuB,SAAA,CAAU;AAAA,GAC7C;AACA,EAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAK,iBAAiB,EAAE,CAAA;AAE3D,EAAA,MAAM,iBAAA,GACJ,UAAA,GAAa,IAAA,GAAO,SAAA,GAAY,OAAO,SAAA,GAAY,GAAA;AACrD,EAAA,MAAM,KAAA,GACJ,iBAAA,GAAoB,UAAA,GAAa,iBAAA,GAAoB,kBAAA;AAGvD,EAAA,MAAM,iBAAA,GAAoB,eAAA,CAAgB,SAAA,CAAU,UAAU,CAAA;AAE9D,EAAA,MAAM,MAAA,GACJ,UAAA,GAAa,GAAA,GACT,CAAA,YAAA,EAAA,CAAgB,UAAA,GAAa,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,GAC5C,SAAA,GAAY,GAAA,GACV,qBAAqB,SAAA,GAAY,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,GAChD,SAAA,GAAY,GAAA,GACV,CAAA,eAAA,EAAA,CAAmB,SAAA,GAAY,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,GAC9C,CAAA,cAAA,EAAiB,UAAU,oBAAoB,CAAA,QAAA,CAAA;AAEzD,EAAA,OAAO;AAAA,IACL,cAAc,SAAA,CAAU,MAAA;AAAA,IACxB,YAAY,SAAA,CAAU,UAAA;AAAA,IACtB,OAAO,SAAA,CAAU,KAAA;AAAA,IACjB,KAAA;AAAA,IACA,iBAAA;AAAA,IACA;AAAA,GACF;AACF;AAKA,SAAS,gBAAgB,UAAA,EAA4B;AACnD,EAAA,QAAQ,UAAA;AAAY,IAClB,KAAK,SAAA;AAAA,IACL,KAAK,QAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,UAAA;AAAA,IACL,KAAK,aAAA;AACH,MAAA,OAAO,SAAA;AAAA,IACT;AACE,MAAA,OAAO,UAAA;AAAA;AAEb;AAMO,SAAS,qBAAA,CACd,QAAA,EACA,UAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,IAAA;AACtC,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,EAAA;AAEhC,EAAA,OAAO,UAAA,CACJ,GAAA;AAAA,IAAI,CAAC,CAAA,KACJ,qBAAA,CAAsB,QAAA,EAAU,CAAA,EAAG;AAAA,MACjC,oBAAoB,OAAA,EAAS;AAAA,KAC9B;AAAA,IAEF,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,KAAA,IAAS,QAAQ,CAAA,CACjC,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAA,CAChC,KAAA,CAAM,GAAG,KAAK,CAAA;AACnB","file":"ontology-matching.js","sourcesContent":["/**\n * Shared lexical matching primitives used across MCP handlers and graph utilities.\n *\n * The goal is not to replace downstream LLM scoring. It provides a fast,\n * deterministic substrate for candidate generation, reranking, and light\n * classification across belief/question/evidence/entity surfaces.\n */\n\nexport type LexicalStrategy = \"tokenOverlap\" | \"bigramJaccard\" | \"wordOverlap\";\n\nexport type PreparedLexicalQuery = {\n raw: string;\n tokens: string[];\n words: string[];\n bigrams: Set<string>;\n};\n\nexport type LexicalSignal = {\n strategy?: LexicalStrategy;\n text: string | null | undefined;\n weight: number;\n};\n\nexport type LexicalRerankOptions = {\n lexicalWeight?: number;\n rankWeight?: number;\n};\n\nconst TOKEN_SPLIT_REGEX = /[^a-z0-9]+/;\nconst NON_ALPHANUMERIC_REGEX = /[^a-z0-9]/g;\n\n/** Stop words that add noise to scoring. */\nconst STOP_WORDS = new Set([\n \"the\",\n \"a\",\n \"an\",\n \"and\",\n \"or\",\n \"but\",\n \"in\",\n \"on\",\n \"at\",\n \"to\",\n \"for\",\n \"of\",\n \"with\",\n \"by\",\n \"from\",\n \"is\",\n \"it\",\n \"as\",\n \"be\",\n \"was\",\n \"are\",\n \"this\",\n \"that\",\n \"has\",\n \"had\",\n \"have\",\n \"not\",\n \"all\",\n \"can\",\n \"do\",\n \"its\",\n \"may\",\n \"will\",\n \"how\",\n \"what\",\n \"which\",\n \"who\",\n \"when\",\n \"where\",\n \"than\",\n \"then\",\n \"each\",\n \"into\",\n \"such\",\n \"any\",\n \"been\",\n \"if\",\n \"would\",\n \"about\",\n \"should\",\n \"these\",\n \"those\",\n \"their\",\n \"we\",\n \"our\",\n \"so\",\n]);\n\n/** Tokenize a string into lowercase words, removing stop words. */\nexport function tokenizeSearchText(text: string): string[] {\n return text\n .toLowerCase()\n .split(TOKEN_SPLIT_REGEX)\n .filter((token) => token.length >= 2 && !STOP_WORDS.has(token));\n}\n\n/** Simple stemmer: strip common English suffixes for fuzzy matching. */\nexport function stemToken(word: string): string {\n if (word.length <= 4) {\n return word;\n }\n if (word.endsWith(\"ation\")) {\n return word.slice(0, -5);\n }\n if (word.endsWith(\"ment\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ness\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ical\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"tion\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"sion\")) {\n return word.slice(0, -4);\n }\n if (word.endsWith(\"ing\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ous\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ive\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ity\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ics\")) {\n return word.slice(0, -3);\n }\n if (word.endsWith(\"ly\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"ed\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"er\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"es\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"al\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"ic\")) {\n return word.slice(0, -2);\n }\n if (word.endsWith(\"s\") && !word.endsWith(\"ss\")) {\n return word.slice(0, -1);\n }\n return word;\n}\n\n/** Compute token overlap score between query tokens and text tokens. */\nexport function tokenOverlapScore(\n queryTokens: string[],\n textTokens: string[]\n): number {\n if (queryTokens.length === 0 || textTokens.length === 0) {\n return 0;\n }\n\n const stemmedText = new Set(textTokens.map(stemToken));\n let matchCount = 0;\n\n for (const queryToken of queryTokens) {\n const stemmedQuery = stemToken(queryToken);\n\n if (stemmedText.has(stemmedQuery)) {\n matchCount += 1;\n continue;\n }\n\n for (const textToken of stemmedText) {\n if (\n textToken.startsWith(stemmedQuery) ||\n stemmedQuery.startsWith(textToken)\n ) {\n matchCount += 0.5;\n break;\n }\n }\n }\n\n return matchCount / queryTokens.length;\n}\n\n/**\n * Extract character bigrams from text. Normalizes to lowercase, removes\n * non-alphanumeric characters, and generates overlapping pairs.\n */\nexport function bigramTokenize(text: string): Set<string> {\n const normalized = text.toLowerCase().replace(NON_ALPHANUMERIC_REGEX, \"\");\n const bigrams = new Set<string>();\n for (let i = 0; i < normalized.length - 1; i++) {\n bigrams.add(normalized.slice(i, i + 2));\n }\n return bigrams;\n}\n\n/**\n * Extract word-level tokens from text (for coarser matching).\n * Normalizes to lowercase, splits on non-alphanumeric.\n */\nexport function wordTokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(TOKEN_SPLIT_REGEX)\n .filter((token) => token.length > 1);\n}\n\n/** Jaccard similarity between two sets: |A ∩ B| / |A ∪ B|. */\nexport function jaccardSimilarity(\n setA: Set<string>,\n setB: Set<string>\n): number {\n if (setA.size === 0 && setB.size === 0) {\n return 0;\n }\n\n let intersectionSize = 0;\n const smaller = setA.size <= setB.size ? setA : setB;\n const larger = setA.size <= setB.size ? setB : setA;\n\n for (const item of smaller) {\n if (larger.has(item)) {\n intersectionSize++;\n }\n }\n\n const unionSize = setA.size + setB.size - intersectionSize;\n return unionSize === 0 ? 0 : intersectionSize / unionSize;\n}\n\n/** Exact word overlap score: fraction of type words found in input text. */\nexport function wordOverlapScore(\n inputWords: string[],\n typeWords: string[]\n): number {\n if (typeWords.length === 0) {\n return 0;\n }\n let matches = 0;\n for (const word of typeWords) {\n if (inputWords.includes(word)) {\n matches++;\n }\n }\n return matches / typeWords.length;\n}\n\n/** Pre-compute reusable lexical structures for a query. */\nexport function prepareLexicalQuery(query: string): PreparedLexicalQuery {\n return {\n raw: query,\n tokens: tokenizeSearchText(query),\n words: wordTokenize(query),\n bigrams: bigramTokenize(query),\n };\n}\n\n/** Score a single lexical signal against a prepared query. */\nexport function scoreLexicalSignal(\n query: PreparedLexicalQuery,\n signal: LexicalSignal\n): number {\n const text = signal.text?.trim();\n if (!text) {\n return 0;\n }\n\n switch (signal.strategy ?? \"tokenOverlap\") {\n case \"bigramJaccard\":\n return jaccardSimilarity(query.bigrams, bigramTokenize(text));\n case \"wordOverlap\":\n return wordOverlapScore(query.words, wordTokenize(text));\n default:\n return tokenOverlapScore(query.tokens, tokenizeSearchText(text));\n }\n}\n\n/** Weighted lexical score across multiple textual signals. */\nexport function scoreLexicalSignals(\n query: PreparedLexicalQuery,\n signals: LexicalSignal[]\n): number {\n let weightedScore = 0;\n let totalWeight = 0;\n\n for (const signal of signals) {\n if (!signal.text?.trim() || signal.weight <= 0) {\n continue;\n }\n weightedScore += scoreLexicalSignal(query, signal) * signal.weight;\n totalWeight += signal.weight;\n }\n\n return totalWeight === 0 ? 0 : weightedScore / totalWeight;\n}\n\n/** Map a candidate's original rank position into a 0..1 prior. */\nexport function rankWindowScore(index: number, total: number): number {\n if (total <= 1) {\n return 1;\n }\n const clampedIndex = Math.max(0, Math.min(index, total - 1));\n return 1 - clampedIndex / (total - 1);\n}\n\n/** Rerank a candidate window by lexical overlap while preserving original-rank prior. */\nexport function rerankLexicalWindow<T>(\n query: string,\n items: T[],\n getText: (item: T) => string | null | undefined,\n options?: LexicalRerankOptions\n): T[] {\n const preparedQuery = prepareLexicalQuery(query);\n if (preparedQuery.tokens.length === 0 || items.length <= 1) {\n return items;\n }\n\n const lexicalWeight = options?.lexicalWeight ?? 0.65;\n const rankWeight = options?.rankWeight ?? 0.35;\n\n return items\n .map((item, index) => {\n const lexicalScore = scoreLexicalSignals(preparedQuery, [\n { text: getText(item) ?? \"\", weight: 1, strategy: \"tokenOverlap\" },\n ]);\n const rankScore = rankWindowScore(index, items.length);\n\n return {\n item,\n combinedScore: lexicalScore * lexicalWeight + rankScore * rankWeight,\n };\n })\n .sort((left, right) => right.combinedScore - left.combinedScore)\n .map(({ item }) => item);\n}\n","/**\n * @lucern/contracts — OntologiesV1 namespace (resource contracts)\n *\n * Ontology Matching Engine — L0 entity type classification and similarity scoring.\n * Provides bigram-based text similarity for matching free text against\n * ontology entity types. Domain-agnostic: works identically for companies,\n * molecules, code modules, or any tenant-defined entity vocabulary.\n *\n * Moved from src/ontology-matching.contract.ts in EK-16 T1 PR 2.\n * Compat shim remains at the old path until the Lucern 1.0.0 cut.\n */\n\nimport {\n bigramTokenize,\n jaccardSimilarity,\n prepareLexicalQuery,\n scoreLexicalSignals,\n wordOverlapScore,\n wordTokenize,\n} from \"../../text-matching.contract\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** An entity type definition from a resolved ontology version. */\nexport type OntologyEntityType = {\n value: string;\n label: string;\n description?: string;\n subtypes?: Array<{ value: string; label: string; description?: string }>;\n};\n\n/** A scored match between input text and an entity type. */\nexport type EntityTypeMatch = {\n entityType: string;\n label: string;\n score: number;\n reason: string;\n};\n\n/** A candidate entity node that can be matched against a target node. */\nexport type EntityMatchCandidate = {\n nodeId: string;\n entityType: string;\n title: string;\n canonicalText: string;\n connectedBeliefCount: number;\n connectedEvidenceCount: number;\n};\n\n/** A scored entity match with suggested bridge edge type. */\nexport type EntityConnectionMatch = {\n entityNodeId: string;\n entityType: string;\n title: string;\n score: number;\n suggestedEdgeType: string;\n reason: string;\n};\n\n// =============================================================================\n// ENTITY TYPE SCORING\n// =============================================================================\n\n/** Weights for combining scoring signals. */\nconst MATCH_WEIGHTS = {\n tokenOverlap: 0.35,\n bigramSimilarity: 0.25,\n wordOverlap: 0.2,\n descriptionBonus: 0.2,\n} as const;\n\n/**\n * Score how well input text matches a single entity type definition.\n * Combines bigram Jaccard similarity, word overlap, and description matching.\n */\nexport function scoreEntityTypeMatch(\n inputText: string,\n entityType: OntologyEntityType\n): EntityTypeMatch {\n const preparedQuery = prepareLexicalQuery(inputText);\n const labelText = `${entityType.label} ${entityType.value}`;\n\n const tokenScore = scoreLexicalSignals(preparedQuery, [\n { text: labelText, weight: 1, strategy: \"tokenOverlap\" },\n ]);\n\n // Score against the type label (primary signal)\n const labelBigrams = bigramTokenize(entityType.label);\n const bigramScore = jaccardSimilarity(preparedQuery.bigrams, labelBigrams);\n\n // Word overlap with label + value\n const labelWords = wordTokenize(labelText);\n const wordScore = wordOverlapScore(preparedQuery.words, labelWords);\n\n // Description matching bonus (if description exists)\n let descScore = 0;\n if (entityType.description) {\n descScore = scoreLexicalSignals(preparedQuery, [\n { text: entityType.description, weight: 1, strategy: \"tokenOverlap\" },\n ]);\n }\n\n // Check subtypes for additional matches\n let subtypeBonus = 0;\n if (entityType.subtypes && entityType.subtypes.length > 0) {\n for (const subtype of entityType.subtypes) {\n const subtypeScore = scoreLexicalSignals(preparedQuery, [\n {\n text: `${subtype.label} ${subtype.value} ${subtype.description || \"\"}`,\n weight: 1,\n strategy: \"tokenOverlap\",\n },\n ]);\n subtypeBonus = Math.max(subtypeBonus, subtypeScore * 0.3); // up to 30% subtype bonus\n }\n }\n\n const score = Math.min(\n 1.0,\n tokenScore * MATCH_WEIGHTS.tokenOverlap +\n bigramScore * MATCH_WEIGHTS.bigramSimilarity +\n wordScore * MATCH_WEIGHTS.wordOverlap +\n descScore * MATCH_WEIGHTS.descriptionBonus +\n subtypeBonus\n );\n\n // Generate human-readable reason\n const reasons: string[] = [];\n if (tokenScore > 0.3) {\n reasons.push(`stem match: ${(tokenScore * 100).toFixed(0)}%`);\n }\n if (bigramScore > 0.3) {\n reasons.push(`text similarity: ${(bigramScore * 100).toFixed(0)}%`);\n }\n if (wordScore > 0.3) {\n reasons.push(`word match: ${(wordScore * 100).toFixed(0)}%`);\n }\n if (descScore > 0.2) {\n reasons.push(\"description match\");\n }\n if (subtypeBonus > 0.05) {\n reasons.push(\"subtype match\");\n }\n const reason = reasons.length > 0 ? reasons.join(\", \") : \"low similarity\";\n\n return {\n entityType: entityType.value,\n label: entityType.label,\n score,\n reason,\n };\n}\n\n/**\n * Rank all entity types in an ontology against input text.\n * Returns matches sorted by score (descending), filtered to score > minScore.\n */\nexport function rankEntityTypeMatches(\n inputText: string,\n entityTypes: OntologyEntityType[],\n options?: { minScore?: number; limit?: number }\n): EntityTypeMatch[] {\n const minScore = options?.minScore ?? 0.05;\n const limit = options?.limit ?? 10;\n\n const matches = entityTypes\n .map((et) => scoreEntityTypeMatch(inputText, et))\n .filter((m) => m.score >= minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n\n return matches;\n}\n\n// =============================================================================\n// ENTITY DISCOVERY SCORING\n// =============================================================================\n\n/**\n * Score how well a node's text matches an entity candidate.\n * Used by discover_entity_connections to suggest missing bridge edges.\n */\nexport function scoreEntityConnection(\n nodeText: string,\n candidate: EntityMatchCandidate,\n options?: { connectivityWeight?: number }\n): EntityConnectionMatch {\n const preparedQuery = prepareLexicalQuery(nodeText);\n const connectivityWeight = options?.connectivityWeight ?? 0.3;\n const textWeight = 1.0 - connectivityWeight;\n const candidateText = `${candidate.title} ${candidate.canonicalText}`;\n const tokenScore = scoreLexicalSignals(preparedQuery, [\n { text: candidateText, weight: 1, strategy: \"tokenOverlap\" },\n ]);\n const textScore = scoreLexicalSignals(preparedQuery, [\n { text: candidateText, weight: 1, strategy: \"bigramJaccard\" },\n ]);\n const wordScore = scoreLexicalSignals(preparedQuery, [\n { text: candidateText, weight: 1, strategy: \"wordOverlap\" },\n ]);\n\n // Connectivity signal (normalized externally by caller)\n const maxConnections = Math.max(\n 1,\n candidate.connectedBeliefCount + candidate.connectedEvidenceCount\n );\n const connectivityScore = Math.min(1.0, maxConnections / 10); // soft-cap at 10\n\n const combinedTextScore =\n tokenScore * 0.45 + textScore * 0.35 + wordScore * 0.2;\n const score =\n combinedTextScore * textWeight + connectivityScore * connectivityWeight;\n\n // Suggest edge type based on entity type\n const suggestedEdgeType = suggestEdgeType(candidate.entityType);\n\n const reason =\n tokenScore > 0.3\n ? `stem match: ${(tokenScore * 100).toFixed(0)}%`\n : textScore > 0.2\n ? `name similarity: ${(textScore * 100).toFixed(0)}%`\n : wordScore > 0.2\n ? `keyword match: ${(wordScore * 100).toFixed(0)}%`\n : `connectivity: ${candidate.connectedBeliefCount} beliefs`;\n\n return {\n entityNodeId: candidate.nodeId,\n entityType: candidate.entityType,\n title: candidate.title,\n score,\n suggestedEdgeType,\n reason,\n };\n}\n\n/**\n * Suggest the most appropriate bridge edge type for an entity type.\n */\nfunction suggestEdgeType(entityType: string): string {\n switch (entityType) {\n case \"company\":\n case \"person\":\n case \"investor\":\n return \"contains\";\n case \"function\":\n case \"value_chain\":\n return \"impacts\";\n default:\n return \"contains\";\n }\n}\n\n/**\n * Rank entity candidates against a node's text.\n * Returns sorted matches above the minimum score threshold.\n */\nexport function rankEntityConnections(\n nodeText: string,\n candidates: EntityMatchCandidate[],\n options?: { minScore?: number; limit?: number; connectivityWeight?: number }\n): EntityConnectionMatch[] {\n const minScore = options?.minScore ?? 0.05;\n const limit = options?.limit ?? 10;\n\n return candidates\n .map((c) =>\n scoreEntityConnection(nodeText, c, {\n connectivityWeight: options?.connectivityWeight,\n })\n )\n .filter((m) => m.score >= minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
declare const getPendingForProject: any;
|
|
2
|
+
declare const getPendingForNode: any;
|
|
3
|
+
declare const getThemeOntologyMatches: any;
|
|
4
|
+
declare const createPendingLink: any;
|
|
5
|
+
declare const approve: any;
|
|
6
|
+
declare const reject: any;
|
|
7
|
+
declare const bulkApprove: any;
|
|
8
|
+
declare const bulkApproveHighConfidence: any;
|
|
9
|
+
declare const createNeo4jEdge: any;
|
|
10
|
+
declare const batchCreatePendingLinks: any;
|
|
11
|
+
|
|
12
|
+
declare const ontologyApproval_approve: typeof approve;
|
|
13
|
+
declare const ontologyApproval_batchCreatePendingLinks: typeof batchCreatePendingLinks;
|
|
14
|
+
declare const ontologyApproval_bulkApprove: typeof bulkApprove;
|
|
15
|
+
declare const ontologyApproval_bulkApproveHighConfidence: typeof bulkApproveHighConfidence;
|
|
16
|
+
declare const ontologyApproval_createNeo4jEdge: typeof createNeo4jEdge;
|
|
17
|
+
declare const ontologyApproval_createPendingLink: typeof createPendingLink;
|
|
18
|
+
declare const ontologyApproval_getPendingForNode: typeof getPendingForNode;
|
|
19
|
+
declare const ontologyApproval_getPendingForProject: typeof getPendingForProject;
|
|
20
|
+
declare const ontologyApproval_getThemeOntologyMatches: typeof getThemeOntologyMatches;
|
|
21
|
+
declare const ontologyApproval_reject: typeof reject;
|
|
22
|
+
declare namespace ontologyApproval {
|
|
23
|
+
export { ontologyApproval_approve as approve, ontologyApproval_batchCreatePendingLinks as batchCreatePendingLinks, ontologyApproval_bulkApprove as bulkApprove, ontologyApproval_bulkApproveHighConfidence as bulkApproveHighConfidence, ontologyApproval_createNeo4jEdge as createNeo4jEdge, ontologyApproval_createPendingLink as createPendingLink, ontologyApproval_getPendingForNode as getPendingForNode, ontologyApproval_getPendingForProject as getPendingForProject, ontologyApproval_getThemeOntologyMatches as getThemeOntologyMatches, ontologyApproval_reject as reject };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { getPendingForNode as a, getThemeOntologyMatches as b, createPendingLink as c, approve as d, bulkApprove as e, bulkApproveHighConfidence as f, getPendingForProject as g, createNeo4jEdge as h, batchCreatePendingLinks as i, ontologyApproval as o, reject as r };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { d as approve, i as batchCreatePendingLinks, e as bulkApprove, f as bulkApproveHighConfidence, h as createNeo4jEdge, c as createPendingLink, a as getPendingForNode, g as getPendingForProject, b as getThemeOntologyMatches, r as reject } from './ontologyApproval-Ba0Jjk1k.js';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { v } from 'convex/values';
|
|
2
|
+
import { componentsGeneric, queryGeneric, mutationGeneric, internalMutationGeneric } from 'convex/server';
|
|
3
|
+
|
|
4
|
+
// src/ontologyApproval.ts
|
|
5
|
+
componentsGeneric();
|
|
6
|
+
var internalMutation = internalMutationGeneric;
|
|
7
|
+
var mutation = mutationGeneric;
|
|
8
|
+
var query = queryGeneric;
|
|
9
|
+
var permissiveReturn = v.optional(v.any());
|
|
10
|
+
var looseJsonObject = v.record(v.string(), v.any());
|
|
11
|
+
var looseJsonArray = v.array(v.any());
|
|
12
|
+
v.union(
|
|
13
|
+
v.string(),
|
|
14
|
+
v.number(),
|
|
15
|
+
v.boolean(),
|
|
16
|
+
v.null(),
|
|
17
|
+
looseJsonObject,
|
|
18
|
+
looseJsonArray
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// src/ontologyApproval.ts
|
|
22
|
+
var getPendingForProject = query({
|
|
23
|
+
args: v.any(),
|
|
24
|
+
returns: permissiveReturn,
|
|
25
|
+
handler: async () => ({ total: 0, bySource: [] })
|
|
26
|
+
});
|
|
27
|
+
var getPendingForNode = query({
|
|
28
|
+
args: v.any(),
|
|
29
|
+
returns: permissiveReturn,
|
|
30
|
+
handler: async () => []
|
|
31
|
+
});
|
|
32
|
+
var getThemeOntologyMatches = query({
|
|
33
|
+
args: v.any(),
|
|
34
|
+
returns: permissiveReturn,
|
|
35
|
+
handler: async () => []
|
|
36
|
+
});
|
|
37
|
+
var createPendingLink = mutation({
|
|
38
|
+
args: v.any(),
|
|
39
|
+
returns: permissiveReturn,
|
|
40
|
+
handler: async () => null
|
|
41
|
+
});
|
|
42
|
+
var approve = mutation({
|
|
43
|
+
args: v.any(),
|
|
44
|
+
returns: permissiveReturn,
|
|
45
|
+
handler: async () => ({ success: true })
|
|
46
|
+
});
|
|
47
|
+
var reject = mutation({
|
|
48
|
+
args: v.any(),
|
|
49
|
+
returns: permissiveReturn,
|
|
50
|
+
handler: async () => ({ success: true })
|
|
51
|
+
});
|
|
52
|
+
var bulkApprove = mutation({
|
|
53
|
+
args: v.any(),
|
|
54
|
+
returns: permissiveReturn,
|
|
55
|
+
handler: async (ctx, args) => ({
|
|
56
|
+
approved: 0,
|
|
57
|
+
total: Array.isArray(args.linkIds) ? args.linkIds.length : 0
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
var bulkApproveHighConfidence = mutation({
|
|
61
|
+
args: v.any(),
|
|
62
|
+
returns: permissiveReturn,
|
|
63
|
+
handler: async () => ({ approved: 0 })
|
|
64
|
+
});
|
|
65
|
+
var createNeo4jEdge = internalMutation({
|
|
66
|
+
args: v.any(),
|
|
67
|
+
returns: permissiveReturn,
|
|
68
|
+
handler: async () => ({ success: true })
|
|
69
|
+
});
|
|
70
|
+
var batchCreatePendingLinks = internalMutation({
|
|
71
|
+
args: v.any(),
|
|
72
|
+
returns: permissiveReturn,
|
|
73
|
+
handler: async () => ({ created: 0, autoApproved: 0 })
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export { approve, batchCreatePendingLinks, bulkApprove, bulkApproveHighConfidence, createNeo4jEdge, createPendingLink, getPendingForNode, getPendingForProject, getThemeOntologyMatches, reject };
|
|
77
|
+
//# sourceMappingURL=ontologyApproval.js.map
|
|
78
|
+
//# sourceMappingURL=ontologyApproval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/convex.ts","../../schema-management/src/validators.ts","../src/ontologyApproval.ts"],"names":["v"],"mappings":"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","file":"ontologyApproval.js","sourcesContent":["import {\n actionGeneric,\n anyApi,\n componentsGeneric,\n httpActionGeneric,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n mutationGeneric,\n queryGeneric,\n} from \"convex/server\";\nimport type { GenericId } from \"convex/values\";\n\nexport const api = anyApi as any;\nexport const components = componentsGeneric() as any;\nexport const internal = anyApi as any;\n\nexport type TableNames = string;\nexport type Id<TableName extends TableNames = string> = GenericId<TableName>;\nexport type Doc<TableName extends TableNames = string> = any;\nexport type DataModel = any;\nexport type ActionCtx = any;\nexport type DatabaseReader = any;\nexport type DatabaseWriter = any;\nexport type MutationCtx = any;\nexport type QueryCtx = any;\n\nexport const action = actionGeneric as any;\nexport const httpAction = httpActionGeneric as any;\nexport const internalAction = internalActionGeneric as any;\nexport const internalMutation = internalMutationGeneric as any;\nexport const internalQuery = internalQueryGeneric as any;\nexport const mutation = mutationGeneric as any;\nexport const query = queryGeneric as any;\n","/**\n * validators module implementation.\n */\n\nimport { v } from \"convex/values\";\n\n/**\n * Permissive return validator used while contracts are tightened.\n */\nexport const permissiveReturn: any = v.optional(v.any());\n\n/**\n * Shallow JSON validators for dynamic payloads.\n */\nexport const looseJsonObject = v.record(v.string(), v.any());\nexport const looseJsonArray = v.array(v.any());\nexport const looseJsonValue = v.union(\n v.string(),\n v.number(),\n v.boolean(),\n v.null(),\n looseJsonObject,\n looseJsonArray\n);\n","// DORMANT: Ontology approval UI stubbed in EK-16.1c. Re-enable when approval workflow ships.\n\nimport { v } from \"convex/values\";\nimport { internalMutation, mutation, query } from \"./convex\";\nimport { permissiveReturn } from \"@lucern/schema-management/validators\";\n\nexport const getPendingForProject = query({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ total: 0, bySource: [] }),\n});\n\nexport const getPendingForNode = query({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => [],\n});\n\nexport const getThemeOntologyMatches = query({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => [],\n});\n\nexport const createPendingLink = mutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => null,\n});\n\nexport const approve = mutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ success: true }),\n});\n\nexport const reject = mutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ success: true }),\n});\n\nexport const bulkApprove = mutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async (ctx, args) => ({\n approved: 0,\n total: Array.isArray((args as { linkIds?: unknown[] }).linkIds)\n ? (args as { linkIds: unknown[] }).linkIds.length\n : 0,\n }),\n});\n\nexport const bulkApproveHighConfidence = mutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ approved: 0 }),\n});\n\nexport const createNeo4jEdge = internalMutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ success: true }),\n});\n\nexport const batchCreatePendingLinks = internalMutation({\n args: v.any(),\n returns: permissiveReturn,\n handler: async () => ({ created: 0, autoApproved: 0 }),\n});\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ontology Definition Mutations & Queries
|
|
3
|
+
*
|
|
4
|
+
* CRUD operations for first-class ontology definition objects.
|
|
5
|
+
* Follows the packDefinitions + packVersions two-table pattern from Master Control.
|
|
6
|
+
*
|
|
7
|
+
* Pure helper functions live in ontologyHelpers.ts for unit testing.
|
|
8
|
+
*
|
|
9
|
+
* @module graph-primitives/ontologyDefinitions
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Get an ontology definition by ID.
|
|
13
|
+
*/
|
|
14
|
+
declare const getOntologyDefinition: any;
|
|
15
|
+
/**
|
|
16
|
+
* Get an ontology definition by ontologyKey (optionally scoped by tenant).
|
|
17
|
+
*/
|
|
18
|
+
declare const getOntologyDefinitionByKey: any;
|
|
19
|
+
/**
|
|
20
|
+
* List ontology definitions with optional filters.
|
|
21
|
+
*/
|
|
22
|
+
declare const listOntologyDefinitions: any;
|
|
23
|
+
/**
|
|
24
|
+
* Get a specific version by ontologyId + version string.
|
|
25
|
+
*/
|
|
26
|
+
declare const getOntologyVersion: any;
|
|
27
|
+
/**
|
|
28
|
+
* List versions for an ontology, optionally filtered by status.
|
|
29
|
+
*/
|
|
30
|
+
declare const listOntologyVersions: any;
|
|
31
|
+
/**
|
|
32
|
+
* Get the latest published version for an ontology.
|
|
33
|
+
*/
|
|
34
|
+
declare const getPublishedVersion: any;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the effective ontology by composing parent chain.
|
|
37
|
+
* Walks parentOntologyId chain (max depth 3) and merges additively.
|
|
38
|
+
*/
|
|
39
|
+
declare const resolveEffectiveOntology: any;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new ontology definition.
|
|
42
|
+
*/
|
|
43
|
+
declare const createOntologyDefinition: any;
|
|
44
|
+
/**
|
|
45
|
+
* Update an ontology definition (name, description, status).
|
|
46
|
+
* Only allowed while draft or active.
|
|
47
|
+
*/
|
|
48
|
+
declare const updateOntologyDefinition: any;
|
|
49
|
+
/**
|
|
50
|
+
* Archive an ontology definition.
|
|
51
|
+
*/
|
|
52
|
+
declare const archiveOntologyDefinition: any;
|
|
53
|
+
/**
|
|
54
|
+
* Create a new version snapshot for an ontology.
|
|
55
|
+
*/
|
|
56
|
+
declare const createOntologyVersion: any;
|
|
57
|
+
/**
|
|
58
|
+
* Update a draft version (entityTypes, edgeTypes, releaseNotes).
|
|
59
|
+
* Only allowed while version is in "draft" status.
|
|
60
|
+
*/
|
|
61
|
+
declare const updateDraftVersion: any;
|
|
62
|
+
/**
|
|
63
|
+
* Publish a version — freezes it (status → "published").
|
|
64
|
+
* If the parent definition is "draft", promotes it to "active".
|
|
65
|
+
*/
|
|
66
|
+
declare const publishOntologyVersion: any;
|
|
67
|
+
/**
|
|
68
|
+
* Deprecate a published version.
|
|
69
|
+
*/
|
|
70
|
+
declare const deprecateOntologyVersion: any;
|
|
71
|
+
|
|
72
|
+
export { archiveOntologyDefinition, createOntologyDefinition, createOntologyVersion, deprecateOntologyVersion, getOntologyDefinition, getOntologyDefinitionByKey, getOntologyVersion, getPublishedVersion, listOntologyDefinitions, listOntologyVersions, publishOntologyVersion, resolveEffectiveOntology, updateDraftVersion, updateOntologyDefinition };
|