@lucern/graph-primitives 1.0.22 → 1.0.23
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/dist/beliefDecay.js +46 -0
- package/dist/beliefDecay.js.map +1 -1
- package/dist/beliefEvidenceLinks.js +87 -5
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.js +41 -5
- package/dist/beliefEvidenceLinks.operational.js.map +1 -1
- package/dist/contradictions.js +46 -0
- package/dist/contradictions.js.map +1 -1
- package/dist/edgeValidation.js +66 -1
- package/dist/edgeValidation.js.map +1 -1
- package/dist/entityBridge.js +66 -1
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityLifecycle.js +90 -5
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/epistemicAnswers.js +64 -11
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.js +46 -0
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.js +46 -0
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +1 -1
- package/dist/epistemicBeliefs.confidence.js +53 -6
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.js +91 -11
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +1 -1
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +2 -2
- package/dist/epistemicBeliefs.helpers.js +46 -0
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.js +90 -10
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +103 -22
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.js +53 -6
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.js +85 -4
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.js +39 -8
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
- package/dist/epistemicContracts.evaluators.js +53 -6
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.js +54 -10
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +54 -10
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicEdges.d.ts +1 -1
- package/dist/epistemicEdges.handlers.js +48 -3
- package/dist/epistemicEdges.handlers.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +3 -3
- package/dist/epistemicEdges.js +162 -4
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.js +112 -1
- package/dist/epistemicEdges.mutations.js.map +1 -1
- package/dist/epistemicEdges.queries.js +46 -0
- package/dist/epistemicEdges.queries.js.map +1 -1
- package/dist/epistemicEdges.types.d.ts +1 -1
- package/dist/epistemicEvidence.d.ts +1 -1
- package/dist/epistemicEvidence.js +168 -14
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +1 -1
- package/dist/epistemicEvidenceHelpers.js +46 -0
- package/dist/epistemicEvidenceHelpers.js.map +1 -1
- package/dist/epistemicEvidenceMutations.js +168 -14
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicEvidenceQueries.js +46 -0
- package/dist/epistemicEvidenceQueries.js.map +1 -1
- package/dist/epistemicHelpers.js +11 -6
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicInsert.d.ts +8 -0
- package/dist/epistemicInsert.js +45 -0
- package/dist/epistemicInsert.js.map +1 -0
- package/dist/epistemicNodeCreation.js +11 -6
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/epistemicNodes.helpers.d.ts +1 -1
- package/dist/epistemicNodes.internal.js +53 -1
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +56 -4
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.js +55 -3
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicNodes.queries.js +46 -0
- package/dist/epistemicNodes.queries.js.map +1 -1
- package/dist/epistemicNodes.validators.d.ts +1 -1
- package/dist/epistemicQuestions.conviction.js +46 -0
- package/dist/epistemicQuestions.conviction.js.map +1 -1
- package/dist/epistemicQuestions.create.js +58 -7
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.d.ts +1 -1
- package/dist/epistemicQuestions.evidence.js +53 -2
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.helpers.d.ts +1 -1
- package/dist/epistemicQuestions.helpers.js +46 -0
- package/dist/epistemicQuestions.helpers.js.map +1 -1
- package/dist/epistemicQuestions.js +60 -9
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.js +46 -0
- package/dist/epistemicQuestions.lifecycle.js.map +1 -1
- package/dist/epistemicQuestions.queries.js +46 -0
- package/dist/epistemicQuestions.queries.js.map +1 -1
- package/dist/epistemicQuestions.sprint.js +46 -0
- package/dist/epistemicQuestions.sprint.js.map +1 -1
- package/dist/epistemicQuestions.tail.js +53 -2
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/epistemicSources.js +53 -2
- package/dist/epistemicSources.js.map +1 -1
- package/dist/helpers.js +66 -1
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +304 -76
- package/dist/index.js.map +1 -1
- package/dist/proof-attestation.json +1 -1
- package/dist/questionEvidenceLinks.js +46 -0
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/scopeResolverCompat.d.ts +1 -1
- package/dist/scopeResolverCompat.js +46 -0
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/{topicScope-By_zp4tt.d.ts → topicScope-7zhyeGl7.d.ts} +1 -1
- package/dist/topicScope.d.ts +1 -1
- package/dist/topicScope.js +46 -0
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.js +46 -0
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.d.ts +1 -1
- package/dist/workspaceIsolation.js +46 -0
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -4
package/dist/epistemicAnswers.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { v } from 'convex/values';
|
|
2
2
|
import { componentsGeneric, anyApi, mutationGeneric, internalMutationGeneric, queryGeneric } from 'convex/server';
|
|
3
3
|
import { checkScopeAccess } from '@lucern/access-control/access';
|
|
4
|
-
import { generateGlobalId } from '@lucern/contracts/ids';
|
|
4
|
+
import { generateGlobalId, assertUuidV7Identity } from '@lucern/contracts/ids';
|
|
5
5
|
import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
|
|
6
|
+
import '@lucern/contracts';
|
|
6
7
|
|
|
7
8
|
// src/epistemicAnswers.ts
|
|
8
9
|
var api = anyApi;
|
|
@@ -26,6 +27,35 @@ function debugGraphPrimitiveFallback(message, context) {
|
|
|
26
27
|
|
|
27
28
|
// src/topicScope.ts
|
|
28
29
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
30
|
+
async function resolveTopicNodeScopeOrNull(ctx, ref) {
|
|
31
|
+
if (!ctx?.db || typeof ctx.db.query !== "function") {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
let node = null;
|
|
35
|
+
try {
|
|
36
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
|
|
37
|
+
if (byGlobalId && byGlobalId.nodeType === "topic") {
|
|
38
|
+
node = byGlobalId;
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
debugGraphPrimitiveFallback(
|
|
42
|
+
"[topicScope] topic-node scope lookup by globalId failed",
|
|
43
|
+
{ error, ref }
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (!node) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
|
|
50
|
+
if (!scopeKey) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
topicId: scopeKey,
|
|
55
|
+
projectId: asMappedProjectId(node),
|
|
56
|
+
source: "topic_node"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
29
59
|
function asMappedProjectId(topic) {
|
|
30
60
|
if (!topic) {
|
|
31
61
|
return;
|
|
@@ -166,6 +196,13 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
166
196
|
) ?? null;
|
|
167
197
|
}
|
|
168
198
|
if (!topic) {
|
|
199
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
200
|
+
ctx,
|
|
201
|
+
String(args.topicId)
|
|
202
|
+
);
|
|
203
|
+
if (nodeScope) {
|
|
204
|
+
return nodeScope;
|
|
205
|
+
}
|
|
169
206
|
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
170
207
|
}
|
|
171
208
|
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
@@ -236,6 +273,16 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
236
273
|
source: "project_mapped_topic"
|
|
237
274
|
};
|
|
238
275
|
}
|
|
276
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
277
|
+
ctx,
|
|
278
|
+
String(args.projectId)
|
|
279
|
+
);
|
|
280
|
+
if (nodeScope) {
|
|
281
|
+
return {
|
|
282
|
+
...nodeScope,
|
|
283
|
+
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
284
|
+
};
|
|
285
|
+
}
|
|
239
286
|
throw new Error(
|
|
240
287
|
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
241
288
|
);
|
|
@@ -281,6 +328,12 @@ async function resolveScope(ctx, args) {
|
|
|
281
328
|
return null;
|
|
282
329
|
}
|
|
283
330
|
}
|
|
331
|
+
async function insertEpistemicNode(ctx, doc) {
|
|
332
|
+
assertUuidV7Identity("epistemicNodes", doc.globalId);
|
|
333
|
+
return ctx.db.insert("epistemicNodes", doc);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/epistemicAnswers.ts
|
|
284
337
|
function generateContentHash(text) {
|
|
285
338
|
const content = `answer:${text.trim().toLowerCase().replace(/\s+/g, " ").slice(0, 500)}`;
|
|
286
339
|
let hash = 5381;
|
|
@@ -356,7 +409,7 @@ var create = mutation({
|
|
|
356
409
|
}
|
|
357
410
|
}
|
|
358
411
|
}
|
|
359
|
-
const nodeId = await ctx
|
|
412
|
+
const nodeId = await insertEpistemicNode(ctx, {
|
|
360
413
|
globalId,
|
|
361
414
|
projectId: topicId,
|
|
362
415
|
topicId: questionNode.topicId,
|
|
@@ -411,7 +464,7 @@ var create = mutation({
|
|
|
411
464
|
}
|
|
412
465
|
);
|
|
413
466
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
414
|
-
globalId:
|
|
467
|
+
globalId: generateGlobalId(),
|
|
415
468
|
fromGlobalId: globalId,
|
|
416
469
|
toGlobalId: questionNode.globalId,
|
|
417
470
|
edgeType: "responds_to",
|
|
@@ -425,7 +478,7 @@ var create = mutation({
|
|
|
425
478
|
});
|
|
426
479
|
for (const oldAnswer of activeAnswersForQuestion) {
|
|
427
480
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
428
|
-
globalId:
|
|
481
|
+
globalId: generateGlobalId(),
|
|
429
482
|
fromGlobalId: globalId,
|
|
430
483
|
toGlobalId: oldAnswer.globalId,
|
|
431
484
|
edgeType: "supersedes",
|
|
@@ -442,7 +495,7 @@ var create = mutation({
|
|
|
442
495
|
const evNode = await ctx.db.get(evId);
|
|
443
496
|
if (evNode) {
|
|
444
497
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
445
|
-
globalId:
|
|
498
|
+
globalId: generateGlobalId(),
|
|
446
499
|
fromGlobalId: globalId,
|
|
447
500
|
toGlobalId: evNode.globalId,
|
|
448
501
|
edgeType: "derived_from",
|
|
@@ -464,7 +517,7 @@ var create = mutation({
|
|
|
464
517
|
const evidenceNode = await ctx.db.get(edge.fromNodeId);
|
|
465
518
|
if (evidenceNode) {
|
|
466
519
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
467
|
-
globalId:
|
|
520
|
+
globalId: generateGlobalId(),
|
|
468
521
|
fromGlobalId: evidenceNode.globalId,
|
|
469
522
|
toGlobalId: globalId,
|
|
470
523
|
edgeType: "derived_from",
|
|
@@ -556,7 +609,7 @@ var createInternal = internalMutation({
|
|
|
556
609
|
}
|
|
557
610
|
}
|
|
558
611
|
}
|
|
559
|
-
const nodeId = await ctx
|
|
612
|
+
const nodeId = await insertEpistemicNode(ctx, {
|
|
560
613
|
globalId,
|
|
561
614
|
projectId: topicId,
|
|
562
615
|
topicId: questionNode.topicId,
|
|
@@ -612,7 +665,7 @@ var createInternal = internalMutation({
|
|
|
612
665
|
}
|
|
613
666
|
);
|
|
614
667
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
615
|
-
globalId:
|
|
668
|
+
globalId: generateGlobalId(),
|
|
616
669
|
fromGlobalId: globalId,
|
|
617
670
|
toGlobalId: questionNode.globalId,
|
|
618
671
|
edgeType: "responds_to",
|
|
@@ -626,7 +679,7 @@ var createInternal = internalMutation({
|
|
|
626
679
|
});
|
|
627
680
|
for (const oldAnswer of activeAnswersForQuestion) {
|
|
628
681
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
629
|
-
globalId:
|
|
682
|
+
globalId: generateGlobalId(),
|
|
630
683
|
fromGlobalId: globalId,
|
|
631
684
|
toGlobalId: oldAnswer.globalId,
|
|
632
685
|
edgeType: "supersedes",
|
|
@@ -643,7 +696,7 @@ var createInternal = internalMutation({
|
|
|
643
696
|
const evNode = await ctx.db.get(evId);
|
|
644
697
|
if (evNode) {
|
|
645
698
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
646
|
-
globalId:
|
|
699
|
+
globalId: generateGlobalId(),
|
|
647
700
|
fromGlobalId: globalId,
|
|
648
701
|
toGlobalId: evNode.globalId,
|
|
649
702
|
edgeType: "derived_from",
|
|
@@ -665,7 +718,7 @@ var createInternal = internalMutation({
|
|
|
665
718
|
const evidenceNode = await ctx.db.get(edge.fromNodeId);
|
|
666
719
|
if (evidenceNode) {
|
|
667
720
|
await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
|
|
668
|
-
globalId:
|
|
721
|
+
globalId: generateGlobalId(),
|
|
669
722
|
fromGlobalId: evidenceNode.globalId,
|
|
670
723
|
toGlobalId: globalId,
|
|
671
724
|
edgeType: "derived_from",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/convex.ts","../src/debug.ts","../src/topicScope.ts","../src/scopeResolverCompat.ts","../src/epistemicAnswers.ts"],"names":["normalizeScopeValue","v"],"mappings":"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","file":"epistemicAnswers.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;\ntype IndexRangeBuilder = {\n field(fieldName: string): string;\n eq(fieldName: string, value: unknown): IndexRangeBuilder;\n gt(fieldName: string, value: unknown): IndexRangeBuilder;\n gte(fieldName: string, value: unknown): IndexRangeBuilder;\n lt(fieldName: string, value: unknown): IndexRangeBuilder;\n lte(fieldName: string, value: unknown): IndexRangeBuilder;\n};\ntype FilterBuilder = {\n eq(left: unknown, right: unknown): unknown;\n neq(left: unknown, right: unknown): unknown;\n gt(left: unknown, right: unknown): unknown;\n gte(left: unknown, right: unknown): unknown;\n lt(left: unknown, right: unknown): unknown;\n lte(left: unknown, right: unknown): unknown;\n and(...clauses: unknown[]): unknown;\n or(...clauses: unknown[]): unknown;\n field(fieldName: string): unknown;\n};\ntype QueryInitializer<TableName extends TableNames> = {\n withIndex(\n indexName: string,\n range?: (q: any) => unknown\n ): QueryInitializer<TableName>;\n filter(predicate: (q: any) => unknown): QueryInitializer<TableName>;\n order(direction: \"asc\" | \"desc\"): QueryInitializer<TableName>;\n collect(): Promise<Doc<TableName>[]>;\n take(limit: number): Promise<Doc<TableName>[]>;\n first(): Promise<Doc<TableName> | null>;\n unique(): Promise<Doc<TableName> | null>;\n};\nexport type DatabaseReader = {\n get<TableName extends TableNames>(\n id: Id<TableName>\n ): Promise<Doc<TableName> | null>;\n query<TableName extends TableNames>(\n tableName: TableName\n ): QueryInitializer<TableName>;\n normalizeId?<TableName extends TableNames>(\n tableName: TableName,\n id: string\n ): Id<TableName> | null;\n};\nexport type DatabaseWriter = DatabaseReader & {\n insert<TableName extends TableNames>(\n tableName: TableName,\n value: Record<string, unknown>\n ): Promise<Id<TableName>>;\n patch<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n replace<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n delete<TableName extends TableNames>(id: Id<TableName>): Promise<void>;\n};\ntype Scheduler = {\n runAfter(delayMs: number, functionReference: unknown, args?: unknown): Promise<void>;\n};\ntype AuthReader = {\n getUserIdentity(): Promise<unknown>;\n};\ntype RuntimeInvoker = {\n runQuery(functionReference: unknown, args?: unknown): Promise<any>;\n runMutation(functionReference: unknown, args?: unknown): Promise<any>;\n runAction(functionReference: unknown, args?: unknown): Promise<any>;\n};\nexport type QueryCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseReader;\n scheduler: Scheduler;\n};\nexport type MutationCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseWriter;\n scheduler: Scheduler;\n};\nexport type ActionCtx = RuntimeInvoker & {\n auth: AuthReader;\n scheduler: Scheduler;\n};\n\ntype ConvexFunctionBuilder<Ctx> = <\n Definition extends { handler?: (ctx: Ctx, args: any) => any },\n>(\n definition: Definition\n) => any;\n\nexport const action = actionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const httpAction =\n httpActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalAction =\n internalActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalMutation =\n internalMutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const internalQuery =\n internalQueryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\nexport const mutation =\n mutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const query = queryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\n","type GraphPrimitiveDebugEnvironment = {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction isGraphPrimitiveDebugEnabled(): boolean {\n const env = (globalThis as GraphPrimitiveDebugEnvironment).process?.env;\n return (\n env?.LUCERN_COMPAT_FALLBACK_DEBUG === \"1\" ||\n env?.LUCERN_GRAPH_DEBUG === \"1\"\n );\n}\n\nexport function formatGraphPrimitiveError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n if (typeof error === \"string\") {\n return error;\n }\n if (error === null) {\n return \"null\";\n }\n if (error === undefined) {\n return \"undefined\";\n }\n try {\n return JSON.stringify(error);\n } catch {\n return Object.prototype.toString.call(error);\n }\n}\n\nexport function debugGraphPrimitiveFallback(\n message: string,\n context?: Record<string, unknown>\n): void {\n if (!isGraphPrimitiveDebugEnabled()) {\n return;\n }\n console.debug(message, context ?? {});\n}\n","/** Topic-scope resolution helpers for graph-primitive operations. */\nimport { v } from \"convex/values\";\nimport { api as appApi } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nconst LEGACY_SCOPE_FIELD = \"graphScope\" + \"ProjectId\";\n\ntype TopicDoc = Record<string, unknown> & {\n _id: Id<\"topics\">;\n globalId?: string;\n name?: string;\n depth?: number;\n createdAt?: number;\n parentTopicId?: Id<\"topics\">;\n tenantId?: string;\n workspaceId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type TopicProjectScope = {\n topicId: Id<\"topics\">;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source: \"topic\" | \"project_mapped_topic\" | \"topic_inferred\";\n};\n\ntype MaterializedTopicNodeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n metadata?: Record<string, unknown>;\n};\n\nfunction asMappedProjectId(\n topic: TopicDoc | null | undefined,\n): string | undefined {\n if (!topic) {\n return;\n }\n const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);\n if (directLegacyProjectId) {\n return directLegacyProjectId;\n }\n const metadata = (topic.metadata || {}) as Record<string, unknown>;\n const candidate =\n (metadata[LEGACY_SCOPE_FIELD] as string | undefined) ||\n (metadata.legacyProjectId as string | undefined) ||\n (metadata.projectId as string | undefined) ||\n (metadata.scopeProjectId as string | undefined);\n return candidate ? (candidate as string) : undefined;\n}\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction pickPrimaryTopic(candidates: TopicDoc[]): TopicDoc | undefined {\n return [...candidates].sort((a, b) => {\n const depthA = a.depth ?? 9999;\n const depthB = b.depth ?? 9999;\n if (depthA !== depthB) {\n return depthA - depthB;\n }\n const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;\n const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;\n if (createdA !== createdB) {\n return createdA - createdB;\n }\n return String(a.name || \"\").localeCompare(String(b.name || \"\"));\n })[0];\n}\n\nasync function findTopicsByScopeAlias(\n ctx: any,\n scopeId: string,\n): Promise<TopicDoc[]> {\n try {\n return (await ctx.db\n .query(\"topics\")\n .withIndex(\"by_graph_scope_project\", (q: any) =>\n q.eq(LEGACY_SCOPE_FIELD, scopeId),\n )\n .collect()) as TopicDoc[];\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve scope alias via index\",\n {\n error,\n scopeId,\n },\n );\n // Older Lucern dev deployments can lag index backfills while still carrying\n // the underlying topics table. Scan and filter so scope resolution keeps\n // working during the rollout.\n const topics = (await ctx.db.query(\"topics\").collect()) as TopicDoc[];\n return topics.filter((topic) => {\n const normalizedGlobalId = normalizeScopeValue(topic.globalId);\n const mappedProjectId = asMappedProjectId(topic);\n return (\n String(topic._id) === scopeId ||\n normalizedGlobalId === scopeId ||\n mappedProjectId === scopeId\n );\n });\n }\n}\n\nasync function tryResolveHostTopicById(\n ctx: any,\n topicId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.get as any, {\n id: topicId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by host query\",\n {\n error,\n topicId,\n },\n );\n return null;\n }\n}\n\nasync function tryResolveHostTopicByLegacyScope(\n ctx: any,\n legacyScopeId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.getByLegacyScopeId as any, {\n projectId: legacyScopeId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by legacy scope\",\n {\n error,\n legacyScopeId,\n },\n );\n return null;\n }\n}\n\nexport function readMaterializedTopicTableId(\n topicNode: MaterializedTopicNodeDoc | null | undefined,\n): string | undefined {\n if (!topicNode) {\n return;\n }\n\n const metadata = (topicNode.metadata || {}) as Record<string, unknown>;\n const topicTableId =\n (metadata.topicTableId as string | undefined) ||\n (metadata.topicId as string | undefined);\n\n return typeof topicTableId === \"string\" && topicTableId.trim().length > 0\n ? topicTableId.trim()\n : undefined;\n}\n\n/**\n * Walk the topic parent chain to find inherited workspaceId and tenantId.\n * Mirrors the pattern used by resolveTopicOntology for ontologyId inheritance.\n * Max depth: 10 (defensive limit against pathological nesting).\n */\nasync function resolveInheritedWorkspaceScope(\n ctx: any,\n topic: TopicDoc,\n): Promise<{ tenantId?: string; workspaceId?: string }> {\n const MAX_DEPTH = 10;\n let tenantId = normalizeScopeValue(topic.tenantId);\n let workspaceId = normalizeScopeValue(topic.workspaceId);\n\n if (tenantId && workspaceId) {\n return { tenantId, workspaceId };\n }\n\n let current: TopicDoc | null = topic;\n for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n if (!current) break;\n\n if (!tenantId) {\n tenantId = normalizeScopeValue(current.tenantId);\n }\n if (!workspaceId) {\n workspaceId = normalizeScopeValue(current.workspaceId);\n }\n if (tenantId && workspaceId) break;\n }\n\n return { tenantId, workspaceId };\n}\n\nexport async function resolveTopicProjectScope(\n ctx: any,\n args: { topicId?: Id<\"topics\"> | string; projectId?: string },\n): Promise<TopicProjectScope> {\n if (args.topicId) {\n // Try direct lookup, fall back to the legacy mapped-project bridge\n let topic: TopicDoc | null = null;\n try {\n topic = (await ctx.db.get(\n args.topicId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load topic by direct id\",\n {\n error,\n topicId: args.topicId,\n },\n );\n // Not a valid topics table ID\n }\n if (!topic) {\n topic = await tryResolveHostTopicById(ctx, String(args.topicId));\n }\n if (!topic) {\n // Try as legacy projectId / globalId via the mapped-project bridge.\n topic =\n pickPrimaryTopic(\n await findTopicsByScopeAlias(ctx, String(args.topicId)),\n ) ?? null;\n }\n if (!topic) {\n throw new Error(`Topic not found: ${String(args.topicId)}`);\n }\n const inherited = await resolveInheritedWorkspaceScope(ctx, topic);\n const mapped = asMappedProjectId(topic);\n if (mapped) {\n return {\n topicId: topic._id,\n projectId: mapped,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n return {\n topicId: topic._id,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n\n if (args.projectId) {\n let directTopic: TopicDoc | null = null;\n try {\n directTopic = (await ctx.db.get(\n args.projectId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load direct project topic\",\n {\n error,\n projectId: args.projectId,\n },\n );\n // Not a valid topics table ID, continue to legacy graph-scope lookup.\n }\n\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n const topics = await findTopicsByScopeAlias(ctx, args.projectId);\n const primary = pickPrimaryTopic(topics);\n if (primary) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, primary);\n return {\n topicId: primary._id,\n projectId: args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"project_mapped_topic\",\n };\n }\n throw new Error(\n `Legacy project scope ${String(args.projectId)} has no mapped topic.`,\n );\n }\n\n throw new Error(\n \"Missing scope: provide topicId (preferred) or legacy projectId alias.\",\n );\n}\n\n/** Shared scope args for graph-primitive functions. topicId is canonical; projectId is a legacy alias. */\nexport const optionalScopeArgs = {\n projectId: v.optional(v.string()),\n topicId: v.optional(v.string()),\n} as const;\n","import { optionalScopeArgs, resolveTopicProjectScope } from \"./topicScope\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nexport const scopeArgs = optionalScopeArgs;\n\nexport type ResolvedScope = Awaited<\n ReturnType<typeof resolveTopicProjectScope>\n>;\nexport type SoftResolvedScope = {\n topicId?: string;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source?: ResolvedScope[\"source\"];\n};\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nexport async function resolveScope(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null },\n): Promise<ResolvedScope | null> {\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n if (!topicId && !projectId) {\n return null;\n }\n\n try {\n return await resolveTopicProjectScope(ctx, {\n topicId,\n projectId,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[scopeResolverCompat] Failed to resolve scope\",\n {\n error,\n topicId,\n projectId,\n },\n );\n return null;\n }\n}\n\nexport async function resolveScopeSoft(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null },\n): Promise<SoftResolvedScope> {\n const resolved = await resolveScope(ctx, args);\n if (resolved) {\n const topicId = normalizeScopeValue(resolved.topicId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(resolved.projectId ? { projectId: resolved.projectId } : {}),\n ...(resolved.tenantId ? { tenantId: resolved.tenantId } : {}),\n ...(resolved.workspaceId ? { workspaceId: resolved.workspaceId } : {}),\n ...(resolved.source ? { source: resolved.source } : {}),\n };\n }\n\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(projectId ? { projectId } : {}),\n };\n}\n","/**\n * Epistemic Answers API\n *\n * Answers are first-class L2 nodes in the epistemic spine.\n * Every answer is an immutable snapshot — new answers create new nodes,\n * old ones get `superseded`. This gives full version history and lets\n * answers have their own edges in the knowledge graph.\n *\n * Edge: Answer —responds_to→ Question\n * Edge: Answer —based_on→ Evidence (for each supporting evidence)\n * Edge: NewAnswer —supersedes→ OldAnswer (for versioning)\n *\n * @see /docs/epistemic-invariants/00-epistemic-invariants.md\n */\n\nimport { v } from \"convex/values\";\nimport { api, internal } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { internalMutation, mutation, query } from \"./convex\";\nimport type { MutationCtx, QueryCtx } from \"./convex\";\nimport { checkScopeAccess } from \"@lucern/access-control/access\";\nimport { generateGlobalId } from \"./globalId\";\nimport { resolveScope, scopeArgs } from \"./scopeResolverCompat\";\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\ntype AnswerNodeRow = {\n _id: Id<\"epistemicNodes\">;\n globalId: string;\n canonicalText?: string;\n metadata?: Record<string, unknown>;\n status?: string;\n createdBy?: string;\n createdAt?: number;\n supersededBy?: Id<\"epistemicNodes\">;\n topicId?: Id<\"topics\">;\n projectId?: string;\n nodeType?: string;\n};\n\ntype IndexQuery = {\n eq(field: string, value: unknown): IndexQuery;\n};\n\ntype FilterQuery = {\n field(name: string): unknown;\n eq(left: unknown, right: unknown): unknown;\n or(...conditions: unknown[]): unknown;\n};\n\nfunction generateContentHash(text: string): string {\n const content = `answer:${text.trim().toLowerCase().replace(/\\s+/g, \" \").slice(0, 500)}`;\n let hash = 5381;\n for (let i = 0; i < content.length; i++) {\n hash = (hash << 5) + hash + content.charCodeAt(i);\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\n// =============================================================================\n// CREATE\n// =============================================================================\n\n/**\n * Create a new answer node for a question.\n *\n * 1. Validates the question exists\n * 2. Determines version number\n * 3. Supersedes previous active answer (if any)\n * 4. Creates the answer node\n * 5. Creates responds_to edge (Answer → Question)\n * 6. Creates supersedes edge (NewAnswer → OldAnswer) if versioning\n * 7. Creates based_on edges (Answer → Evidence) for each evidence node\n * 8. Updates question's answerQuality field\n * 9. Logs to epistemicAudit\n */\nexport const create = mutation({\n args: {\n ...scopeArgs,\n questionNodeId: v.id(\"epistemicNodes\"),\n answerText: v.string(),\n confidence: v.optional(\n v.union(\n v.literal(\"definitive\"),\n v.literal(\"strong\"),\n v.literal(\"moderate\"),\n v.literal(\"weak\"),\n v.literal(\"speculative\")\n )\n ),\n evidenceNodeIds: v.optional(v.array(v.id(\"epistemicNodes\"))),\n answerSource: v.optional(v.string()),\n sprintId: v.optional(v.string()),\n userId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = scope?.topicId ? String(scope.topicId) : (args.topicId || \"\");\n await checkScopeAccess(ctx, topicId, args.userId);\n\n // 1. Validate question exists\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n throw new Error(\"Question node not found or not a question type\");\n }\n\n const now = Date.now();\n const globalId = generateGlobalId();\n const contentHash = generateContentHash(args.answerText);\n\n // 2. Find current active answer(s) for this question to determine version\n // TC-C: Use by_topic_type (canonical)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId ?? topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n const activeAnswersForQuestion = existingAnswers.filter((n) => {\n const meta = (n.metadata || {}) as Record<string, unknown>;\n return (\n meta.questionNodeId === args.questionNodeId &&\n meta.isLatest === true &&\n n.status === \"active\"\n );\n });\n\n const versionNumber =\n activeAnswersForQuestion.length > 0\n ? Math.max(\n ...activeAnswersForQuestion.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return (meta.versionNumber as number) || 0;\n })\n ) + 1\n : 1;\n\n // 3. Supersede previous active answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n status: \"superseded\",\n supersededBy: undefined, // Will be set after insert\n updatedAt: now,\n metadata: {\n ...((oldAnswer.metadata as Record<string, unknown>) || {}),\n isLatest: false,\n },\n });\n }\n\n // Gather evidence globalIds\n const evidenceGlobalIds: string[] = [];\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n evidenceGlobalIds.push(evNode.globalId);\n }\n }\n }\n\n // 4. Insert new answer node — inherit topicId from the question\n const nodeId = await ctx.db.insert(\"epistemicNodes\", {\n globalId,\n projectId: topicId,\n topicId: questionNode.topicId,\n nodeType: \"answer\",\n epistemicLayer: \"L2\",\n canonicalText: args.answerText,\n contentHash,\n status: \"active\",\n sourceType: args.answerSource === \"human\" ? \"human\" : \"ai_generated\",\n createdBy: args.userId,\n createdAt: now,\n updatedAt: now,\n metadata: {\n questionGlobalId: questionNode.globalId,\n questionNodeId: String(args.questionNodeId),\n versionNumber,\n isLatest: true,\n evidenceGlobalIds,\n evidenceCount: evidenceGlobalIds.length,\n answeredBy: args.userId,\n answerSource: args.answerSource || \"human\",\n sprintId: args.sprintId,\n },\n });\n\n // Update supersededBy on old answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n supersededBy: nodeId,\n });\n }\n\n // 5. Schedule Neo4j sync\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await ctx.scheduler.runAfter(\n 0,\n api.embeddingActions.generateEpistemicNodeEmbedding,\n {\n nodeId,\n projectId: topicId,\n topicId: questionNode.topicId ? String(questionNode.topicId) : undefined,\n createdBy: args.userId,\n nodeType: \"answer\",\n text: args.answerText.slice(0, 20_000),\n }\n );\n await ctx.scheduler.runAfter(\n 0,\n internal.sprints.embedProjectThemeCollectiveInternal,\n {\n projectId: topicId,\n userId: args.userId,\n }\n );\n\n // 6. Create responds_to edge (Answer → Question)\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: questionNode.globalId,\n edgeType: \"responds_to\",\n weight: 1.0,\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"question\",\n fromLayer: \"L2\",\n toLayer: \"L3\",\n });\n\n // 7. Create supersedes edges (NewAnswer → OldAnswer)\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: oldAnswer.globalId,\n edgeType: \"supersedes\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n\n // 8. Create based_on edges (Answer → Evidence)\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: evNode.globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"evidence\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n }\n\n // 9. Re-edge: evidence that \"derived_from\" the question now also gets \"derived_from\" → answer\n const evidenceEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_to_type\", (q: IndexQuery) =>\n q.eq(\"toNodeId\", args.questionNodeId).eq(\"edgeType\", \"derived_from\")\n )\n .collect();\n\n for (const edge of evidenceEdges) {\n const evidenceNode = await ctx.db.get(edge.fromNodeId);\n if (evidenceNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: evidenceNode.globalId,\n toGlobalId: globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"evidence\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n\n // 10. Update question's answerQuality\n const answerQuality = args.confidence || \"moderate\";\n await ctx.db.patch(args.questionNodeId, {\n answerQuality,\n updatedAt: now,\n });\n\n // 11. Log to audit\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"answer\",\n entityId: nodeId,\n changeType: \"created\",\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n projectId: topicId,\n newState: {\n answerText: args.answerText.slice(0, 200),\n versionNumber,\n questionNodeId: String(args.questionNodeId),\n confidence: answerQuality,\n },\n });\n\n return { nodeId, globalId, versionNumber };\n },\n});\n\n// =============================================================================\n// CREATE INTERNAL (for scheduler / other modules)\n// =============================================================================\n\n/**\n * Internal mutation for creating answer nodes.\n * Called from epistemicQuestions.updateStatus when status === \"answered\".\n */\nexport const createInternal = internalMutation({\n args: {\n ...scopeArgs,\n questionNodeId: v.id(\"epistemicNodes\"),\n answerText: v.string(),\n confidence: v.optional(v.string()),\n evidenceNodeIds: v.optional(v.array(v.id(\"epistemicNodes\"))),\n answerSource: v.optional(v.string()),\n sprintId: v.optional(v.string()),\n userId: v.string(),\n backfilledFromQuestionId: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = scope?.topicId ? String(scope.topicId) : (args.topicId || \"\");\n\n // Validate question exists\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n throw new Error(\"Question node not found or not a question type\");\n }\n\n const now = Date.now();\n const globalId = generateGlobalId();\n const contentHash = generateContentHash(args.answerText);\n\n // Find current active answers for this question (TC-C: use topic index)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId ?? topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n const activeAnswersForQuestion = existingAnswers.filter((n) => {\n const meta = (n.metadata || {}) as Record<string, unknown>;\n return (\n meta.questionNodeId === String(args.questionNodeId) &&\n meta.isLatest === true &&\n n.status === \"active\"\n );\n });\n\n const versionNumber =\n activeAnswersForQuestion.length > 0\n ? Math.max(\n ...activeAnswersForQuestion.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return (meta.versionNumber as number) || 0;\n })\n ) + 1\n : 1;\n\n // Supersede previous active answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n status: \"superseded\",\n updatedAt: now,\n metadata: {\n ...((oldAnswer.metadata as Record<string, unknown>) || {}),\n isLatest: false,\n },\n });\n }\n\n // Gather evidence globalIds\n const evidenceGlobalIds: string[] = [];\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n evidenceGlobalIds.push(evNode.globalId);\n }\n }\n }\n\n // Insert answer node — inherit topicId from the question (TC-C fix)\n const nodeId = await ctx.db.insert(\"epistemicNodes\", {\n globalId,\n projectId: topicId,\n topicId: questionNode.topicId,\n nodeType: \"answer\",\n epistemicLayer: \"L2\",\n canonicalText: args.answerText,\n contentHash,\n status: \"active\",\n sourceType: args.answerSource === \"human\" ? \"human\" : \"ai_generated\",\n createdBy: args.userId,\n createdAt: now,\n updatedAt: now,\n metadata: {\n questionGlobalId: questionNode.globalId,\n questionNodeId: String(args.questionNodeId),\n versionNumber,\n isLatest: true,\n evidenceGlobalIds,\n evidenceCount: evidenceGlobalIds.length,\n answeredBy: args.userId,\n answerSource: args.answerSource || \"human\",\n sprintId: args.sprintId,\n backfilledFromQuestionId: args.backfilledFromQuestionId,\n },\n });\n\n // Update supersededBy on old answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n supersededBy: nodeId,\n });\n }\n\n // Schedule Neo4j sync\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await ctx.scheduler.runAfter(\n 0,\n api.embeddingActions.generateEpistemicNodeEmbedding,\n {\n nodeId,\n projectId: topicId,\n topicId: questionNode.topicId ? String(questionNode.topicId) : undefined,\n createdBy: args.userId,\n nodeType: \"answer\",\n text: args.answerText.slice(0, 20_000),\n }\n );\n await ctx.scheduler.runAfter(\n 0,\n internal.sprints.embedProjectThemeCollectiveInternal,\n {\n projectId: topicId,\n userId: args.userId,\n }\n );\n\n // Create responds_to edge (Answer → Question)\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: questionNode.globalId,\n edgeType: \"responds_to\",\n weight: 1.0,\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"question\",\n fromLayer: \"L2\",\n toLayer: \"L3\",\n });\n\n // Create supersedes edges\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: oldAnswer.globalId,\n edgeType: \"supersedes\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n\n // Create based_on edges (Answer → Evidence)\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: globalId,\n toGlobalId: evNode.globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"evidence\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n }\n\n // Re-edge: evidence that \"derived_from\" the question now also gets \"derived_from\" → answer\n const evidenceEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_to_type\", (q: IndexQuery) =>\n q.eq(\"toNodeId\", args.questionNodeId).eq(\"edgeType\", \"derived_from\")\n )\n .collect();\n\n for (const edge of evidenceEdges) {\n const evidenceNode = await ctx.db.get(edge.fromNodeId);\n if (evidenceNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: crypto.randomUUID(),\n fromGlobalId: evidenceNode.globalId,\n toGlobalId: globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"evidence\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n\n // Update question's answerQuality\n const answerQuality = args.confidence || \"moderate\";\n await ctx.db.patch(args.questionNodeId, {\n answerQuality,\n updatedAt: now,\n });\n\n // Log to audit\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"answer\",\n entityId: nodeId,\n changeType: \"created\",\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n projectId: topicId,\n newState: {\n answerText: args.answerText.slice(0, 200),\n versionNumber,\n questionNodeId: String(args.questionNodeId),\n backfilled: !!args.backfilledFromQuestionId,\n },\n });\n\n return { nodeId, globalId, versionNumber };\n },\n});\n\n// =============================================================================\n// QUERIES\n// =============================================================================\n\n/**\n * Get all answers for a question, optionally including superseded.\n */\nexport const getByQuestion = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n includeSuperseded: v.optional(v.boolean()),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return [];\n }\n\n const topicId = questionNode.topicId;\n if (!topicId) {\n return [];\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n // Filter to answers for this question\n const questionIdStr = String(args.questionNodeId);\n const filtered = answers.filter((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr;\n });\n\n if (!args.includeSuperseded) {\n return filtered.filter((a) => a.status === \"active\");\n }\n\n // Sort by version number (newest first)\n filtered.sort((a, b) => {\n const metaA = (a.metadata || {}) as Record<string, unknown>;\n const metaB = (b.metadata || {}) as Record<string, unknown>;\n return (\n ((metaB.versionNumber as number) || 0) -\n ((metaA.versionNumber as number) || 0)\n );\n });\n\n return filtered;\n },\n});\n\n/**\n * Get the single active (latest) answer for a question.\n */\nexport const getLatestForQuestion = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return null;\n }\n\n // Filter status === \"active\" at DB level to reduce JS-side work.\n // metadata.questionNodeId filtering must stay in JS (no index on metadata fields).\n if (!questionNode.topicId) {\n return null;\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId!).eq(\"nodeType\", \"answer\")\n )\n .filter((q: FilterQuery) => q.eq(q.field(\"status\"), \"active\"))\n .collect()) as AnswerNodeRow[];\n\n const questionIdStr = String(args.questionNodeId);\n const latest = answers.find((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr && meta.isLatest === true;\n });\n\n return latest || null;\n },\n});\n\n/**\n * Get full version history for answers to a question.\n * Returns answers ordered by version number (newest first).\n */\nexport const getVersionHistory = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return [];\n }\n\n // Filter status at DB level; metadata.questionNodeId must filter in JS (no index on metadata).\n if (!questionNode.topicId) {\n return [];\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId!).eq(\"nodeType\", \"answer\")\n )\n .filter((q: FilterQuery) =>\n q.or(\n q.eq(q.field(\"status\"), \"active\"),\n q.eq(q.field(\"status\"), \"superseded\")\n )\n )\n .collect()) as AnswerNodeRow[];\n\n const questionIdStr = String(args.questionNodeId);\n const history = answers\n .filter((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr;\n })\n .map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return {\n _id: a._id,\n globalId: a.globalId,\n answerText: a.canonicalText,\n versionNumber: (meta.versionNumber as number) || 1,\n isLatest: (meta.isLatest as boolean) || false,\n status: a.status,\n answeredBy: (meta.answeredBy as string) || a.createdBy,\n answerSource: meta.answerSource as string | undefined,\n evidenceCount: (meta.evidenceCount as number) || 0,\n createdAt: a.createdAt,\n supersededBy: a.supersededBy,\n };\n })\n .sort((a, b) => b.versionNumber - a.versionNumber);\n\n return history;\n },\n});\n\n// =============================================================================\n// BACKFILL: Create answer nodes for questions that have answer text but no node\n// =============================================================================\n\n/**\n * Backfill answer nodes for questions that have answer text in metadata\n * but never had an answer node created (due to the QuestionAnswerEditor bug\n * where saveAnswer passed wrong params to updateStatus).\n *\n * Run once via Convex dashboard:\n * internal.epistemicAnswers.backfillAnswerNodes({ projectId, userId })\n */\nexport const backfillAnswerNodes = internalMutation({\n args: {\n ...scopeArgs,\n userId: v.string(),\n dryRun: v.optional(v.boolean()),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = (scope?.topicId ??\n args.topicId) as Id<\"topics\">;\n const dryRun = args.dryRun ?? false;\n\n // 1. Find all question nodes with answer text in metadata (TC-C: prefer topic)\n const questions = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"question\")\n )\n .collect()) as AnswerNodeRow[];\n\n const questionsWithAnswers = questions.filter((q) => {\n const meta = (q.metadata || {}) as Record<string, unknown>;\n const answer = meta.answer as string | undefined;\n return answer && answer.trim().length > 0;\n });\n\n // 2. Find all existing answer nodes (TC-C: use topic index since projectId is now topicId)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n // Build set of question IDs that already have answer nodes\n const questionIdsWithAnswerNodes = new Set(\n existingAnswers.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId as string;\n })\n );\n\n // 3. Filter to questions that need backfill\n const needsBackfill = questionsWithAnswers.filter(\n (q) => !questionIdsWithAnswerNodes.has(String(q._id))\n );\n\n console.log(\n `[backfillAnswerNodes] Found ${questionsWithAnswers.length} questions with answers, ` +\n `${questionIdsWithAnswerNodes.size} already have answer nodes, ` +\n `${needsBackfill.length} need backfill. dryRun=${dryRun}`\n );\n\n if (dryRun) {\n return {\n questionsWithAnswers: questionsWithAnswers.length,\n alreadyHaveNodes: questionIdsWithAnswerNodes.size,\n needsBackfill: needsBackfill.length,\n questions: needsBackfill.map((q) => ({\n id: q._id,\n globalId: q.globalId,\n text: q.canonicalText?.slice(0, 80),\n answer: (q.metadata?.answer as string | undefined)?.slice(0, 80),\n })),\n };\n }\n\n // 4. Create answer nodes for each\n let created = 0;\n for (const question of needsBackfill) {\n const meta = (question.metadata || {}) as Record<string, unknown>;\n const answerText = meta.answer as string;\n\n await ctx.scheduler.runAfter(\n 0,\n internal.epistemicAnswers.createInternal,\n {\n topicId: String(topicId), // TC-C: migrated from projectId\n questionNodeId: question._id,\n answerText,\n answerSource: (meta.answeredBy as string) ? \"human\" : \"ai_generated\",\n userId: (meta.answeredBy as string) || args.userId,\n backfilledFromQuestionId: String(question._id),\n }\n );\n created++;\n }\n\n return {\n questionsWithAnswers: questionsWithAnswers.length,\n alreadyHaveNodes: questionIdsWithAnswerNodes.size,\n backfilled: created,\n };\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/convex.ts","../src/debug.ts","../src/topicScope.ts","../src/scopeResolverCompat.ts","../src/epistemicInsert.ts","../src/epistemicAnswers.ts"],"names":["normalizeScopeValue","v"],"mappings":"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","file":"epistemicAnswers.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;\ntype IndexRangeBuilder = {\n field(fieldName: string): string;\n eq(fieldName: string, value: unknown): IndexRangeBuilder;\n gt(fieldName: string, value: unknown): IndexRangeBuilder;\n gte(fieldName: string, value: unknown): IndexRangeBuilder;\n lt(fieldName: string, value: unknown): IndexRangeBuilder;\n lte(fieldName: string, value: unknown): IndexRangeBuilder;\n};\ntype FilterBuilder = {\n eq(left: unknown, right: unknown): unknown;\n neq(left: unknown, right: unknown): unknown;\n gt(left: unknown, right: unknown): unknown;\n gte(left: unknown, right: unknown): unknown;\n lt(left: unknown, right: unknown): unknown;\n lte(left: unknown, right: unknown): unknown;\n and(...clauses: unknown[]): unknown;\n or(...clauses: unknown[]): unknown;\n field(fieldName: string): unknown;\n};\ntype QueryInitializer<TableName extends TableNames> = {\n withIndex(\n indexName: string,\n range?: (q: any) => unknown\n ): QueryInitializer<TableName>;\n filter(predicate: (q: any) => unknown): QueryInitializer<TableName>;\n order(direction: \"asc\" | \"desc\"): QueryInitializer<TableName>;\n collect(): Promise<Doc<TableName>[]>;\n take(limit: number): Promise<Doc<TableName>[]>;\n first(): Promise<Doc<TableName> | null>;\n unique(): Promise<Doc<TableName> | null>;\n};\nexport type DatabaseReader = {\n get<TableName extends TableNames>(\n id: Id<TableName>\n ): Promise<Doc<TableName> | null>;\n query<TableName extends TableNames>(\n tableName: TableName\n ): QueryInitializer<TableName>;\n normalizeId?<TableName extends TableNames>(\n tableName: TableName,\n id: string\n ): Id<TableName> | null;\n};\nexport type DatabaseWriter = DatabaseReader & {\n insert<TableName extends TableNames>(\n tableName: TableName,\n value: Record<string, unknown>\n ): Promise<Id<TableName>>;\n patch<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n replace<TableName extends TableNames>(\n id: Id<TableName>,\n value: Record<string, unknown>\n ): Promise<void>;\n delete<TableName extends TableNames>(id: Id<TableName>): Promise<void>;\n};\ntype Scheduler = {\n runAfter(delayMs: number, functionReference: unknown, args?: unknown): Promise<void>;\n};\ntype AuthReader = {\n getUserIdentity(): Promise<unknown>;\n};\ntype RuntimeInvoker = {\n runQuery(functionReference: unknown, args?: unknown): Promise<any>;\n runMutation(functionReference: unknown, args?: unknown): Promise<any>;\n runAction(functionReference: unknown, args?: unknown): Promise<any>;\n};\nexport type QueryCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseReader;\n scheduler: Scheduler;\n};\nexport type MutationCtx = RuntimeInvoker & {\n auth: AuthReader;\n db: DatabaseWriter;\n scheduler: Scheduler;\n};\nexport type ActionCtx = RuntimeInvoker & {\n auth: AuthReader;\n scheduler: Scheduler;\n};\n\ntype ConvexFunctionBuilder<Ctx> = <\n Definition extends { handler?: (ctx: Ctx, args: any) => any },\n>(\n definition: Definition\n) => any;\n\nexport const action = actionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const httpAction =\n httpActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalAction =\n internalActionGeneric as unknown as ConvexFunctionBuilder<ActionCtx>;\nexport const internalMutation =\n internalMutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const internalQuery =\n internalQueryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\nexport const mutation =\n mutationGeneric as unknown as ConvexFunctionBuilder<MutationCtx>;\nexport const query = queryGeneric as unknown as ConvexFunctionBuilder<QueryCtx>;\n","type GraphPrimitiveDebugEnvironment = {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction isGraphPrimitiveDebugEnabled(): boolean {\n const env = (globalThis as GraphPrimitiveDebugEnvironment).process?.env;\n return (\n env?.LUCERN_COMPAT_FALLBACK_DEBUG === \"1\" ||\n env?.LUCERN_GRAPH_DEBUG === \"1\"\n );\n}\n\nexport function formatGraphPrimitiveError(error: unknown): string {\n if (error instanceof Error) {\n return `${error.name}: ${error.message}`;\n }\n if (typeof error === \"string\") {\n return error;\n }\n if (error === null) {\n return \"null\";\n }\n if (error === undefined) {\n return \"undefined\";\n }\n try {\n return JSON.stringify(error);\n } catch {\n return Object.prototype.toString.call(error);\n }\n}\n\nexport function debugGraphPrimitiveFallback(\n message: string,\n context?: Record<string, unknown>\n): void {\n if (!isGraphPrimitiveDebugEnabled()) {\n return;\n }\n console.debug(message, context ?? {});\n}\n","/** Topic-scope resolution helpers for graph-primitive operations. */\nimport { v } from \"convex/values\";\nimport { api as appApi } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nconst LEGACY_SCOPE_FIELD = \"graphScope\" + \"ProjectId\";\n\ntype TopicDoc = Record<string, unknown> & {\n _id: Id<\"topics\">;\n globalId?: string;\n name?: string;\n depth?: number;\n createdAt?: number;\n parentTopicId?: Id<\"topics\">;\n tenantId?: string;\n workspaceId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type TopicProjectScope = {\n topicId: Id<\"topics\">;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source:\n | \"topic\"\n | \"project_mapped_topic\"\n | \"topic_inferred\"\n | \"topic_node\";\n};\n\n/**\n * RR.5 (legacy topics-table retirement) — graph-primitives mirror of the\n * kernel's epistemicNodes-first topic-scope fallback. Kept in lockstep with\n * `packages/reasoning-kernel/src/adapters/lib/topicScope.ts`\n * (`tests/unit/convex/topic-scope-fallbacks.test.ts` asserts parity).\n *\n * Resolves a topic that exists only as `epistemicNodes(nodeType=\"topic\")` —\n * the write-of-record — when no legacy `topics` row backs the ref, returning the\n * node's `topicId` self-key so scoped beliefs/evidence/questions stay reachable.\n * See the kernel module for the full silent-empty-result rationale.\n */\ntype TopicNodeScopeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n globalId?: string;\n nodeType?: string;\n topicId?: string;\n metadata?: Record<string, unknown>;\n};\n\nasync function resolveTopicNodeScopeOrNull(\n ctx: any,\n ref: string,\n): Promise<TopicProjectScope | null> {\n if (!ctx?.db || typeof ctx.db.query !== \"function\") {\n return null;\n }\n\n let node: TopicNodeScopeDoc | null = null;\n\n // 1. The ref IS the topic node's UUIDv7 globalId.\n try {\n const byGlobalId = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q: any) => q.eq(\"globalId\", ref))\n .first()) as TopicNodeScopeDoc | null;\n if (byGlobalId && byGlobalId.nodeType === \"topic\") {\n node = byGlobalId;\n }\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] topic-node scope lookup by globalId failed\",\n { error, ref },\n );\n }\n\n if (!node) {\n return null;\n }\n\n const scopeKey =\n normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);\n if (!scopeKey) {\n return null;\n }\n\n return {\n topicId: scopeKey as Id<\"topics\">,\n projectId: asMappedProjectId(node as unknown as TopicDoc),\n source: \"topic_node\",\n };\n}\n\ntype MaterializedTopicNodeDoc = {\n _id: string | Id<\"epistemicNodes\">;\n metadata?: Record<string, unknown>;\n};\n\nfunction asMappedProjectId(\n topic: TopicDoc | null | undefined,\n): string | undefined {\n if (!topic) {\n return;\n }\n const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);\n if (directLegacyProjectId) {\n return directLegacyProjectId;\n }\n const metadata = (topic.metadata || {}) as Record<string, unknown>;\n const candidate =\n (metadata[LEGACY_SCOPE_FIELD] as string | undefined) ||\n (metadata.legacyProjectId as string | undefined) ||\n (metadata.projectId as string | undefined) ||\n (metadata.scopeProjectId as string | undefined);\n return candidate ? (candidate as string) : undefined;\n}\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction pickPrimaryTopic(candidates: TopicDoc[]): TopicDoc | undefined {\n return [...candidates].sort((a, b) => {\n const depthA = a.depth ?? 9999;\n const depthB = b.depth ?? 9999;\n if (depthA !== depthB) {\n return depthA - depthB;\n }\n const createdA = a.createdAt ?? Number.MAX_SAFE_INTEGER;\n const createdB = b.createdAt ?? Number.MAX_SAFE_INTEGER;\n if (createdA !== createdB) {\n return createdA - createdB;\n }\n return String(a.name || \"\").localeCompare(String(b.name || \"\"));\n })[0];\n}\n\nasync function findTopicsByScopeAlias(\n ctx: any,\n scopeId: string,\n): Promise<TopicDoc[]> {\n try {\n return (await ctx.db\n .query(\"topics\")\n .withIndex(\"by_graph_scope_project\", (q: any) =>\n q.eq(LEGACY_SCOPE_FIELD, scopeId),\n )\n .collect()) as TopicDoc[];\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve scope alias via index\",\n {\n error,\n scopeId,\n },\n );\n // Older Lucern dev deployments can lag index backfills while still carrying\n // the underlying topics table. Scan and filter so scope resolution keeps\n // working during the rollout.\n const topics = (await ctx.db.query(\"topics\").collect()) as TopicDoc[];\n return topics.filter((topic) => {\n const normalizedGlobalId = normalizeScopeValue(topic.globalId);\n const mappedProjectId = asMappedProjectId(topic);\n return (\n String(topic._id) === scopeId ||\n normalizedGlobalId === scopeId ||\n mappedProjectId === scopeId\n );\n });\n }\n}\n\nasync function tryResolveHostTopicById(\n ctx: any,\n topicId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.get as any, {\n id: topicId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by host query\",\n {\n error,\n topicId,\n },\n );\n return null;\n }\n}\n\nasync function tryResolveHostTopicByLegacyScope(\n ctx: any,\n legacyScopeId: string,\n): Promise<TopicDoc | null> {\n if (typeof ctx.runQuery !== \"function\") {\n return null;\n }\n try {\n return ((await ctx.runQuery(appApi.topics.getByLegacyScopeId as any, {\n projectId: legacyScopeId,\n })) ?? null) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to resolve topic by legacy scope\",\n {\n error,\n legacyScopeId,\n },\n );\n return null;\n }\n}\n\nexport function readMaterializedTopicTableId(\n topicNode: MaterializedTopicNodeDoc | null | undefined,\n): string | undefined {\n if (!topicNode) {\n return;\n }\n\n const metadata = (topicNode.metadata || {}) as Record<string, unknown>;\n const topicTableId =\n (metadata.topicTableId as string | undefined) ||\n (metadata.topicId as string | undefined);\n\n return typeof topicTableId === \"string\" && topicTableId.trim().length > 0\n ? topicTableId.trim()\n : undefined;\n}\n\n/**\n * Walk the topic parent chain to find inherited workspaceId and tenantId.\n * Mirrors the pattern used by resolveTopicOntology for ontologyId inheritance.\n * Max depth: 10 (defensive limit against pathological nesting).\n */\nasync function resolveInheritedWorkspaceScope(\n ctx: any,\n topic: TopicDoc,\n): Promise<{ tenantId?: string; workspaceId?: string }> {\n const MAX_DEPTH = 10;\n let tenantId = normalizeScopeValue(topic.tenantId);\n let workspaceId = normalizeScopeValue(topic.workspaceId);\n\n if (tenantId && workspaceId) {\n return { tenantId, workspaceId };\n }\n\n let current: TopicDoc | null = topic;\n for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {\n current = (await ctx.db.get(current.parentTopicId)) as TopicDoc | null;\n if (!current) break;\n\n if (!tenantId) {\n tenantId = normalizeScopeValue(current.tenantId);\n }\n if (!workspaceId) {\n workspaceId = normalizeScopeValue(current.workspaceId);\n }\n if (tenantId && workspaceId) break;\n }\n\n return { tenantId, workspaceId };\n}\n\nexport async function resolveTopicProjectScope(\n ctx: any,\n args: { topicId?: Id<\"topics\"> | string; projectId?: string },\n): Promise<TopicProjectScope> {\n if (args.topicId) {\n // Try direct lookup, fall back to the legacy mapped-project bridge\n let topic: TopicDoc | null = null;\n try {\n topic = (await ctx.db.get(\n args.topicId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load topic by direct id\",\n {\n error,\n topicId: args.topicId,\n },\n );\n // Not a valid topics table ID\n }\n if (!topic) {\n topic = await tryResolveHostTopicById(ctx, String(args.topicId));\n }\n if (!topic) {\n // Try as legacy projectId / globalId via the mapped-project bridge.\n topic =\n pickPrimaryTopic(\n await findTopicsByScopeAlias(ctx, String(args.topicId)),\n ) ?? null;\n }\n if (!topic) {\n // RR.5: no legacy topics row — resolve the canonical topic node store\n // before throwing (silent-empty-result fix).\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.topicId),\n );\n if (nodeScope) {\n return nodeScope;\n }\n throw new Error(`Topic not found: ${String(args.topicId)}`);\n }\n const inherited = await resolveInheritedWorkspaceScope(ctx, topic);\n const mapped = asMappedProjectId(topic);\n if (mapped) {\n return {\n topicId: topic._id,\n projectId: mapped,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n return {\n topicId: topic._id,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic\",\n };\n }\n\n if (args.projectId) {\n let directTopic: TopicDoc | null = null;\n try {\n directTopic = (await ctx.db.get(\n args.projectId as Id<\"topics\">,\n )) as TopicDoc | null;\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[topicScope] Failed to load direct project topic\",\n {\n error,\n projectId: args.projectId,\n },\n );\n // Not a valid topics table ID, continue to legacy graph-scope lookup.\n }\n\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);\n if (directTopic) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);\n const mapped = asMappedProjectId(directTopic);\n return {\n topicId: directTopic._id,\n projectId: mapped ?? args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"topic_inferred\",\n };\n }\n\n const topics = await findTopicsByScopeAlias(ctx, args.projectId);\n const primary = pickPrimaryTopic(topics);\n if (primary) {\n const inherited = await resolveInheritedWorkspaceScope(ctx, primary);\n return {\n topicId: primary._id,\n projectId: args.projectId,\n tenantId: inherited.tenantId,\n workspaceId: inherited.workspaceId,\n source: \"project_mapped_topic\",\n };\n }\n // RR.5: try the canonical topic node store before failing.\n const nodeScope = await resolveTopicNodeScopeOrNull(\n ctx,\n String(args.projectId),\n );\n if (nodeScope) {\n return {\n ...nodeScope,\n projectId: nodeScope.projectId ?? String(args.projectId),\n };\n }\n\n throw new Error(\n `Legacy project scope ${String(args.projectId)} has no mapped topic.`,\n );\n }\n\n throw new Error(\n \"Missing scope: provide topicId (preferred) or legacy projectId alias.\",\n );\n}\n\n/** Shared scope args for graph-primitive functions. topicId is canonical; projectId is a legacy alias. */\nexport const optionalScopeArgs = {\n projectId: v.optional(v.string()),\n topicId: v.optional(v.string()),\n} as const;\n","import { optionalScopeArgs, resolveTopicProjectScope } from \"./topicScope\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\n\nexport const scopeArgs = optionalScopeArgs;\n\nexport type ResolvedScope = Awaited<\n ReturnType<typeof resolveTopicProjectScope>\n>;\nexport type SoftResolvedScope = {\n topicId?: string;\n projectId?: string;\n tenantId?: string;\n workspaceId?: string;\n source?: ResolvedScope[\"source\"];\n};\n\nfunction normalizeScopeValue(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return;\n }\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nexport async function resolveScope(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null },\n): Promise<ResolvedScope | null> {\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n if (!topicId && !projectId) {\n return null;\n }\n\n try {\n return await resolveTopicProjectScope(ctx, {\n topicId,\n projectId,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[scopeResolverCompat] Failed to resolve scope\",\n {\n error,\n topicId,\n projectId,\n },\n );\n return null;\n }\n}\n\nexport async function resolveScopeSoft(\n ctx: any,\n args: { topicId?: string | null; projectId?: string | null },\n): Promise<SoftResolvedScope> {\n const resolved = await resolveScope(ctx, args);\n if (resolved) {\n const topicId = normalizeScopeValue(resolved.topicId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(resolved.projectId ? { projectId: resolved.projectId } : {}),\n ...(resolved.tenantId ? { tenantId: resolved.tenantId } : {}),\n ...(resolved.workspaceId ? { workspaceId: resolved.workspaceId } : {}),\n ...(resolved.source ? { source: resolved.source } : {}),\n };\n }\n\n const topicId = normalizeScopeValue(args.topicId);\n const projectId = normalizeScopeValue(args.projectId);\n return {\n ...(topicId ? { topicId } : {}),\n ...(projectId ? { projectId } : {}),\n };\n}\n","import type { WithoutSystemFields } from \"convex/server\";\nimport {\n assertUuidV7Identity,\n assertStorageEdgeVocabulary,\n assertCanonicalEdgeEndpoint,\n} from \"@lucern/contracts/ids\";\nimport {\n assertEdgePolicyAllowed,\n edgePolicyManifest,\n type EpistemicNodeType,\n} from \"@lucern/contracts\";\nimport type { Doc, Id, MutationCtx } from \"./convex\";\n\nexport async function insertEpistemicNode(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicNodes\">>,\n): Promise<Id<\"epistemicNodes\">> {\n assertUuidV7Identity(\"epistemicNodes\", doc.globalId);\n return ctx.db.insert(\"epistemicNodes\", doc);\n}\n\nexport async function insertEpistemicEdge(\n ctx: MutationCtx,\n doc: WithoutSystemFields<Doc<\"epistemicEdges\">>,\n): Promise<Id<\"epistemicEdges\">> {\n assertUuidV7Identity(\"epistemicEdges\", doc.globalId);\n\n // R1.1a — STORAGE-VOCABULARY MEMBERSHIP\n assertStorageEdgeVocabulary(doc.edgeType);\n\n // R1.1b — ENDPOINT PRESENCE\n if (!doc.fromNodeId || typeof doc.fromNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId\"\n );\n }\n if (!doc.toNodeId || typeof doc.toNodeId !== \"string\") {\n throw new Error(\n \"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId\"\n );\n }\n\n // C2-RR.4 Defect E — ENDPOINT CANONICAL IDENTITY. Edge endpoints must be the\n // UUIDv7 globalIds of the connected nodes, never Convex doc ids or legacy\n // topic ids. This refuses the mixed _id/globalId endpoint writes at the floor.\n assertCanonicalEdgeEndpoint(\"fromNodeId\", doc.fromNodeId);\n assertCanonicalEdgeEndpoint(\"toNodeId\", doc.toNodeId);\n\n // R1.1c — FULL POLICY ASSERT (when nodeTypes are present and edgeType is in public manifest)\n if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== \"extracted_from\") {\n assertEdgePolicyAllowed(\n edgePolicyManifest,\n doc.edgeType,\n {\n kind: \"epistemic_node\",\n nodeId: doc.fromNodeId,\n nodeType: doc.fromNodeType as EpistemicNodeType,\n },\n {\n kind: \"epistemic_node\",\n nodeId: doc.toNodeId,\n nodeType: doc.toNodeType as EpistemicNodeType,\n }\n );\n }\n\n return ctx.db.insert(\"epistemicEdges\", doc);\n}\n","/**\n * Epistemic Answers API\n *\n * Answers are first-class L2 nodes in the epistemic spine.\n * Every answer is an immutable snapshot — new answers create new nodes,\n * old ones get `superseded`. This gives full version history and lets\n * answers have their own edges in the knowledge graph.\n *\n * Edge: Answer —responds_to→ Question\n * Edge: Answer —based_on→ Evidence (for each supporting evidence)\n * Edge: NewAnswer —supersedes→ OldAnswer (for versioning)\n *\n * @see /docs/epistemic-invariants/00-epistemic-invariants.md\n */\n\nimport { v } from \"convex/values\";\nimport { api, internal } from \"./convex\";\nimport type { Id } from \"./convex\";\nimport { internalMutation, mutation, query } from \"./convex\";\nimport type { MutationCtx, QueryCtx } from \"./convex\";\nimport { checkScopeAccess } from \"@lucern/access-control/access\";\nimport { generateGlobalId } from \"./globalId\";\nimport { resolveScope, scopeArgs } from \"./scopeResolverCompat\";\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport { insertEpistemicNode } from \"./epistemicInsert.js\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\ntype AnswerNodeRow = {\n _id: Id<\"epistemicNodes\">;\n globalId: string;\n canonicalText?: string;\n metadata?: Record<string, unknown>;\n status?: string;\n createdBy?: string;\n createdAt?: number;\n supersededBy?: Id<\"epistemicNodes\">;\n topicId?: Id<\"topics\">;\n projectId?: string;\n nodeType?: string;\n};\n\ntype IndexQuery = {\n eq(field: string, value: unknown): IndexQuery;\n};\n\ntype FilterQuery = {\n field(name: string): unknown;\n eq(left: unknown, right: unknown): unknown;\n or(...conditions: unknown[]): unknown;\n};\n\nfunction generateContentHash(text: string): string {\n const content = `answer:${text.trim().toLowerCase().replace(/\\s+/g, \" \").slice(0, 500)}`;\n let hash = 5381;\n for (let i = 0; i < content.length; i++) {\n hash = (hash << 5) + hash + content.charCodeAt(i);\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\n// =============================================================================\n// CREATE\n// =============================================================================\n\n/**\n * Create a new answer node for a question.\n *\n * 1. Validates the question exists\n * 2. Determines version number\n * 3. Supersedes previous active answer (if any)\n * 4. Creates the answer node\n * 5. Creates responds_to edge (Answer → Question)\n * 6. Creates supersedes edge (NewAnswer → OldAnswer) if versioning\n * 7. Creates based_on edges (Answer → Evidence) for each evidence node\n * 8. Updates question's answerQuality field\n * 9. Logs to epistemicAudit\n */\nexport const create = mutation({\n args: {\n ...scopeArgs,\n questionNodeId: v.id(\"epistemicNodes\"),\n answerText: v.string(),\n confidence: v.optional(\n v.union(\n v.literal(\"definitive\"),\n v.literal(\"strong\"),\n v.literal(\"moderate\"),\n v.literal(\"weak\"),\n v.literal(\"speculative\")\n )\n ),\n evidenceNodeIds: v.optional(v.array(v.id(\"epistemicNodes\"))),\n answerSource: v.optional(v.string()),\n sprintId: v.optional(v.string()),\n userId: v.string(),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = scope?.topicId ? String(scope.topicId) : (args.topicId || \"\");\n await checkScopeAccess(ctx, topicId, args.userId);\n\n // 1. Validate question exists\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n throw new Error(\"Question node not found or not a question type\");\n }\n\n const now = Date.now();\n const globalId = generateGlobalId();\n const contentHash = generateContentHash(args.answerText);\n\n // 2. Find current active answer(s) for this question to determine version\n // TC-C: Use by_topic_type (canonical)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId ?? topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n const activeAnswersForQuestion = existingAnswers.filter((n) => {\n const meta = (n.metadata || {}) as Record<string, unknown>;\n return (\n meta.questionNodeId === args.questionNodeId &&\n meta.isLatest === true &&\n n.status === \"active\"\n );\n });\n\n const versionNumber =\n activeAnswersForQuestion.length > 0\n ? Math.max(\n ...activeAnswersForQuestion.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return (meta.versionNumber as number) || 0;\n })\n ) + 1\n : 1;\n\n // 3. Supersede previous active answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n status: \"superseded\",\n supersededBy: undefined, // Will be set after insert\n updatedAt: now,\n metadata: {\n ...((oldAnswer.metadata as Record<string, unknown>) || {}),\n isLatest: false,\n },\n });\n }\n\n // Gather evidence globalIds\n const evidenceGlobalIds: string[] = [];\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n evidenceGlobalIds.push(evNode.globalId);\n }\n }\n }\n\n // 4. Insert new answer node — inherit topicId from the question\n const nodeId = await insertEpistemicNode(ctx, {\n globalId,\n projectId: topicId,\n topicId: questionNode.topicId,\n nodeType: \"answer\",\n epistemicLayer: \"L2\",\n canonicalText: args.answerText,\n contentHash,\n status: \"active\",\n sourceType: args.answerSource === \"human\" ? \"human\" : \"ai_generated\",\n createdBy: args.userId,\n createdAt: now,\n updatedAt: now,\n metadata: {\n questionGlobalId: questionNode.globalId,\n questionNodeId: String(args.questionNodeId),\n versionNumber,\n isLatest: true,\n evidenceGlobalIds,\n evidenceCount: evidenceGlobalIds.length,\n answeredBy: args.userId,\n answerSource: args.answerSource || \"human\",\n sprintId: args.sprintId,\n },\n });\n\n // Update supersededBy on old answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n supersededBy: nodeId,\n });\n }\n\n // 5. Schedule Neo4j sync\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await ctx.scheduler.runAfter(\n 0,\n api.embeddingActions.generateEpistemicNodeEmbedding,\n {\n nodeId,\n projectId: topicId,\n topicId: questionNode.topicId ? String(questionNode.topicId) : undefined,\n createdBy: args.userId,\n nodeType: \"answer\",\n text: args.answerText.slice(0, 20_000),\n }\n );\n await ctx.scheduler.runAfter(\n 0,\n internal.sprints.embedProjectThemeCollectiveInternal,\n {\n projectId: topicId,\n userId: args.userId,\n }\n );\n\n // 6. Create responds_to edge (Answer → Question)\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: questionNode.globalId,\n edgeType: \"responds_to\",\n weight: 1.0,\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"question\",\n fromLayer: \"L2\",\n toLayer: \"L3\",\n });\n\n // 7. Create supersedes edges (NewAnswer → OldAnswer)\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: oldAnswer.globalId,\n edgeType: \"supersedes\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n\n // 8. Create based_on edges (Answer → Evidence)\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: evNode.globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"evidence\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n }\n\n // 9. Re-edge: evidence that \"derived_from\" the question now also gets \"derived_from\" → answer\n const evidenceEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_to_type\", (q: IndexQuery) =>\n q.eq(\"toNodeId\", args.questionNodeId).eq(\"edgeType\", \"derived_from\")\n )\n .collect();\n\n for (const edge of evidenceEdges) {\n const evidenceNode = await ctx.db.get(edge.fromNodeId);\n if (evidenceNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: evidenceNode.globalId,\n toGlobalId: globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"evidence\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n\n // 10. Update question's answerQuality\n const answerQuality = args.confidence || \"moderate\";\n await ctx.db.patch(args.questionNodeId, {\n answerQuality,\n updatedAt: now,\n });\n\n // 11. Log to audit\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"answer\",\n entityId: nodeId,\n changeType: \"created\",\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n projectId: topicId,\n newState: {\n answerText: args.answerText.slice(0, 200),\n versionNumber,\n questionNodeId: String(args.questionNodeId),\n confidence: answerQuality,\n },\n });\n\n return { nodeId, globalId, versionNumber };\n },\n});\n\n// =============================================================================\n// CREATE INTERNAL (for scheduler / other modules)\n// =============================================================================\n\n/**\n * Internal mutation for creating answer nodes.\n * Called from epistemicQuestions.updateStatus when status === \"answered\".\n */\nexport const createInternal = internalMutation({\n args: {\n ...scopeArgs,\n questionNodeId: v.id(\"epistemicNodes\"),\n answerText: v.string(),\n confidence: v.optional(v.string()),\n evidenceNodeIds: v.optional(v.array(v.id(\"epistemicNodes\"))),\n answerSource: v.optional(v.string()),\n sprintId: v.optional(v.string()),\n userId: v.string(),\n backfilledFromQuestionId: v.optional(v.string()),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = scope?.topicId ? String(scope.topicId) : (args.topicId || \"\");\n\n // Validate question exists\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n throw new Error(\"Question node not found or not a question type\");\n }\n\n const now = Date.now();\n const globalId = generateGlobalId();\n const contentHash = generateContentHash(args.answerText);\n\n // Find current active answers for this question (TC-C: use topic index)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId ?? topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n const activeAnswersForQuestion = existingAnswers.filter((n) => {\n const meta = (n.metadata || {}) as Record<string, unknown>;\n return (\n meta.questionNodeId === String(args.questionNodeId) &&\n meta.isLatest === true &&\n n.status === \"active\"\n );\n });\n\n const versionNumber =\n activeAnswersForQuestion.length > 0\n ? Math.max(\n ...activeAnswersForQuestion.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return (meta.versionNumber as number) || 0;\n })\n ) + 1\n : 1;\n\n // Supersede previous active answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n status: \"superseded\",\n updatedAt: now,\n metadata: {\n ...((oldAnswer.metadata as Record<string, unknown>) || {}),\n isLatest: false,\n },\n });\n }\n\n // Gather evidence globalIds\n const evidenceGlobalIds: string[] = [];\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n evidenceGlobalIds.push(evNode.globalId);\n }\n }\n }\n\n // Insert answer node — inherit topicId from the question (TC-C fix)\n const nodeId = await insertEpistemicNode(ctx, {\n globalId,\n projectId: topicId,\n topicId: questionNode.topicId,\n nodeType: \"answer\",\n epistemicLayer: \"L2\",\n canonicalText: args.answerText,\n contentHash,\n status: \"active\",\n sourceType: args.answerSource === \"human\" ? \"human\" : \"ai_generated\",\n createdBy: args.userId,\n createdAt: now,\n updatedAt: now,\n metadata: {\n questionGlobalId: questionNode.globalId,\n questionNodeId: String(args.questionNodeId),\n versionNumber,\n isLatest: true,\n evidenceGlobalIds,\n evidenceCount: evidenceGlobalIds.length,\n answeredBy: args.userId,\n answerSource: args.answerSource || \"human\",\n sprintId: args.sprintId,\n backfilledFromQuestionId: args.backfilledFromQuestionId,\n },\n });\n\n // Update supersededBy on old answers\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.db.patch(oldAnswer._id, {\n supersededBy: nodeId,\n });\n }\n\n // Schedule Neo4j sync\n await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {\n nodeId,\n operation: \"upsert\",\n });\n\n await ctx.scheduler.runAfter(\n 0,\n api.embeddingActions.generateEpistemicNodeEmbedding,\n {\n nodeId,\n projectId: topicId,\n topicId: questionNode.topicId ? String(questionNode.topicId) : undefined,\n createdBy: args.userId,\n nodeType: \"answer\",\n text: args.answerText.slice(0, 20_000),\n }\n );\n await ctx.scheduler.runAfter(\n 0,\n internal.sprints.embedProjectThemeCollectiveInternal,\n {\n projectId: topicId,\n userId: args.userId,\n }\n );\n\n // Create responds_to edge (Answer → Question)\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: questionNode.globalId,\n edgeType: \"responds_to\",\n weight: 1.0,\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"question\",\n fromLayer: \"L2\",\n toLayer: \"L3\",\n });\n\n // Create supersedes edges\n for (const oldAnswer of activeAnswersForQuestion) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: oldAnswer.globalId,\n edgeType: \"supersedes\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n\n // Create based_on edges (Answer → Evidence)\n if (args.evidenceNodeIds) {\n for (const evId of args.evidenceNodeIds) {\n const evNode = await ctx.db.get(evId);\n if (evNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: globalId,\n toGlobalId: evNode.globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"answer\",\n toNodeType: \"evidence\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n }\n\n // Re-edge: evidence that \"derived_from\" the question now also gets \"derived_from\" → answer\n const evidenceEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_to_type\", (q: IndexQuery) =>\n q.eq(\"toNodeId\", args.questionNodeId).eq(\"edgeType\", \"derived_from\")\n )\n .collect();\n\n for (const edge of evidenceEdges) {\n const evidenceNode = await ctx.db.get(edge.fromNodeId);\n if (evidenceNode) {\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: generateGlobalId(),\n fromGlobalId: evidenceNode.globalId,\n toGlobalId: globalId,\n edgeType: \"derived_from\",\n createdBy: args.userId,\n topicId: String(args.topicId ?? \"\"),\n fromNodeType: \"evidence\",\n toNodeType: \"answer\",\n fromLayer: \"L2\",\n toLayer: \"L2\",\n });\n }\n }\n\n // Update question's answerQuality\n const answerQuality = args.confidence || \"moderate\";\n await ctx.db.patch(args.questionNodeId, {\n answerQuality,\n updatedAt: now,\n });\n\n // Log to audit\n await ctx.db.insert(\"epistemicAudit\", {\n entityType: \"answer\",\n entityId: nodeId,\n changeType: \"created\",\n changedAt: now,\n changedBy: args.userId,\n isAgent: false,\n projectId: topicId,\n newState: {\n answerText: args.answerText.slice(0, 200),\n versionNumber,\n questionNodeId: String(args.questionNodeId),\n backfilled: !!args.backfilledFromQuestionId,\n },\n });\n\n return { nodeId, globalId, versionNumber };\n },\n});\n\n// =============================================================================\n// QUERIES\n// =============================================================================\n\n/**\n * Get all answers for a question, optionally including superseded.\n */\nexport const getByQuestion = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n includeSuperseded: v.optional(v.boolean()),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return [];\n }\n\n const topicId = questionNode.topicId;\n if (!topicId) {\n return [];\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n // Filter to answers for this question\n const questionIdStr = String(args.questionNodeId);\n const filtered = answers.filter((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr;\n });\n\n if (!args.includeSuperseded) {\n return filtered.filter((a) => a.status === \"active\");\n }\n\n // Sort by version number (newest first)\n filtered.sort((a, b) => {\n const metaA = (a.metadata || {}) as Record<string, unknown>;\n const metaB = (b.metadata || {}) as Record<string, unknown>;\n return (\n ((metaB.versionNumber as number) || 0) -\n ((metaA.versionNumber as number) || 0)\n );\n });\n\n return filtered;\n },\n});\n\n/**\n * Get the single active (latest) answer for a question.\n */\nexport const getLatestForQuestion = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return null;\n }\n\n // Filter status === \"active\" at DB level to reduce JS-side work.\n // metadata.questionNodeId filtering must stay in JS (no index on metadata fields).\n if (!questionNode.topicId) {\n return null;\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId!).eq(\"nodeType\", \"answer\")\n )\n .filter((q: FilterQuery) => q.eq(q.field(\"status\"), \"active\"))\n .collect()) as AnswerNodeRow[];\n\n const questionIdStr = String(args.questionNodeId);\n const latest = answers.find((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr && meta.isLatest === true;\n });\n\n return latest || null;\n },\n});\n\n/**\n * Get full version history for answers to a question.\n * Returns answers ordered by version number (newest first).\n */\nexport const getVersionHistory = query({\n args: {\n questionNodeId: v.id(\"epistemicNodes\"),\n },\n returns: permissiveReturn,\n handler: async (ctx: QueryCtx, args) => {\n const questionNode = await ctx.db.get(args.questionNodeId);\n if (!questionNode || questionNode.nodeType !== \"question\") {\n return [];\n }\n\n // Filter status at DB level; metadata.questionNodeId must filter in JS (no index on metadata).\n if (!questionNode.topicId) {\n return [];\n }\n const answers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", questionNode.topicId!).eq(\"nodeType\", \"answer\")\n )\n .filter((q: FilterQuery) =>\n q.or(\n q.eq(q.field(\"status\"), \"active\"),\n q.eq(q.field(\"status\"), \"superseded\")\n )\n )\n .collect()) as AnswerNodeRow[];\n\n const questionIdStr = String(args.questionNodeId);\n const history = answers\n .filter((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId === questionIdStr;\n })\n .map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return {\n _id: a._id,\n globalId: a.globalId,\n answerText: a.canonicalText,\n versionNumber: (meta.versionNumber as number) || 1,\n isLatest: (meta.isLatest as boolean) || false,\n status: a.status,\n answeredBy: (meta.answeredBy as string) || a.createdBy,\n answerSource: meta.answerSource as string | undefined,\n evidenceCount: (meta.evidenceCount as number) || 0,\n createdAt: a.createdAt,\n supersededBy: a.supersededBy,\n };\n })\n .sort((a, b) => b.versionNumber - a.versionNumber);\n\n return history;\n },\n});\n\n// =============================================================================\n// BACKFILL: Create answer nodes for questions that have answer text but no node\n// =============================================================================\n\n/**\n * Backfill answer nodes for questions that have answer text in metadata\n * but never had an answer node created (due to the QuestionAnswerEditor bug\n * where saveAnswer passed wrong params to updateStatus).\n *\n * Run once via Convex dashboard:\n * internal.epistemicAnswers.backfillAnswerNodes({ projectId, userId })\n */\nexport const backfillAnswerNodes = internalMutation({\n args: {\n ...scopeArgs,\n userId: v.string(),\n dryRun: v.optional(v.boolean()),\n },\n returns: permissiveReturn,\n handler: async (ctx: MutationCtx, args) => {\n const scope = await resolveScope(ctx, args);\n const topicId = (scope?.topicId ??\n args.topicId) as Id<\"topics\">;\n const dryRun = args.dryRun ?? false;\n\n // 1. Find all question nodes with answer text in metadata (TC-C: prefer topic)\n const questions = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"question\")\n )\n .collect()) as AnswerNodeRow[];\n\n const questionsWithAnswers = questions.filter((q) => {\n const meta = (q.metadata || {}) as Record<string, unknown>;\n const answer = meta.answer as string | undefined;\n return answer && answer.trim().length > 0;\n });\n\n // 2. Find all existing answer nodes (TC-C: use topic index since projectId is now topicId)\n const existingAnswers = (await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: IndexQuery) =>\n q.eq(\"topicId\", topicId).eq(\"nodeType\", \"answer\")\n )\n .collect()) as AnswerNodeRow[];\n\n // Build set of question IDs that already have answer nodes\n const questionIdsWithAnswerNodes = new Set(\n existingAnswers.map((a) => {\n const meta = (a.metadata || {}) as Record<string, unknown>;\n return meta.questionNodeId as string;\n })\n );\n\n // 3. Filter to questions that need backfill\n const needsBackfill = questionsWithAnswers.filter(\n (q) => !questionIdsWithAnswerNodes.has(String(q._id))\n );\n\n console.log(\n `[backfillAnswerNodes] Found ${questionsWithAnswers.length} questions with answers, ` +\n `${questionIdsWithAnswerNodes.size} already have answer nodes, ` +\n `${needsBackfill.length} need backfill. dryRun=${dryRun}`\n );\n\n if (dryRun) {\n return {\n questionsWithAnswers: questionsWithAnswers.length,\n alreadyHaveNodes: questionIdsWithAnswerNodes.size,\n needsBackfill: needsBackfill.length,\n questions: needsBackfill.map((q) => ({\n id: q._id,\n globalId: q.globalId,\n text: q.canonicalText?.slice(0, 80),\n answer: (q.metadata?.answer as string | undefined)?.slice(0, 80),\n })),\n };\n }\n\n // 4. Create answer nodes for each\n let created = 0;\n for (const question of needsBackfill) {\n const meta = (question.metadata || {}) as Record<string, unknown>;\n const answerText = meta.answer as string;\n\n await ctx.scheduler.runAfter(\n 0,\n internal.epistemicAnswers.createInternal,\n {\n topicId: String(topicId), // TC-C: migrated from projectId\n questionNodeId: question._id,\n answerText,\n answerSource: (meta.answeredBy as string) ? \"human\" : \"ai_generated\",\n userId: (meta.answeredBy as string) || args.userId,\n backfilledFromQuestionId: String(question._id),\n }\n );\n created++;\n }\n\n return {\n questionsWithAnswers: questionsWithAnswers.length,\n alreadyHaveNodes: questionIdsWithAnswerNodes.size,\n backfilled: created,\n };\n },\n});\n"]}
|
|
@@ -26,6 +26,35 @@ function debugGraphPrimitiveFallback(message, context) {
|
|
|
26
26
|
console.debug(message, context ?? {});
|
|
27
27
|
}
|
|
28
28
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
29
|
+
async function resolveTopicNodeScopeOrNull(ctx, ref) {
|
|
30
|
+
if (!ctx?.db || typeof ctx.db.query !== "function") {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
let node = null;
|
|
34
|
+
try {
|
|
35
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
|
|
36
|
+
if (byGlobalId && byGlobalId.nodeType === "topic") {
|
|
37
|
+
node = byGlobalId;
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
debugGraphPrimitiveFallback(
|
|
41
|
+
"[topicScope] topic-node scope lookup by globalId failed",
|
|
42
|
+
{ error, ref }
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (!node) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
|
|
49
|
+
if (!scopeKey) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
topicId: scopeKey,
|
|
54
|
+
projectId: asMappedProjectId(node),
|
|
55
|
+
source: "topic_node"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
29
58
|
function asMappedProjectId(topic) {
|
|
30
59
|
if (!topic) {
|
|
31
60
|
return;
|
|
@@ -166,6 +195,13 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
166
195
|
) ?? null;
|
|
167
196
|
}
|
|
168
197
|
if (!topic) {
|
|
198
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
199
|
+
ctx,
|
|
200
|
+
String(args.topicId)
|
|
201
|
+
);
|
|
202
|
+
if (nodeScope) {
|
|
203
|
+
return nodeScope;
|
|
204
|
+
}
|
|
169
205
|
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
170
206
|
}
|
|
171
207
|
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
@@ -236,6 +272,16 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
236
272
|
source: "project_mapped_topic"
|
|
237
273
|
};
|
|
238
274
|
}
|
|
275
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
276
|
+
ctx,
|
|
277
|
+
String(args.projectId)
|
|
278
|
+
);
|
|
279
|
+
if (nodeScope) {
|
|
280
|
+
return {
|
|
281
|
+
...nodeScope,
|
|
282
|
+
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
283
|
+
};
|
|
284
|
+
}
|
|
239
285
|
throw new Error(
|
|
240
286
|
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
241
287
|
);
|