@lucern/graph-primitives 1.0.0 → 1.0.1
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 +13 -12
- package/dist/beliefDecay.js +24 -17
- package/dist/beliefDecay.js.map +1 -1
- package/dist/beliefEvidenceLinks.js +32 -8
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/confidencePropagationDispatch.js.map +1 -1
- package/dist/contradictions.js +32 -9
- package/dist/contradictions.js.map +1 -1
- package/dist/convex.d.ts +55 -12
- package/dist/convex.js.map +1 -1
- package/dist/edgeValidation.d.ts +25 -2
- package/dist/edges/index.d.ts +9 -2
- package/dist/edges/index.js.map +1 -1
- package/dist/edges/propagationTypes.d.ts +2 -3
- package/dist/edges/propagationTypes.js.map +1 -1
- package/dist/entityBridge.js +10 -3
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityLifecycle.js +15 -3
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.d.ts +36 -0
- package/dist/epistemicBeliefs.admin.js +745 -0
- package/dist/epistemicBeliefs.admin.js.map +1 -0
- package/dist/epistemicBeliefs.backfills.d.ts +62 -0
- package/dist/epistemicBeliefs.backfills.js +1004 -0
- package/dist/epistemicBeliefs.backfills.js.map +1 -0
- package/dist/epistemicBeliefs.confidence.d.ts +45 -0
- package/dist/epistemicBeliefs.confidence.js +1285 -0
- package/dist/epistemicBeliefs.confidence.js.map +1 -0
- package/dist/epistemicBeliefs.core.d.ts +35 -0
- package/dist/epistemicBeliefs.core.js +1508 -0
- package/dist/epistemicBeliefs.core.js.map +1 -0
- package/dist/epistemicBeliefs.d.ts +12 -3
- package/dist/epistemicBeliefs.helpers.d.ts +168 -0
- package/dist/epistemicBeliefs.helpers.js +1060 -0
- package/dist/epistemicBeliefs.helpers.js.map +1 -0
- package/dist/epistemicBeliefs.internal.d.ts +30 -0
- package/dist/epistemicBeliefs.internal.js +1329 -0
- package/dist/epistemicBeliefs.internal.js.map +1 -0
- package/dist/epistemicBeliefs.js +1196 -1184
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +19 -0
- package/dist/epistemicBeliefs.lifecycle.js +1608 -0
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -0
- package/dist/epistemicBeliefs.links.d.ts +30 -0
- package/dist/epistemicBeliefs.links.js +761 -0
- package/dist/epistemicBeliefs.links.js.map +1 -0
- package/dist/epistemicBeliefs.queries.d.ts +16 -0
- package/dist/epistemicBeliefs.queries.js +90 -0
- package/dist/epistemicBeliefs.queries.js.map +1 -0
- package/dist/epistemicContractHelpers.d.ts +1 -1
- package/dist/epistemicContractHelpers.js +1 -1
- package/dist/epistemicContracts.d.ts +5 -76
- package/dist/epistemicContracts.evaluators.d.ts +36 -0
- package/dist/epistemicContracts.evaluators.js +2506 -0
- package/dist/epistemicContracts.evaluators.js.map +1 -0
- package/dist/epistemicContracts.handlers.d.ts +40 -0
- package/dist/epistemicContracts.handlers.js +3029 -0
- package/dist/epistemicContracts.handlers.js.map +1 -0
- package/dist/epistemicContracts.js +2006 -5281
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.d.ts +26 -0
- package/dist/epistemicContracts.metrics.js +427 -0
- package/dist/epistemicContracts.metrics.js.map +1 -0
- package/dist/epistemicContracts.types.d.ts +159 -0
- package/dist/epistemicContracts.types.js +3 -0
- package/dist/epistemicContracts.types.js.map +1 -0
- package/dist/epistemicEdgeCreation.d.ts +73 -0
- package/dist/epistemicEdgeCreation.js +450 -0
- package/dist/epistemicEdgeCreation.js.map +1 -0
- package/dist/epistemicEdges-BF-cn4i3.d.ts +43 -0
- package/dist/epistemicEdges.d.ts +8 -1
- package/dist/epistemicEdges.handlers.d.ts +20 -0
- package/dist/epistemicEdges.handlers.js +289 -0
- package/dist/epistemicEdges.handlers.js.map +1 -0
- package/dist/epistemicEdges.helpers.d.ts +27 -0
- package/dist/epistemicEdges.helpers.js +162 -0
- package/dist/epistemicEdges.helpers.js.map +1 -0
- package/dist/epistemicEdges.js +797 -875
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +39 -0
- package/dist/epistemicEdges.mutations.js +1365 -0
- package/dist/epistemicEdges.mutations.js.map +1 -0
- package/dist/epistemicEdges.queries.d.ts +95 -0
- package/dist/epistemicEdges.queries.js +851 -0
- package/dist/epistemicEdges.queries.js.map +1 -0
- package/dist/epistemicEdges.types.d.ts +32 -0
- package/dist/epistemicEdges.types.js +3 -0
- package/dist/epistemicEdges.types.js.map +1 -0
- package/dist/epistemicEvidence-DvfchNt7.d.ts +46 -0
- package/dist/epistemicEvidence.d.ts +5 -2
- package/dist/epistemicEvidence.js +801 -807
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +71 -0
- package/dist/epistemicEvidenceHelpers.js +769 -0
- package/dist/epistemicEvidenceHelpers.js.map +1 -0
- package/dist/epistemicEvidenceMutations.d.ts +10 -0
- package/dist/epistemicEvidenceMutations.js +1421 -0
- package/dist/epistemicEvidenceMutations.js.map +1 -0
- package/dist/epistemicEvidenceQueries.d.ts +10 -0
- package/dist/epistemicEvidenceQueries.js +1049 -0
- package/dist/epistemicEvidenceQueries.js.map +1 -0
- package/dist/epistemicHelpers.d.ts +4 -2
- package/dist/epistemicHelpers.js +132 -127
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicLayerRules.d.ts +138 -0
- package/dist/epistemicLayerRules.js +481 -0
- package/dist/epistemicLayerRules.js.map +1 -0
- package/dist/epistemicLinking.js +1 -1
- package/dist/epistemicLinking.js.map +1 -1
- package/dist/epistemicNodeCreation.d.ts +101 -0
- package/dist/epistemicNodeCreation.js +709 -0
- package/dist/epistemicNodeCreation.js.map +1 -0
- package/dist/epistemicNodes-BCQxpYx_.d.ts +54 -0
- package/dist/epistemicNodes.d.ts +5 -1
- package/dist/epistemicNodes.helpers.d.ts +51 -0
- package/dist/epistemicNodes.helpers.js +73 -0
- package/dist/epistemicNodes.helpers.js.map +1 -0
- package/dist/epistemicNodes.internal.d.ts +34 -0
- package/dist/epistemicNodes.internal.js +658 -0
- package/dist/epistemicNodes.internal.js.map +1 -0
- package/dist/epistemicNodes.js +698 -693
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +34 -0
- package/dist/epistemicNodes.mutations.js +1153 -0
- package/dist/epistemicNodes.mutations.js.map +1 -0
- package/dist/epistemicNodes.queries.d.ts +36 -0
- package/dist/epistemicNodes.queries.js +619 -0
- package/dist/epistemicNodes.queries.js.map +1 -0
- package/dist/epistemicNodes.validators.d.ts +23 -0
- package/dist/epistemicNodes.validators.js +105 -0
- package/dist/epistemicNodes.validators.js.map +1 -0
- package/dist/epistemicQuestions-bwHd2FWE.d.ts +68 -0
- package/dist/epistemicQuestions.conviction.d.ts +52 -0
- package/dist/epistemicQuestions.conviction.js +1389 -0
- package/dist/epistemicQuestions.conviction.js.map +1 -0
- package/dist/epistemicQuestions.create.d.ts +29 -0
- package/dist/epistemicQuestions.create.js +1300 -0
- package/dist/epistemicQuestions.create.js.map +1 -0
- package/dist/epistemicQuestions.d.ts +10 -2
- package/dist/epistemicQuestions.evidence.d.ts +22 -0
- package/dist/epistemicQuestions.evidence.js +929 -0
- package/dist/epistemicQuestions.evidence.js.map +1 -0
- package/dist/epistemicQuestions.helpers.d.ts +69 -0
- package/dist/epistemicQuestions.helpers.js +824 -0
- package/dist/epistemicQuestions.helpers.js.map +1 -0
- package/dist/epistemicQuestions.js +2435 -2430
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.d.ts +24 -0
- package/dist/epistemicQuestions.lifecycle.js +838 -0
- package/dist/epistemicQuestions.lifecycle.js.map +1 -0
- package/dist/epistemicQuestions.queries.d.ts +41 -0
- package/dist/epistemicQuestions.queries.js +1013 -0
- package/dist/epistemicQuestions.queries.js.map +1 -0
- package/dist/epistemicQuestions.sprint.d.ts +22 -0
- package/dist/epistemicQuestions.sprint.js +757 -0
- package/dist/epistemicQuestions.sprint.js.map +1 -0
- package/dist/epistemicQuestions.tail.d.ts +42 -0
- package/dist/epistemicQuestions.tail.js +1345 -0
- package/dist/epistemicQuestions.tail.js.map +1 -0
- package/dist/epistemicSources.js +6 -2
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.d.ts +2 -2
- package/dist/evaluators/index.js +45 -5320
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/lintCheckerEvaluator.d.ts +1 -1
- package/dist/evaluators/sentryCheckerEvaluator.d.ts +1 -1
- package/dist/evaluators/testRunnerEvaluator.d.ts +1 -1
- package/dist/evaluators/tscCheckerEvaluator.d.ts +1 -1
- package/dist/{graphTypes-CpgIuCdo.d.ts → graphTypes-B8VaIjnl.d.ts} +1 -1
- package/dist/graphTypes.d.ts +1 -1
- package/dist/{helpers-BYHIk5vU.d.ts → helpers-DNYfg6mo.d.ts} +2 -3
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/{index-Dq-7R-gi.d.ts → index-C-Kyd7hD.d.ts} +1 -1
- package/dist/index.d.ts +160 -14
- package/dist/index.js +12291 -13001
- package/dist/index.js.map +1 -1
- package/dist/logicalRoleInference.js.map +1 -1
- package/dist/ontologyApproval.js +1 -1
- package/dist/ontologyApproval.js.map +1 -1
- package/dist/ontologyDefinitions.js +25 -7
- package/dist/ontologyDefinitions.js.map +1 -1
- package/dist/ontologyRegistry.js.map +1 -1
- package/dist/projectionReconciliation.js.map +1 -1
- package/dist/questionEvidenceLinks.js +28 -7
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/resolvers.js.map +1 -1
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/topicProjectOverlay.js.map +1 -1
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -5
- package/dist/edgeValidation-CeI0wc0r.d.ts +0 -35
- package/dist/epistemicBeliefs-DzKjZAeC.d.ts +0 -377
- package/dist/epistemicEdges-CvlKnEyy.d.ts +0 -191
- package/dist/epistemicEvidence-xw6UUrwh.d.ts +0 -128
- package/dist/epistemicHelpers-DevrYgPN.d.ts +0 -329
- package/dist/epistemicNodes-DjSUfvyD.d.ts +0 -167
- package/dist/epistemicQuestions-B_nUclrH.d.ts +0 -214
- package/dist/index-Dct1T70K.d.ts +0 -25
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
import { v } from 'convex/values';
|
|
2
|
+
import { checkScopeAccess } from '@lucern/access-control/access';
|
|
3
|
+
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
4
|
+
import { componentsGeneric, queryGeneric, anyApi } from 'convex/server';
|
|
5
|
+
|
|
6
|
+
// src/epistemicNodes.queries.ts
|
|
7
|
+
var api = anyApi;
|
|
8
|
+
componentsGeneric();
|
|
9
|
+
var query = queryGeneric;
|
|
10
|
+
|
|
11
|
+
// src/debug.ts
|
|
12
|
+
function isGraphPrimitiveDebugEnabled() {
|
|
13
|
+
const env = globalThis.process?.env;
|
|
14
|
+
return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
|
|
15
|
+
}
|
|
16
|
+
function debugGraphPrimitiveFallback(message, context) {
|
|
17
|
+
if (!isGraphPrimitiveDebugEnabled()) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.debug(message, context ?? {});
|
|
21
|
+
}
|
|
22
|
+
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
23
|
+
function asMappedProjectId(topic) {
|
|
24
|
+
if (!topic) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
|
|
28
|
+
if (directLegacyProjectId) {
|
|
29
|
+
return directLegacyProjectId;
|
|
30
|
+
}
|
|
31
|
+
const metadata = topic.metadata || {};
|
|
32
|
+
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
33
|
+
return candidate ? candidate : void 0;
|
|
34
|
+
}
|
|
35
|
+
function normalizeScopeValue(value) {
|
|
36
|
+
if (typeof value !== "string") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const normalized = value.trim();
|
|
40
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
41
|
+
}
|
|
42
|
+
function pickPrimaryTopic(candidates) {
|
|
43
|
+
return [...candidates].sort((a, b) => {
|
|
44
|
+
const depthA = a.depth ?? 9999;
|
|
45
|
+
const depthB = b.depth ?? 9999;
|
|
46
|
+
if (depthA !== depthB) {
|
|
47
|
+
return depthA - depthB;
|
|
48
|
+
}
|
|
49
|
+
const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
50
|
+
const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
51
|
+
if (createdA !== createdB) {
|
|
52
|
+
return createdA - createdB;
|
|
53
|
+
}
|
|
54
|
+
return String(a.name || "").localeCompare(String(b.name || ""));
|
|
55
|
+
})[0];
|
|
56
|
+
}
|
|
57
|
+
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
58
|
+
try {
|
|
59
|
+
return await ctx.db.query("topics").withIndex(
|
|
60
|
+
"by_graph_scope_project",
|
|
61
|
+
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
62
|
+
).collect();
|
|
63
|
+
} catch (error) {
|
|
64
|
+
debugGraphPrimitiveFallback(
|
|
65
|
+
"[topicScope] Failed to resolve scope alias via index",
|
|
66
|
+
{
|
|
67
|
+
error,
|
|
68
|
+
scopeId
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
const topics = await ctx.db.query("topics").collect();
|
|
72
|
+
return topics.filter((topic) => {
|
|
73
|
+
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
74
|
+
const mappedProjectId = asMappedProjectId(topic);
|
|
75
|
+
return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function tryResolveHostTopicById(ctx, topicId) {
|
|
80
|
+
if (typeof ctx.runQuery !== "function") {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
return await ctx.runQuery(api.topics.get, {
|
|
85
|
+
id: topicId
|
|
86
|
+
}) ?? null;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
debugGraphPrimitiveFallback(
|
|
89
|
+
"[topicScope] Failed to resolve topic by host query",
|
|
90
|
+
{
|
|
91
|
+
error,
|
|
92
|
+
topicId
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
|
|
99
|
+
if (typeof ctx.runQuery !== "function") {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
return await ctx.runQuery(api.topics.getByLegacyScopeId, {
|
|
104
|
+
projectId: legacyScopeId
|
|
105
|
+
}) ?? null;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
debugGraphPrimitiveFallback(
|
|
108
|
+
"[topicScope] Failed to resolve topic by legacy scope",
|
|
109
|
+
{
|
|
110
|
+
error,
|
|
111
|
+
legacyScopeId
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
118
|
+
const MAX_DEPTH = 10;
|
|
119
|
+
let tenantId = normalizeScopeValue(topic.tenantId);
|
|
120
|
+
let workspaceId = normalizeScopeValue(topic.workspaceId);
|
|
121
|
+
if (tenantId && workspaceId) {
|
|
122
|
+
return { tenantId, workspaceId };
|
|
123
|
+
}
|
|
124
|
+
let current = topic;
|
|
125
|
+
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
126
|
+
current = await ctx.db.get(current.parentTopicId);
|
|
127
|
+
if (!current) break;
|
|
128
|
+
if (!tenantId) {
|
|
129
|
+
tenantId = normalizeScopeValue(current.tenantId);
|
|
130
|
+
}
|
|
131
|
+
if (!workspaceId) {
|
|
132
|
+
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
133
|
+
}
|
|
134
|
+
if (tenantId && workspaceId) break;
|
|
135
|
+
}
|
|
136
|
+
return { tenantId, workspaceId };
|
|
137
|
+
}
|
|
138
|
+
async function resolveTopicProjectScope(ctx, args) {
|
|
139
|
+
if (args.topicId) {
|
|
140
|
+
let topic = null;
|
|
141
|
+
try {
|
|
142
|
+
topic = await ctx.db.get(
|
|
143
|
+
args.topicId
|
|
144
|
+
);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
debugGraphPrimitiveFallback(
|
|
147
|
+
"[topicScope] Failed to load topic by direct id",
|
|
148
|
+
{
|
|
149
|
+
error,
|
|
150
|
+
topicId: args.topicId
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (!topic) {
|
|
155
|
+
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
156
|
+
}
|
|
157
|
+
if (!topic) {
|
|
158
|
+
topic = pickPrimaryTopic(
|
|
159
|
+
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
160
|
+
) ?? null;
|
|
161
|
+
}
|
|
162
|
+
if (!topic) {
|
|
163
|
+
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
164
|
+
}
|
|
165
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
166
|
+
const mapped = asMappedProjectId(topic);
|
|
167
|
+
if (mapped) {
|
|
168
|
+
return {
|
|
169
|
+
topicId: topic._id,
|
|
170
|
+
projectId: mapped,
|
|
171
|
+
tenantId: inherited.tenantId,
|
|
172
|
+
workspaceId: inherited.workspaceId,
|
|
173
|
+
source: "topic"
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
topicId: topic._id,
|
|
178
|
+
tenantId: inherited.tenantId,
|
|
179
|
+
workspaceId: inherited.workspaceId,
|
|
180
|
+
source: "topic"
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (args.projectId) {
|
|
184
|
+
let directTopic = null;
|
|
185
|
+
try {
|
|
186
|
+
directTopic = await ctx.db.get(
|
|
187
|
+
args.projectId
|
|
188
|
+
);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
debugGraphPrimitiveFallback(
|
|
191
|
+
"[topicScope] Failed to load direct project topic",
|
|
192
|
+
{
|
|
193
|
+
error,
|
|
194
|
+
projectId: args.projectId
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (directTopic) {
|
|
199
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
200
|
+
const mapped = asMappedProjectId(directTopic);
|
|
201
|
+
return {
|
|
202
|
+
topicId: directTopic._id,
|
|
203
|
+
projectId: mapped ?? args.projectId,
|
|
204
|
+
tenantId: inherited.tenantId,
|
|
205
|
+
workspaceId: inherited.workspaceId,
|
|
206
|
+
source: "topic_inferred"
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
210
|
+
if (directTopic) {
|
|
211
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
212
|
+
const mapped = asMappedProjectId(directTopic);
|
|
213
|
+
return {
|
|
214
|
+
topicId: directTopic._id,
|
|
215
|
+
projectId: mapped ?? args.projectId,
|
|
216
|
+
tenantId: inherited.tenantId,
|
|
217
|
+
workspaceId: inherited.workspaceId,
|
|
218
|
+
source: "topic_inferred"
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
222
|
+
const primary = pickPrimaryTopic(topics);
|
|
223
|
+
if (primary) {
|
|
224
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
225
|
+
return {
|
|
226
|
+
topicId: primary._id,
|
|
227
|
+
projectId: args.projectId,
|
|
228
|
+
tenantId: inherited.tenantId,
|
|
229
|
+
workspaceId: inherited.workspaceId,
|
|
230
|
+
source: "project_mapped_topic"
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
throw new Error(
|
|
234
|
+
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
throw new Error(
|
|
238
|
+
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
var optionalScopeArgs = {
|
|
242
|
+
projectId: v.optional(v.string()),
|
|
243
|
+
topicId: v.optional(v.string())
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// src/epistemicNodes.helpers.ts
|
|
247
|
+
var DEFAULT_NODE_PAGE_SIZE = 250;
|
|
248
|
+
var MAX_NODE_PAGE_SIZE = 8e3;
|
|
249
|
+
function clampNodeLimit(limit, fallback = DEFAULT_NODE_PAGE_SIZE) {
|
|
250
|
+
if (!Number.isFinite(limit)) {
|
|
251
|
+
return fallback;
|
|
252
|
+
}
|
|
253
|
+
return Math.max(1, Math.min(Math.floor(limit), MAX_NODE_PAGE_SIZE));
|
|
254
|
+
}
|
|
255
|
+
function dedupeWorkspaceNodes(nodes) {
|
|
256
|
+
const seen = /* @__PURE__ */ new Set();
|
|
257
|
+
const deduped = [];
|
|
258
|
+
for (const node of nodes) {
|
|
259
|
+
const key = String(node._id);
|
|
260
|
+
if (seen.has(key)) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
seen.add(key);
|
|
264
|
+
deduped.push(node);
|
|
265
|
+
}
|
|
266
|
+
return deduped;
|
|
267
|
+
}
|
|
268
|
+
function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
269
|
+
return scope.topicId !== void 0 && node.topicId === scope.topicId || scope.projectId !== void 0 && node.projectId === scope.projectId;
|
|
270
|
+
}
|
|
271
|
+
async function collectScopedNodes(ctx, scope, args) {
|
|
272
|
+
const queries = [];
|
|
273
|
+
if (scope.topicId) {
|
|
274
|
+
queries.push(
|
|
275
|
+
args.nodeType ? ctx.db.query("epistemicNodes").withIndex(
|
|
276
|
+
"by_topic_type",
|
|
277
|
+
(q) => q.eq("topicId", scope.topicId).eq("nodeType", args.nodeType)
|
|
278
|
+
).order("desc").take(args.scanLimit) : ctx.db.query("epistemicNodes").withIndex("by_topic", (q) => q.eq("topicId", scope.topicId)).order("desc").take(args.scanLimit)
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
if (scope.projectId && !scope.topicId) {
|
|
282
|
+
queries.push(
|
|
283
|
+
args.nodeType ? ctx.db.query("epistemicNodes").withIndex(
|
|
284
|
+
"by_topic_type",
|
|
285
|
+
(q) => q.eq("topicId", scope.projectId).eq("nodeType", args.nodeType)
|
|
286
|
+
).order("desc").take(args.scanLimit) : ctx.db.query("epistemicNodes").withIndex("by_topic", (q) => q.eq("topicId", scope.projectId)).order("desc").take(args.scanLimit)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
const combined = dedupeWorkspaceNodes((await Promise.all(queries)).flat());
|
|
290
|
+
return combined.filter(
|
|
291
|
+
(node) => nodeMatchesWorkspaceReasoningScope(node, scope)
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
v.union(
|
|
295
|
+
v.literal("L4"),
|
|
296
|
+
v.literal("L3"),
|
|
297
|
+
v.literal("L2"),
|
|
298
|
+
v.literal("L1"),
|
|
299
|
+
v.literal("ontological"),
|
|
300
|
+
v.literal("organizational")
|
|
301
|
+
);
|
|
302
|
+
v.union(v.literal("decision"));
|
|
303
|
+
v.union(
|
|
304
|
+
v.literal("belief"),
|
|
305
|
+
v.literal("question"),
|
|
306
|
+
v.literal("theme"),
|
|
307
|
+
v.literal("deal")
|
|
308
|
+
);
|
|
309
|
+
v.union(
|
|
310
|
+
v.literal("claim"),
|
|
311
|
+
v.literal("evidence"),
|
|
312
|
+
v.literal("synthesis")
|
|
313
|
+
);
|
|
314
|
+
v.union(
|
|
315
|
+
v.literal("atomic_fact"),
|
|
316
|
+
v.literal("excerpt"),
|
|
317
|
+
v.literal("source")
|
|
318
|
+
);
|
|
319
|
+
v.union(
|
|
320
|
+
// L4: Audit targets
|
|
321
|
+
v.literal("decision"),
|
|
322
|
+
// L3: Traversal anchors
|
|
323
|
+
v.literal("belief"),
|
|
324
|
+
v.literal("question"),
|
|
325
|
+
v.literal("theme"),
|
|
326
|
+
v.literal("deal"),
|
|
327
|
+
// L2: Compression boundary
|
|
328
|
+
v.literal("claim"),
|
|
329
|
+
v.literal("evidence"),
|
|
330
|
+
v.literal("synthesis"),
|
|
331
|
+
v.literal("answer"),
|
|
332
|
+
// L1: Terminal leaves
|
|
333
|
+
v.literal("atomic_fact"),
|
|
334
|
+
v.literal("excerpt"),
|
|
335
|
+
v.literal("source")
|
|
336
|
+
);
|
|
337
|
+
v.union(
|
|
338
|
+
v.literal("company"),
|
|
339
|
+
v.literal("person"),
|
|
340
|
+
v.literal("investor"),
|
|
341
|
+
v.literal("function"),
|
|
342
|
+
v.literal("value_chain")
|
|
343
|
+
);
|
|
344
|
+
v.union(v.literal("topic"));
|
|
345
|
+
var nodeTypeValidator = v.union(
|
|
346
|
+
// L4: Audit targets
|
|
347
|
+
v.literal("decision"),
|
|
348
|
+
// L3: Traversal anchors
|
|
349
|
+
v.literal("belief"),
|
|
350
|
+
v.literal("question"),
|
|
351
|
+
v.literal("theme"),
|
|
352
|
+
v.literal("deal"),
|
|
353
|
+
// L2: Compression boundary
|
|
354
|
+
v.literal("claim"),
|
|
355
|
+
v.literal("evidence"),
|
|
356
|
+
v.literal("synthesis"),
|
|
357
|
+
v.literal("answer"),
|
|
358
|
+
// L1: Terminal leaves
|
|
359
|
+
v.literal("atomic_fact"),
|
|
360
|
+
v.literal("excerpt"),
|
|
361
|
+
v.literal("source"),
|
|
362
|
+
// Ontological
|
|
363
|
+
v.literal("company"),
|
|
364
|
+
v.literal("person"),
|
|
365
|
+
v.literal("investor"),
|
|
366
|
+
v.literal("function"),
|
|
367
|
+
v.literal("value_chain"),
|
|
368
|
+
// Organizational
|
|
369
|
+
v.literal("topic")
|
|
370
|
+
);
|
|
371
|
+
v.union(
|
|
372
|
+
v.literal("human"),
|
|
373
|
+
v.literal("ai_extracted"),
|
|
374
|
+
v.literal("ai_generated"),
|
|
375
|
+
v.literal("imported"),
|
|
376
|
+
v.literal("system")
|
|
377
|
+
// System-generated (migrations, classifiers)
|
|
378
|
+
);
|
|
379
|
+
var statusValidator = v.union(
|
|
380
|
+
v.literal("active"),
|
|
381
|
+
v.literal("superseded"),
|
|
382
|
+
v.literal("archived"),
|
|
383
|
+
v.literal("deleted")
|
|
384
|
+
);
|
|
385
|
+
v.union(
|
|
386
|
+
v.literal("unverified"),
|
|
387
|
+
v.literal("human_verified"),
|
|
388
|
+
v.literal("ai_verified"),
|
|
389
|
+
v.literal("contradicted"),
|
|
390
|
+
v.literal("outdated")
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// src/epistemicNodes.queries.ts
|
|
394
|
+
var optionalNodeScopeArgs = optionalScopeArgs;
|
|
395
|
+
var get = query({
|
|
396
|
+
args: { nodeId: v.id("epistemicNodes") },
|
|
397
|
+
returns: permissiveReturn,
|
|
398
|
+
handler: async (ctx, args) => {
|
|
399
|
+
return await ctx.db.get(args.nodeId);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
var getByGlobalId = query({
|
|
403
|
+
args: { globalId: v.string() },
|
|
404
|
+
returns: permissiveReturn,
|
|
405
|
+
handler: async (ctx, args) => {
|
|
406
|
+
return await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", args.globalId)).first();
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
var getByContentHash = query({
|
|
410
|
+
args: { contentHash: v.string() },
|
|
411
|
+
returns: permissiveReturn,
|
|
412
|
+
handler: async (ctx, args) => {
|
|
413
|
+
return await ctx.db.query("epistemicNodes").withIndex("by_contentHash", (q) => q.eq("contentHash", args.contentHash)).collect();
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
var getByProjectAndType = query({
|
|
417
|
+
args: {
|
|
418
|
+
...optionalNodeScopeArgs,
|
|
419
|
+
nodeType: nodeTypeValidator,
|
|
420
|
+
status: v.optional(statusValidator),
|
|
421
|
+
limit: v.optional(v.number())
|
|
422
|
+
},
|
|
423
|
+
returns: permissiveReturn,
|
|
424
|
+
handler: async (ctx, args) => {
|
|
425
|
+
if (!args.projectId && !args.topicId) {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
428
|
+
let scope;
|
|
429
|
+
try {
|
|
430
|
+
scope = await resolveTopicProjectScope(ctx, {
|
|
431
|
+
projectId: args.projectId,
|
|
432
|
+
topicId: args.topicId
|
|
433
|
+
});
|
|
434
|
+
} catch (error) {
|
|
435
|
+
debugGraphPrimitiveFallback(
|
|
436
|
+
"[epistemicNodes] Failed to resolve getByProjectAndType scope",
|
|
437
|
+
{
|
|
438
|
+
error,
|
|
439
|
+
projectId: args.projectId,
|
|
440
|
+
topicId: args.topicId
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
return [];
|
|
444
|
+
}
|
|
445
|
+
const pageSize = clampNodeLimit(args.limit);
|
|
446
|
+
const scanLimit = Math.min(pageSize * 3, MAX_NODE_PAGE_SIZE);
|
|
447
|
+
const nodes = await collectScopedNodes(ctx, scope, {
|
|
448
|
+
nodeType: args.nodeType,
|
|
449
|
+
scanLimit
|
|
450
|
+
});
|
|
451
|
+
if (args.status) {
|
|
452
|
+
return nodes.filter(
|
|
453
|
+
(n) => n.status === args.status && nodeMatchesWorkspaceReasoningScope(n, scope)
|
|
454
|
+
).slice(0, pageSize);
|
|
455
|
+
}
|
|
456
|
+
return nodes.filter(
|
|
457
|
+
(n) => n.status === "active" && nodeMatchesWorkspaceReasoningScope(n, scope)
|
|
458
|
+
).slice(0, pageSize);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
var getByProjectAndTypeLite = query({
|
|
462
|
+
args: {
|
|
463
|
+
...optionalNodeScopeArgs,
|
|
464
|
+
nodeType: nodeTypeValidator,
|
|
465
|
+
status: v.optional(statusValidator),
|
|
466
|
+
limit: v.optional(v.number())
|
|
467
|
+
},
|
|
468
|
+
returns: permissiveReturn,
|
|
469
|
+
handler: async (ctx, args) => {
|
|
470
|
+
if (!args.projectId && !args.topicId) {
|
|
471
|
+
return [];
|
|
472
|
+
}
|
|
473
|
+
let scope;
|
|
474
|
+
try {
|
|
475
|
+
scope = await resolveTopicProjectScope(ctx, {
|
|
476
|
+
projectId: args.projectId,
|
|
477
|
+
topicId: args.topicId
|
|
478
|
+
});
|
|
479
|
+
} catch (error) {
|
|
480
|
+
debugGraphPrimitiveFallback(
|
|
481
|
+
"[epistemicNodes] Failed to resolve getByNodeType scope",
|
|
482
|
+
{
|
|
483
|
+
error,
|
|
484
|
+
projectId: args.projectId,
|
|
485
|
+
topicId: args.topicId
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
return [];
|
|
489
|
+
}
|
|
490
|
+
const pageSize = clampNodeLimit(args.limit);
|
|
491
|
+
const scanLimit = Math.min(pageSize * 3, MAX_NODE_PAGE_SIZE);
|
|
492
|
+
const query2 = ctx.db.query("epistemicNodes").withIndex(
|
|
493
|
+
"by_topic_type",
|
|
494
|
+
(q) => q.eq("topicId", scope.topicId).eq("nodeType", args.nodeType)
|
|
495
|
+
);
|
|
496
|
+
const nodes = await query2.order("desc").take(scanLimit);
|
|
497
|
+
const statusFiltered = args.status ? nodes.filter((n) => n.status === args.status) : nodes.filter((n) => n.status === "active");
|
|
498
|
+
const capped = statusFiltered.slice(0, pageSize);
|
|
499
|
+
return capped.map((n) => ({
|
|
500
|
+
_id: n._id,
|
|
501
|
+
globalId: n.globalId,
|
|
502
|
+
nodeType: n.nodeType,
|
|
503
|
+
createdBy: n.createdBy,
|
|
504
|
+
topicId: n.topicId,
|
|
505
|
+
projectId: n.projectId,
|
|
506
|
+
status: n.status,
|
|
507
|
+
epistemicLayer: n.epistemicLayer
|
|
508
|
+
}));
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
var getByProject = query({
|
|
512
|
+
args: {
|
|
513
|
+
...optionalNodeScopeArgs,
|
|
514
|
+
userId: v.optional(v.string()),
|
|
515
|
+
includeArchived: v.optional(v.boolean()),
|
|
516
|
+
limit: v.optional(v.number())
|
|
517
|
+
},
|
|
518
|
+
returns: permissiveReturn,
|
|
519
|
+
handler: async (ctx, args) => {
|
|
520
|
+
if (!args.projectId && !args.topicId) {
|
|
521
|
+
return [];
|
|
522
|
+
}
|
|
523
|
+
const pageSize = clampNodeLimit(args.limit);
|
|
524
|
+
const scanLimit = Math.min(pageSize * 3, MAX_NODE_PAGE_SIZE);
|
|
525
|
+
let scope;
|
|
526
|
+
try {
|
|
527
|
+
scope = await resolveTopicProjectScope(ctx, {
|
|
528
|
+
projectId: args.projectId,
|
|
529
|
+
topicId: args.topicId
|
|
530
|
+
});
|
|
531
|
+
} catch (error) {
|
|
532
|
+
debugGraphPrimitiveFallback("[epistemicNodes] Failed to resolve list scope", {
|
|
533
|
+
error,
|
|
534
|
+
projectId: args.projectId,
|
|
535
|
+
topicId: args.topicId
|
|
536
|
+
});
|
|
537
|
+
return [];
|
|
538
|
+
}
|
|
539
|
+
if (args.userId) {
|
|
540
|
+
const hasAccess = await checkScopeAccess(
|
|
541
|
+
ctx,
|
|
542
|
+
String(scope.topicId ?? scope.projectId),
|
|
543
|
+
args.userId
|
|
544
|
+
);
|
|
545
|
+
if (!hasAccess) {
|
|
546
|
+
return [];
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const nodes = await collectScopedNodes(ctx, scope, { scanLimit });
|
|
550
|
+
if (args.includeArchived) {
|
|
551
|
+
return nodes.filter(
|
|
552
|
+
(n) => n.status !== "deleted" && nodeMatchesWorkspaceReasoningScope(n, scope)
|
|
553
|
+
).slice(0, pageSize);
|
|
554
|
+
}
|
|
555
|
+
return nodes.filter(
|
|
556
|
+
(n) => n.status === "active" && nodeMatchesWorkspaceReasoningScope(n, scope)
|
|
557
|
+
).slice(0, pageSize);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
var listAll = query({
|
|
561
|
+
args: {
|
|
562
|
+
limit: v.optional(v.number())
|
|
563
|
+
},
|
|
564
|
+
returns: permissiveReturn,
|
|
565
|
+
handler: async (ctx, args) => {
|
|
566
|
+
const pageSize = clampNodeLimit(args.limit ?? 2e3);
|
|
567
|
+
const scanLimit = Math.min(pageSize * 2, MAX_NODE_PAGE_SIZE * 2);
|
|
568
|
+
const nodes = await ctx.db.query("epistemicNodes").order("desc").take(scanLimit);
|
|
569
|
+
return nodes.filter((n) => n.status === "active").slice(0, pageSize);
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
var search = query({
|
|
573
|
+
args: {
|
|
574
|
+
searchQuery: v.string(),
|
|
575
|
+
...optionalNodeScopeArgs,
|
|
576
|
+
nodeType: v.optional(nodeTypeValidator),
|
|
577
|
+
limit: v.optional(v.number())
|
|
578
|
+
},
|
|
579
|
+
returns: permissiveReturn,
|
|
580
|
+
handler: async (ctx, args) => {
|
|
581
|
+
const pageSize = clampNodeLimit(args.limit, 100);
|
|
582
|
+
let scope;
|
|
583
|
+
if (args.projectId || args.topicId) {
|
|
584
|
+
try {
|
|
585
|
+
scope = await resolveTopicProjectScope(ctx, {
|
|
586
|
+
projectId: args.projectId,
|
|
587
|
+
topicId: args.topicId
|
|
588
|
+
});
|
|
589
|
+
} catch (error) {
|
|
590
|
+
debugGraphPrimitiveFallback(
|
|
591
|
+
"[epistemicNodes] Failed to resolve search scope",
|
|
592
|
+
{
|
|
593
|
+
error,
|
|
594
|
+
projectId: args.projectId,
|
|
595
|
+
topicId: args.topicId
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
return [];
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
const searchResults = ctx.db.query("epistemicNodes").withSearchIndex("search_canonicalText", (q) => {
|
|
602
|
+
let search2 = q.search("canonicalText", args.searchQuery);
|
|
603
|
+
if (scope?.topicId) {
|
|
604
|
+
search2 = search2.eq("topicId", scope.topicId);
|
|
605
|
+
} else if (scope?.projectId) {
|
|
606
|
+
search2 = search2.eq("projectId", scope.projectId);
|
|
607
|
+
}
|
|
608
|
+
if (args.nodeType) {
|
|
609
|
+
search2 = search2.eq("nodeType", args.nodeType);
|
|
610
|
+
}
|
|
611
|
+
return search2.eq("status", "active");
|
|
612
|
+
});
|
|
613
|
+
return await searchResults.take(pageSize);
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
export { get, getByContentHash, getByGlobalId, getByProject, getByProjectAndType, getByProjectAndTypeLite, listAll, search };
|
|
618
|
+
//# sourceMappingURL=epistemicNodes.queries.js.map
|
|
619
|
+
//# sourceMappingURL=epistemicNodes.queries.js.map
|