@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,745 @@
|
|
|
1
|
+
import { v } from 'convex/values';
|
|
2
|
+
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
3
|
+
import { componentsGeneric, anyApi, mutationGeneric, queryGeneric } from 'convex/server';
|
|
4
|
+
import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
|
|
5
|
+
import { checkProjectAccess } from '@lucern/access-control/access';
|
|
6
|
+
import '@lucern/access-control/audience';
|
|
7
|
+
import { getCurrentUserId } from '@lucern/access-control/auth';
|
|
8
|
+
import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
|
|
9
|
+
|
|
10
|
+
// src/epistemicBeliefs.admin.ts
|
|
11
|
+
var api = anyApi;
|
|
12
|
+
componentsGeneric();
|
|
13
|
+
var internal = anyApi;
|
|
14
|
+
var mutation = mutationGeneric;
|
|
15
|
+
var query = queryGeneric;
|
|
16
|
+
|
|
17
|
+
// src/debug.ts
|
|
18
|
+
function isGraphPrimitiveDebugEnabled() {
|
|
19
|
+
const env = globalThis.process?.env;
|
|
20
|
+
return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
|
|
21
|
+
}
|
|
22
|
+
function debugGraphPrimitiveFallback(message, context) {
|
|
23
|
+
if (!isGraphPrimitiveDebugEnabled()) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.debug(message, context ?? {});
|
|
27
|
+
}
|
|
28
|
+
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
29
|
+
function asMappedProjectId(topic) {
|
|
30
|
+
if (!topic) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
|
|
34
|
+
if (directLegacyProjectId) {
|
|
35
|
+
return directLegacyProjectId;
|
|
36
|
+
}
|
|
37
|
+
const metadata = topic.metadata || {};
|
|
38
|
+
const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
|
|
39
|
+
return candidate ? candidate : void 0;
|
|
40
|
+
}
|
|
41
|
+
function normalizeScopeValue(value) {
|
|
42
|
+
if (typeof value !== "string") {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const normalized = value.trim();
|
|
46
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
47
|
+
}
|
|
48
|
+
function pickPrimaryTopic(candidates) {
|
|
49
|
+
return [...candidates].sort((a, b) => {
|
|
50
|
+
const depthA = a.depth ?? 9999;
|
|
51
|
+
const depthB = b.depth ?? 9999;
|
|
52
|
+
if (depthA !== depthB) {
|
|
53
|
+
return depthA - depthB;
|
|
54
|
+
}
|
|
55
|
+
const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
56
|
+
const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;
|
|
57
|
+
if (createdA !== createdB) {
|
|
58
|
+
return createdA - createdB;
|
|
59
|
+
}
|
|
60
|
+
return String(a.name || "").localeCompare(String(b.name || ""));
|
|
61
|
+
})[0];
|
|
62
|
+
}
|
|
63
|
+
async function findTopicsByScopeAlias(ctx, scopeId) {
|
|
64
|
+
try {
|
|
65
|
+
return await ctx.db.query("topics").withIndex(
|
|
66
|
+
"by_graph_scope_project",
|
|
67
|
+
(q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
|
|
68
|
+
).collect();
|
|
69
|
+
} catch (error) {
|
|
70
|
+
debugGraphPrimitiveFallback(
|
|
71
|
+
"[topicScope] Failed to resolve scope alias via index",
|
|
72
|
+
{
|
|
73
|
+
error,
|
|
74
|
+
scopeId
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
const topics = await ctx.db.query("topics").collect();
|
|
78
|
+
return topics.filter((topic) => {
|
|
79
|
+
const normalizedGlobalId = normalizeScopeValue(topic.globalId);
|
|
80
|
+
const mappedProjectId = asMappedProjectId(topic);
|
|
81
|
+
return String(topic._id) === scopeId || normalizedGlobalId === scopeId || mappedProjectId === scopeId;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function tryResolveHostTopicById(ctx, topicId) {
|
|
86
|
+
if (typeof ctx.runQuery !== "function") {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
return await ctx.runQuery(api.topics.get, {
|
|
91
|
+
id: topicId
|
|
92
|
+
}) ?? null;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
debugGraphPrimitiveFallback(
|
|
95
|
+
"[topicScope] Failed to resolve topic by host query",
|
|
96
|
+
{
|
|
97
|
+
error,
|
|
98
|
+
topicId
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function tryResolveHostTopicByLegacyScope(ctx, legacyScopeId) {
|
|
105
|
+
if (typeof ctx.runQuery !== "function") {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
return await ctx.runQuery(api.topics.getByLegacyScopeId, {
|
|
110
|
+
projectId: legacyScopeId
|
|
111
|
+
}) ?? null;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
debugGraphPrimitiveFallback(
|
|
114
|
+
"[topicScope] Failed to resolve topic by legacy scope",
|
|
115
|
+
{
|
|
116
|
+
error,
|
|
117
|
+
legacyScopeId
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function resolveInheritedWorkspaceScope(ctx, topic) {
|
|
124
|
+
const MAX_DEPTH = 10;
|
|
125
|
+
let tenantId = normalizeScopeValue(topic.tenantId);
|
|
126
|
+
let workspaceId = normalizeScopeValue(topic.workspaceId);
|
|
127
|
+
if (tenantId && workspaceId) {
|
|
128
|
+
return { tenantId, workspaceId };
|
|
129
|
+
}
|
|
130
|
+
let current = topic;
|
|
131
|
+
for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
|
|
132
|
+
current = await ctx.db.get(current.parentTopicId);
|
|
133
|
+
if (!current) break;
|
|
134
|
+
if (!tenantId) {
|
|
135
|
+
tenantId = normalizeScopeValue(current.tenantId);
|
|
136
|
+
}
|
|
137
|
+
if (!workspaceId) {
|
|
138
|
+
workspaceId = normalizeScopeValue(current.workspaceId);
|
|
139
|
+
}
|
|
140
|
+
if (tenantId && workspaceId) break;
|
|
141
|
+
}
|
|
142
|
+
return { tenantId, workspaceId };
|
|
143
|
+
}
|
|
144
|
+
async function resolveTopicProjectScope(ctx, args) {
|
|
145
|
+
if (args.topicId) {
|
|
146
|
+
let topic = null;
|
|
147
|
+
try {
|
|
148
|
+
topic = await ctx.db.get(
|
|
149
|
+
args.topicId
|
|
150
|
+
);
|
|
151
|
+
} catch (error) {
|
|
152
|
+
debugGraphPrimitiveFallback(
|
|
153
|
+
"[topicScope] Failed to load topic by direct id",
|
|
154
|
+
{
|
|
155
|
+
error,
|
|
156
|
+
topicId: args.topicId
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
if (!topic) {
|
|
161
|
+
topic = await tryResolveHostTopicById(ctx, String(args.topicId));
|
|
162
|
+
}
|
|
163
|
+
if (!topic) {
|
|
164
|
+
topic = pickPrimaryTopic(
|
|
165
|
+
await findTopicsByScopeAlias(ctx, String(args.topicId))
|
|
166
|
+
) ?? null;
|
|
167
|
+
}
|
|
168
|
+
if (!topic) {
|
|
169
|
+
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
170
|
+
}
|
|
171
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
172
|
+
const mapped = asMappedProjectId(topic);
|
|
173
|
+
if (mapped) {
|
|
174
|
+
return {
|
|
175
|
+
topicId: topic._id,
|
|
176
|
+
projectId: mapped,
|
|
177
|
+
tenantId: inherited.tenantId,
|
|
178
|
+
workspaceId: inherited.workspaceId,
|
|
179
|
+
source: "topic"
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
topicId: topic._id,
|
|
184
|
+
tenantId: inherited.tenantId,
|
|
185
|
+
workspaceId: inherited.workspaceId,
|
|
186
|
+
source: "topic"
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (args.projectId) {
|
|
190
|
+
let directTopic = null;
|
|
191
|
+
try {
|
|
192
|
+
directTopic = await ctx.db.get(
|
|
193
|
+
args.projectId
|
|
194
|
+
);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
debugGraphPrimitiveFallback(
|
|
197
|
+
"[topicScope] Failed to load direct project topic",
|
|
198
|
+
{
|
|
199
|
+
error,
|
|
200
|
+
projectId: args.projectId
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
if (directTopic) {
|
|
205
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
206
|
+
const mapped = asMappedProjectId(directTopic);
|
|
207
|
+
return {
|
|
208
|
+
topicId: directTopic._id,
|
|
209
|
+
projectId: mapped ?? args.projectId,
|
|
210
|
+
tenantId: inherited.tenantId,
|
|
211
|
+
workspaceId: inherited.workspaceId,
|
|
212
|
+
source: "topic_inferred"
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
|
|
216
|
+
if (directTopic) {
|
|
217
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
|
|
218
|
+
const mapped = asMappedProjectId(directTopic);
|
|
219
|
+
return {
|
|
220
|
+
topicId: directTopic._id,
|
|
221
|
+
projectId: mapped ?? args.projectId,
|
|
222
|
+
tenantId: inherited.tenantId,
|
|
223
|
+
workspaceId: inherited.workspaceId,
|
|
224
|
+
source: "topic_inferred"
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const topics = await findTopicsByScopeAlias(ctx, args.projectId);
|
|
228
|
+
const primary = pickPrimaryTopic(topics);
|
|
229
|
+
if (primary) {
|
|
230
|
+
const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
|
|
231
|
+
return {
|
|
232
|
+
topicId: primary._id,
|
|
233
|
+
projectId: args.projectId,
|
|
234
|
+
tenantId: inherited.tenantId,
|
|
235
|
+
workspaceId: inherited.workspaceId,
|
|
236
|
+
source: "project_mapped_topic"
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
throw new Error(
|
|
244
|
+
"Missing scope: provide topicId (preferred) or legacy projectId alias."
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
var optionalScopeArgs = {
|
|
248
|
+
projectId: v.optional(v.string()),
|
|
249
|
+
topicId: v.optional(v.string())
|
|
250
|
+
};
|
|
251
|
+
function normalizeScopeValue2(value) {
|
|
252
|
+
if (typeof value !== "string") {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const normalized = value.trim();
|
|
256
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
257
|
+
}
|
|
258
|
+
function nodeMatchesWorkspaceReasoningScope(node, scope) {
|
|
259
|
+
if (!node) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
const scopeTenantId = normalizeScopeValue2(scope.tenantId);
|
|
263
|
+
const scopeWorkspaceId = normalizeScopeValue2(scope.workspaceId);
|
|
264
|
+
const nodeTenantId = normalizeScopeValue2(node.tenantId);
|
|
265
|
+
const nodeWorkspaceId = normalizeScopeValue2(node.workspaceId);
|
|
266
|
+
const epistemicLayer = typeof node.epistemicLayer === "string" ? node.epistemicLayer : void 0;
|
|
267
|
+
if (scopeTenantId && nodeTenantId && scopeTenantId !== nodeTenantId) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
if (epistemicLayer === "ontological" && nodeWorkspaceId === void 0) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
if (!scopeWorkspaceId && node.publicationStatus === "published") {
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
if (!scopeWorkspaceId) {
|
|
277
|
+
return nodeWorkspaceId === void 0;
|
|
278
|
+
}
|
|
279
|
+
return scopeWorkspaceId === nodeWorkspaceId;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/epistemicBeliefs.helpers.ts
|
|
283
|
+
v.id("epistemicNodes");
|
|
284
|
+
var DEFAULT_PROJECT_BELIEF_LIMIT = 250;
|
|
285
|
+
var MAX_PROJECT_BELIEF_LIMIT = 1e3;
|
|
286
|
+
var optionalBeliefScopeArgs = optionalScopeArgs;
|
|
287
|
+
({
|
|
288
|
+
tupleContradiction: normalizeTupleContradictionPolicy()
|
|
289
|
+
});
|
|
290
|
+
function throwStructuredMutationError(args) {
|
|
291
|
+
const error = new Error(args.message);
|
|
292
|
+
error.status = args.status;
|
|
293
|
+
error.code = args.code;
|
|
294
|
+
error.invariantCode = args.invariantCode;
|
|
295
|
+
error.suggestion = args.suggestion;
|
|
296
|
+
error.details = args.details;
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
function buildBeliefStatusSuccessResult() {
|
|
300
|
+
return { success: true };
|
|
301
|
+
}
|
|
302
|
+
function clampBeliefLimit(limit, fallback = DEFAULT_PROJECT_BELIEF_LIMIT) {
|
|
303
|
+
if (!Number.isFinite(limit)) {
|
|
304
|
+
return fallback;
|
|
305
|
+
}
|
|
306
|
+
return Math.max(
|
|
307
|
+
1,
|
|
308
|
+
Math.min(Math.floor(limit), MAX_PROJECT_BELIEF_LIMIT)
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
async function resolveBeliefScopeOrNull(ctx, args) {
|
|
312
|
+
if (!args.projectId && !args.topicId) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
return await resolveTopicProjectScope(ctx, {
|
|
317
|
+
projectId: args.projectId ?? void 0,
|
|
318
|
+
topicId: args.topicId ?? void 0
|
|
319
|
+
});
|
|
320
|
+
} catch (error) {
|
|
321
|
+
debugGraphPrimitiveFallback(
|
|
322
|
+
"[epistemicBeliefs] Failed to resolve belief scope",
|
|
323
|
+
{
|
|
324
|
+
error,
|
|
325
|
+
projectId: args.projectId,
|
|
326
|
+
topicId: args.topicId
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async function getBeliefNodesForScope(ctx, scope, args) {
|
|
333
|
+
const baseQuery = ctx.db.query("epistemicNodes").withIndex(
|
|
334
|
+
"by_topic_type",
|
|
335
|
+
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "belief")
|
|
336
|
+
);
|
|
337
|
+
const nodes = typeof args?.scanLimit === "number" ? await baseQuery.order("desc").take(args.scanLimit) : await baseQuery.collect();
|
|
338
|
+
const scopedNodes = nodes.filter(
|
|
339
|
+
(node) => nodeMatchesWorkspaceReasoningScope(node, scope)
|
|
340
|
+
);
|
|
341
|
+
if (!args?.status) {
|
|
342
|
+
return scopedNodes;
|
|
343
|
+
}
|
|
344
|
+
return scopedNodes.filter((node) => node.status === args.status);
|
|
345
|
+
}
|
|
346
|
+
async function requireAuthenticatedUserId(ctx) {
|
|
347
|
+
const userId = await getCurrentUserId(
|
|
348
|
+
ctx
|
|
349
|
+
);
|
|
350
|
+
if (!userId) {
|
|
351
|
+
throwStructuredMutationError({
|
|
352
|
+
message: "Authentication required.",
|
|
353
|
+
status: 401,
|
|
354
|
+
code: "AUTHENTICATION_REQUIRED",
|
|
355
|
+
invariantCode: "auth.required",
|
|
356
|
+
suggestion: "Provide a valid bearer token before invoking belief mutations."
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
return userId;
|
|
360
|
+
}
|
|
361
|
+
async function requireProjectWriteAccess(ctx, projectId, userId) {
|
|
362
|
+
const hasAccess = await checkProjectAccess(
|
|
363
|
+
ctx,
|
|
364
|
+
projectId,
|
|
365
|
+
userId
|
|
366
|
+
);
|
|
367
|
+
if (!hasAccess) {
|
|
368
|
+
throwStructuredMutationError({
|
|
369
|
+
message: "Project access required.",
|
|
370
|
+
status: 403,
|
|
371
|
+
code: "FORBIDDEN",
|
|
372
|
+
invariantCode: "policy.scope_required",
|
|
373
|
+
suggestion: "Request write access for the project and retry.",
|
|
374
|
+
details: { projectId, userId }
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/epistemicBeliefs.admin.ts
|
|
380
|
+
var deleteRelationship = mutation({
|
|
381
|
+
args: {
|
|
382
|
+
edgeId: v.id("epistemicEdges"),
|
|
383
|
+
userId: v.string()
|
|
384
|
+
},
|
|
385
|
+
returns: permissiveReturn,
|
|
386
|
+
handler: async (ctx, args) => {
|
|
387
|
+
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
388
|
+
const now = Date.now();
|
|
389
|
+
const edge = await ctx.db.get(args.edgeId);
|
|
390
|
+
if (!edge) {
|
|
391
|
+
throw new Error("Edge not found");
|
|
392
|
+
}
|
|
393
|
+
if (!edge.projectId) {
|
|
394
|
+
throw new Error("Edge has no project scope");
|
|
395
|
+
}
|
|
396
|
+
await requireProjectWriteAccess(ctx, edge.projectId, authenticatedUserId);
|
|
397
|
+
const previousState = {
|
|
398
|
+
fromNodeId: edge.fromNodeId,
|
|
399
|
+
toNodeId: edge.toNodeId,
|
|
400
|
+
edgeType: edge.edgeType
|
|
401
|
+
};
|
|
402
|
+
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.deleteEdge, {
|
|
403
|
+
globalId: edge.globalId
|
|
404
|
+
});
|
|
405
|
+
await ctx.db.delete(args.edgeId);
|
|
406
|
+
await ctx.db.insert("epistemicAudit", {
|
|
407
|
+
entityType: "edge",
|
|
408
|
+
entityId: edge.globalId,
|
|
409
|
+
changeType: "edge_removed",
|
|
410
|
+
previousState,
|
|
411
|
+
newState: null,
|
|
412
|
+
changedBy: authenticatedUserId,
|
|
413
|
+
isAgent: false,
|
|
414
|
+
changedAt: now,
|
|
415
|
+
projectId: edge.projectId
|
|
416
|
+
});
|
|
417
|
+
return buildBeliefStatusSuccessResult();
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
var updateCriticality = mutation({
|
|
421
|
+
args: {
|
|
422
|
+
nodeId: v.id("epistemicNodes"),
|
|
423
|
+
criticality: v.union(
|
|
424
|
+
v.literal("blocking"),
|
|
425
|
+
v.literal("important"),
|
|
426
|
+
v.literal("supporting"),
|
|
427
|
+
v.literal("essential"),
|
|
428
|
+
v.literal("nice_to_have")
|
|
429
|
+
),
|
|
430
|
+
userId: v.string()
|
|
431
|
+
},
|
|
432
|
+
returns: permissiveReturn,
|
|
433
|
+
handler: async (ctx, args) => {
|
|
434
|
+
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
435
|
+
const now = Date.now();
|
|
436
|
+
const node = await ctx.db.get(args.nodeId);
|
|
437
|
+
if (!node || node.nodeType !== "belief") {
|
|
438
|
+
throw new Error("Belief not found");
|
|
439
|
+
}
|
|
440
|
+
if (!node.projectId) {
|
|
441
|
+
throw new Error("Belief has no project scope");
|
|
442
|
+
}
|
|
443
|
+
await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
|
|
444
|
+
const metadata = node.metadata || {};
|
|
445
|
+
const previousCriticality = metadata.criticality;
|
|
446
|
+
await ctx.db.patch(args.nodeId, {
|
|
447
|
+
metadata: {
|
|
448
|
+
...metadata,
|
|
449
|
+
criticality: args.criticality
|
|
450
|
+
},
|
|
451
|
+
updatedAt: now
|
|
452
|
+
});
|
|
453
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
454
|
+
nodeId: args.nodeId,
|
|
455
|
+
operation: "upsert"
|
|
456
|
+
});
|
|
457
|
+
await ctx.db.insert("epistemicAudit", {
|
|
458
|
+
entityType: "belief",
|
|
459
|
+
entityId: args.nodeId,
|
|
460
|
+
changeType: "criticality_changed",
|
|
461
|
+
previousState: { criticality: previousCriticality },
|
|
462
|
+
newState: { criticality: args.criticality },
|
|
463
|
+
changedBy: authenticatedUserId,
|
|
464
|
+
isAgent: false,
|
|
465
|
+
changedAt: now,
|
|
466
|
+
projectId: node.projectId
|
|
467
|
+
});
|
|
468
|
+
return {
|
|
469
|
+
nodeId: args.nodeId,
|
|
470
|
+
previousCriticality,
|
|
471
|
+
newCriticality: args.criticality
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
var batchUpdateCriticality = mutation({
|
|
476
|
+
args: {
|
|
477
|
+
updates: v.array(
|
|
478
|
+
v.object({
|
|
479
|
+
beliefId: v.id("epistemicNodes"),
|
|
480
|
+
criticality: v.union(
|
|
481
|
+
v.literal("blocking"),
|
|
482
|
+
v.literal("important"),
|
|
483
|
+
v.literal("supporting"),
|
|
484
|
+
v.literal("essential"),
|
|
485
|
+
v.literal("nice_to_have")
|
|
486
|
+
),
|
|
487
|
+
ifFalseImpact: v.optional(v.string()),
|
|
488
|
+
triagePriority: v.optional(v.number()),
|
|
489
|
+
reasoning: v.optional(v.string()),
|
|
490
|
+
dependentBeliefIds: v.optional(v.array(v.string())),
|
|
491
|
+
blockedByBeliefIds: v.optional(v.array(v.string()))
|
|
492
|
+
})
|
|
493
|
+
),
|
|
494
|
+
userId: v.string()
|
|
495
|
+
},
|
|
496
|
+
returns: permissiveReturn,
|
|
497
|
+
handler: async (ctx, args) => {
|
|
498
|
+
const authenticatedUserId = await requireAuthenticatedUserId(ctx);
|
|
499
|
+
const now = Date.now();
|
|
500
|
+
const results = [];
|
|
501
|
+
for (const update of args.updates) {
|
|
502
|
+
try {
|
|
503
|
+
const node = await ctx.db.get(update.beliefId);
|
|
504
|
+
if (!node || node.nodeType !== "belief") {
|
|
505
|
+
results.push({ beliefId: update.beliefId, success: false });
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (!node.projectId) {
|
|
509
|
+
results.push({ beliefId: update.beliefId, success: false });
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
await requireProjectWriteAccess(
|
|
513
|
+
ctx,
|
|
514
|
+
node.projectId,
|
|
515
|
+
authenticatedUserId
|
|
516
|
+
);
|
|
517
|
+
const metadata = node.metadata || {};
|
|
518
|
+
const previousCriticality = metadata.criticality;
|
|
519
|
+
await ctx.db.patch(node._id, {
|
|
520
|
+
metadata: {
|
|
521
|
+
...metadata,
|
|
522
|
+
criticality: update.criticality,
|
|
523
|
+
ifFalseImpact: update.ifFalseImpact,
|
|
524
|
+
triagePriority: update.triagePriority,
|
|
525
|
+
criticalityReasoning: update.reasoning,
|
|
526
|
+
dependentBeliefIds: update.dependentBeliefIds,
|
|
527
|
+
blockedByBeliefIds: update.blockedByBeliefIds
|
|
528
|
+
},
|
|
529
|
+
updatedAt: now
|
|
530
|
+
});
|
|
531
|
+
await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
|
|
532
|
+
nodeId: node._id,
|
|
533
|
+
operation: "upsert"
|
|
534
|
+
});
|
|
535
|
+
await ctx.db.insert("epistemicAudit", {
|
|
536
|
+
entityType: "belief",
|
|
537
|
+
entityId: node._id,
|
|
538
|
+
changeType: "criticality_changed",
|
|
539
|
+
previousState: { criticality: previousCriticality },
|
|
540
|
+
newState: { criticality: update.criticality },
|
|
541
|
+
changedBy: authenticatedUserId,
|
|
542
|
+
isAgent: false,
|
|
543
|
+
changedAt: now,
|
|
544
|
+
projectId: node.projectId
|
|
545
|
+
});
|
|
546
|
+
const result = {};
|
|
547
|
+
result.beliefId = update.beliefId;
|
|
548
|
+
result.nodeId = node._id;
|
|
549
|
+
result.success = true;
|
|
550
|
+
results.push(result);
|
|
551
|
+
} catch (error) {
|
|
552
|
+
debugGraphPrimitiveFallback(
|
|
553
|
+
"[epistemicBeliefs] Failed to update belief criticality",
|
|
554
|
+
{
|
|
555
|
+
error,
|
|
556
|
+
beliefId: update.beliefId
|
|
557
|
+
}
|
|
558
|
+
);
|
|
559
|
+
const result = {};
|
|
560
|
+
result.beliefId = update.beliefId;
|
|
561
|
+
result.success = false;
|
|
562
|
+
results.push(result);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return { results, updatedCount: results.filter((r) => r.success).length };
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
var getByCriticality = query({
|
|
569
|
+
args: {
|
|
570
|
+
...optionalBeliefScopeArgs,
|
|
571
|
+
criticality: v.union(
|
|
572
|
+
v.literal("blocking"),
|
|
573
|
+
v.literal("important"),
|
|
574
|
+
v.literal("supporting"),
|
|
575
|
+
v.literal("essential"),
|
|
576
|
+
v.literal("nice_to_have")
|
|
577
|
+
)
|
|
578
|
+
},
|
|
579
|
+
returns: permissiveReturn,
|
|
580
|
+
handler: async (ctx, args) => {
|
|
581
|
+
const scope = await resolveBeliefScopeOrNull(ctx, args);
|
|
582
|
+
if (!scope) {
|
|
583
|
+
return [];
|
|
584
|
+
}
|
|
585
|
+
const nodes = await getBeliefNodesForScope(ctx, scope);
|
|
586
|
+
return nodes.filter((n) => {
|
|
587
|
+
const metadata = n.metadata;
|
|
588
|
+
return metadata?.criticality === args.criticality && n.status === "active";
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
var getUnanalyzed = query({
|
|
593
|
+
args: {
|
|
594
|
+
...optionalBeliefScopeArgs,
|
|
595
|
+
limit: v.optional(v.number())
|
|
596
|
+
},
|
|
597
|
+
returns: permissiveReturn,
|
|
598
|
+
handler: async (ctx, args) => {
|
|
599
|
+
const limit = args.limit || 50;
|
|
600
|
+
const scope = await resolveBeliefScopeOrNull(ctx, args);
|
|
601
|
+
if (!scope) {
|
|
602
|
+
return [];
|
|
603
|
+
}
|
|
604
|
+
const nodes = await getBeliefNodesForScope(ctx, scope);
|
|
605
|
+
const unanalyzed = nodes.filter((n) => {
|
|
606
|
+
const metadata = n.metadata;
|
|
607
|
+
return !metadata?.criticality && n.status === "active";
|
|
608
|
+
});
|
|
609
|
+
return unanalyzed.slice(0, limit);
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
var getByProjectSystem = query({
|
|
613
|
+
args: {
|
|
614
|
+
...optionalBeliefScopeArgs,
|
|
615
|
+
status: v.optional(
|
|
616
|
+
v.union(
|
|
617
|
+
v.literal("active"),
|
|
618
|
+
v.literal("superseded"),
|
|
619
|
+
v.literal("archived")
|
|
620
|
+
)
|
|
621
|
+
),
|
|
622
|
+
limit: v.optional(v.number()),
|
|
623
|
+
audienceMode: v.optional(v.string())
|
|
624
|
+
},
|
|
625
|
+
returns: permissiveReturn,
|
|
626
|
+
handler: async (ctx, args) => {
|
|
627
|
+
const pageSize = clampBeliefLimit(args.limit, 500);
|
|
628
|
+
const scanLimit = Math.min(pageSize * 3, MAX_PROJECT_BELIEF_LIMIT);
|
|
629
|
+
const scope = await resolveBeliefScopeOrNull(ctx, args);
|
|
630
|
+
if (!scope) {
|
|
631
|
+
return [];
|
|
632
|
+
}
|
|
633
|
+
const nodes = await getBeliefNodesForScope(ctx, scope, { scanLimit });
|
|
634
|
+
if (args.status) {
|
|
635
|
+
return nodes.filter((n) => n.status === args.status).slice(0, pageSize);
|
|
636
|
+
}
|
|
637
|
+
return nodes.filter((n) => n.status === "active").slice(0, pageSize);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
var getByPillar = query({
|
|
641
|
+
args: {
|
|
642
|
+
...optionalBeliefScopeArgs,
|
|
643
|
+
pillar: v.union(
|
|
644
|
+
v.literal("market"),
|
|
645
|
+
v.literal("competition"),
|
|
646
|
+
v.literal("product"),
|
|
647
|
+
v.literal("team"),
|
|
648
|
+
v.literal("financials"),
|
|
649
|
+
v.literal("regulatory"),
|
|
650
|
+
v.literal("timing"),
|
|
651
|
+
v.literal("customer"),
|
|
652
|
+
v.literal("technology"),
|
|
653
|
+
v.literal("distribution"),
|
|
654
|
+
v.literal("deal"),
|
|
655
|
+
v.literal("risks"),
|
|
656
|
+
v.literal("other")
|
|
657
|
+
),
|
|
658
|
+
status: v.optional(
|
|
659
|
+
v.union(
|
|
660
|
+
v.literal("active"),
|
|
661
|
+
v.literal("superseded"),
|
|
662
|
+
v.literal("archived")
|
|
663
|
+
)
|
|
664
|
+
)
|
|
665
|
+
},
|
|
666
|
+
returns: permissiveReturn,
|
|
667
|
+
handler: async (ctx, args) => {
|
|
668
|
+
if (!args.projectId && !args.topicId) {
|
|
669
|
+
return [];
|
|
670
|
+
}
|
|
671
|
+
let scope;
|
|
672
|
+
try {
|
|
673
|
+
scope = await resolveTopicProjectScope(ctx, {
|
|
674
|
+
projectId: args.projectId,
|
|
675
|
+
topicId: args.topicId
|
|
676
|
+
});
|
|
677
|
+
} catch (error) {
|
|
678
|
+
debugGraphPrimitiveFallback(
|
|
679
|
+
"[epistemicBeliefs] Failed to resolve criticality scope",
|
|
680
|
+
{
|
|
681
|
+
error,
|
|
682
|
+
projectId: args.projectId,
|
|
683
|
+
topicId: args.topicId
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
return [];
|
|
687
|
+
}
|
|
688
|
+
const nodes = await ctx.db.query("epistemicNodes").withIndex(
|
|
689
|
+
"by_topic_type",
|
|
690
|
+
(q) => q.eq("topicId", scope.topicId).eq("nodeType", "belief")
|
|
691
|
+
).collect();
|
|
692
|
+
return nodes.filter((n) => {
|
|
693
|
+
const metadata = n.metadata;
|
|
694
|
+
const matchesPillar = metadata?.pillar === args.pillar;
|
|
695
|
+
const matchesStatus = args.status ? n.status === args.status : n.status === "active";
|
|
696
|
+
return matchesPillar && matchesStatus;
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
var getWorktreeCluster = query({
|
|
701
|
+
args: {
|
|
702
|
+
worktreeId: v.string(),
|
|
703
|
+
userId: v.optional(v.string())
|
|
704
|
+
},
|
|
705
|
+
returns: permissiveReturn,
|
|
706
|
+
handler: async (ctx, args) => {
|
|
707
|
+
const worktree = await ctx.db.get(args.worktreeId);
|
|
708
|
+
if (!worktree) {
|
|
709
|
+
return { beliefs: [], edges: [], beliefCount: 0 };
|
|
710
|
+
}
|
|
711
|
+
const clusterLinks = await ctx.db.query("worktreeBeliefCluster").withIndex("by_worktree", (q) => q.eq("worktreeId", args.worktreeId)).collect();
|
|
712
|
+
const beliefIds = new Set(clusterLinks.map((l) => String(l.beliefId)));
|
|
713
|
+
const beliefs = [];
|
|
714
|
+
for (const link of clusterLinks) {
|
|
715
|
+
const node = await ctx.db.get(link.beliefId);
|
|
716
|
+
if (node) beliefs.push(node);
|
|
717
|
+
}
|
|
718
|
+
const clusterEdges = [];
|
|
719
|
+
for (const beliefId of beliefIds) {
|
|
720
|
+
const outEdges = await ctx.db.query("epistemicEdges").filter(
|
|
721
|
+
(q) => q.eq(q.field("fromNodeId"), beliefId)
|
|
722
|
+
).collect();
|
|
723
|
+
for (const edge of outEdges) {
|
|
724
|
+
if (beliefIds.has(String(edge.toNodeId))) {
|
|
725
|
+
clusterEdges.push({
|
|
726
|
+
fromNodeId: String(edge.fromNodeId),
|
|
727
|
+
toNodeId: String(edge.toNodeId),
|
|
728
|
+
edgeType: edge.edgeType,
|
|
729
|
+
weight: edge.weight,
|
|
730
|
+
context: edge.context
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
beliefs,
|
|
737
|
+
edges: clusterEdges,
|
|
738
|
+
beliefCount: beliefs.length
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
export { batchUpdateCriticality, deleteRelationship, getByCriticality, getByPillar, getByProjectSystem, getUnanalyzed, getWorktreeCluster, updateCriticality };
|
|
744
|
+
//# sourceMappingURL=epistemicBeliefs.admin.js.map
|
|
745
|
+
//# sourceMappingURL=epistemicBeliefs.admin.js.map
|