@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
|
@@ -1,9 +1,43 @@
|
|
|
1
1
|
import { componentsGeneric, anyApi } from 'convex/server';
|
|
2
|
-
import { generateUuidV7 } from '@lucern/contracts/ids';
|
|
2
|
+
import { generateUuidV7, assertUuidV7Identity, assertStorageEdgeVocabulary, assertCanonicalEdgeEndpoint } from '@lucern/contracts/ids';
|
|
3
|
+
import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
|
|
3
4
|
|
|
4
5
|
// src/convex.ts
|
|
5
6
|
componentsGeneric();
|
|
6
7
|
var internal = anyApi;
|
|
8
|
+
async function insertEpistemicEdge(ctx, doc) {
|
|
9
|
+
assertUuidV7Identity("epistemicEdges", doc.globalId);
|
|
10
|
+
assertStorageEdgeVocabulary(doc.edgeType);
|
|
11
|
+
if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
assertCanonicalEdgeEndpoint("fromNodeId", doc.fromNodeId);
|
|
22
|
+
assertCanonicalEdgeEndpoint("toNodeId", doc.toNodeId);
|
|
23
|
+
if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
|
|
24
|
+
assertEdgePolicyAllowed(
|
|
25
|
+
edgePolicyManifest,
|
|
26
|
+
doc.edgeType,
|
|
27
|
+
{
|
|
28
|
+
kind: "epistemic_node",
|
|
29
|
+
nodeId: doc.fromNodeId,
|
|
30
|
+
nodeType: doc.fromNodeType
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
kind: "epistemic_node",
|
|
34
|
+
nodeId: doc.toNodeId,
|
|
35
|
+
nodeType: doc.toNodeType
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return ctx.db.insert("epistemicEdges", doc);
|
|
40
|
+
}
|
|
7
41
|
|
|
8
42
|
// src/epistemicBeliefs.topicAnchor.ts
|
|
9
43
|
function cleanString(value) {
|
|
@@ -55,18 +89,15 @@ async function createRequiredBeliefTopicEdge(ctx, args) {
|
|
|
55
89
|
const now = Date.now();
|
|
56
90
|
const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
|
|
57
91
|
"by_from_to",
|
|
58
|
-
(q) => q.eq("fromNodeId",
|
|
59
|
-
"toNodeId",
|
|
60
|
-
String(args.topicNode._id)
|
|
61
|
-
)
|
|
92
|
+
(q) => q.eq("fromNodeId", args.beliefGlobalId).eq("toNodeId", topicGlobalId)
|
|
62
93
|
).collect();
|
|
63
94
|
const existing = existingEdges.find((edge) => edge.edgeType === "belongs_to");
|
|
64
95
|
const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();
|
|
65
96
|
if (!existing) {
|
|
66
|
-
await ctx
|
|
97
|
+
await insertEpistemicEdge(ctx, {
|
|
67
98
|
globalId: edgeGlobalId,
|
|
68
|
-
fromNodeId:
|
|
69
|
-
toNodeId:
|
|
99
|
+
fromNodeId: args.beliefGlobalId,
|
|
100
|
+
toNodeId: topicGlobalId,
|
|
70
101
|
sourceGlobalId: args.beliefGlobalId,
|
|
71
102
|
targetGlobalId: topicGlobalId,
|
|
72
103
|
edgeType: "belongs_to",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/convex.ts","../src/epistemicBeliefs.topicAnchor.ts"],"names":[],"mappings":"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","file":"epistemicBeliefs.topicAnchor.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","import type { Doc, Id, MutationCtx } from \"./convex\";\nimport { internal } from \"./convex\";\nimport { generateUuidV7 } from \"./globalId\";\n\ntype TopicAnchorInput = {\n topicId?: string;\n topicNodeId?: string;\n topicGlobalId?: string;\n};\n\ntype TopicNodeDoc = Doc<\"epistemicNodes\"> & {\n globalId: string;\n nodeType: \"topic\";\n};\n\nfunction cleanString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction topicNodeCandidates(topicRef: string): string[] {\n const normalized = topicRef.trim();\n if (!normalized) {\n return [];\n }\n const candidates = [normalized];\n if (normalized.startsWith(\"top_\")) {\n candidates.push(normalized.slice(4));\n }\n return [...new Set(candidates)];\n}\n\nexport function readTopicNodeRef(args: TopicAnchorInput): string | undefined {\n return (\n cleanString(args.topicGlobalId) ??\n cleanString(args.topicNodeId) ??\n cleanString(args.topicId)\n );\n}\n\nexport async function resolveRequiredTopicAnchor(\n ctx: MutationCtx,\n topicRef: string,\n): Promise<TopicNodeDoc> {\n for (const candidate of topicNodeCandidates(topicRef)) {\n try {\n const direct = await ctx.db.get(candidate as Id<\"epistemicNodes\">);\n if (direct?.nodeType === \"topic\" && cleanString(direct.globalId)) {\n return direct as TopicNodeDoc;\n }\n } catch (_) {\n // Not a component-local epistemicNodes _id; try the globalId index next.\n }\n\n const byGlobalId = await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q) => q.eq(\"globalId\", candidate))\n .first();\n if (byGlobalId?.nodeType === \"topic\" && cleanString(byGlobalId.globalId)) {\n return byGlobalId as TopicNodeDoc;\n }\n }\n\n throw new Error(\n \"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors.\",\n );\n}\n\nexport function scopeFromTopicAnchor(topicNode: TopicNodeDoc) {\n return {\n topicId: topicNode.globalId,\n projectId: cleanString(topicNode.projectId),\n tenantId: cleanString(topicNode.tenantId),\n workspaceId: cleanString(topicNode.workspaceId),\n source: \"topic\" as const,\n };\n}\n\nexport async function createRequiredBeliefTopicEdge(\n ctx: MutationCtx,\n args: {\n beliefNodeId: Id<\"epistemicNodes\">;\n beliefGlobalId: string;\n topicNode: TopicNodeDoc;\n createdBy: string;\n },\n) {\n const topicGlobalId = args.topicNode.globalId;\n const now = Date.now();\n\n const existingEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_from_to\", (q) =>\n q.eq(\"fromNodeId\", String(args.beliefNodeId)).eq(\n \"toNodeId\",\n String(args.topicNode._id),\n ),\n )\n .collect();\n const existing = existingEdges.find((edge) => edge.edgeType === \"belongs_to\");\n const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();\n\n if (!existing) {\n await ctx.db.insert(\"epistemicEdges\", {\n globalId: edgeGlobalId,\n fromNodeId: String(args.beliefNodeId),\n toNodeId: String(args.topicNode._id),\n sourceGlobalId: args.beliefGlobalId,\n targetGlobalId: topicGlobalId,\n edgeType: \"belongs_to\",\n weight: 1,\n confidence: 1,\n context: \"Belief creation topic anchor invariant.\",\n reasoningMethod: \"implicit\",\n derivationType: \"topic_scope_invariant\",\n metadata: {\n invariant: \"belief.topic_edge_required\",\n edgeUuid: edgeGlobalId,\n fromUuid: args.beliefGlobalId,\n toUuid: topicGlobalId,\n },\n createdBy: args.createdBy,\n createdAt: now,\n updatedAt: now,\n projectId: cleanString(args.topicNode.projectId),\n topicId: topicGlobalId,\n tenantId: cleanString(args.topicNode.tenantId),\n workspaceId: cleanString(args.topicNode.workspaceId),\n fromNodeType: \"belief\",\n toNodeType: \"topic\",\n fromLayer: \"L3\",\n toLayer: args.topicNode.epistemicLayer ?? \"ontological\",\n } as any);\n }\n\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: edgeGlobalId,\n fromGlobalId: args.beliefGlobalId,\n toGlobalId: topicGlobalId,\n edgeType: \"belongs_to\",\n weight: 1,\n confidence: 1,\n context: \"Belief creation topic anchor invariant.\",\n projectId: cleanString(args.topicNode.projectId),\n topicId: topicGlobalId,\n createdBy: args.createdBy,\n fromNodeType: \"belief\",\n toNodeType: \"topic\",\n fromLayer: \"L3\",\n toLayer: args.topicNode.epistemicLayer ?? \"ontological\",\n metadata: {\n invariant: \"belief.topic_edge_required\",\n edgeUuid: edgeGlobalId,\n fromUuid: args.beliefGlobalId,\n toUuid: topicGlobalId,\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/convex.ts","../src/epistemicInsert.ts","../src/epistemicBeliefs.topicAnchor.ts"],"names":[],"mappings":"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","file":"epistemicBeliefs.topicAnchor.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","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","import type { Doc, Id, MutationCtx } from \"./convex\";\nimport { internal } from \"./convex\";\nimport { generateUuidV7 } from \"./globalId\";\nimport { insertEpistemicEdge } from \"./epistemicInsert.js\";\n\ntype TopicAnchorInput = {\n topicId?: string;\n topicNodeId?: string;\n topicGlobalId?: string;\n};\n\ntype TopicNodeDoc = Doc<\"epistemicNodes\"> & {\n globalId: string;\n nodeType: \"topic\";\n};\n\nfunction cleanString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction topicNodeCandidates(topicRef: string): string[] {\n const normalized = topicRef.trim();\n if (!normalized) {\n return [];\n }\n const candidates = [normalized];\n if (normalized.startsWith(\"top_\")) {\n candidates.push(normalized.slice(4));\n }\n return [...new Set(candidates)];\n}\n\nexport function readTopicNodeRef(args: TopicAnchorInput): string | undefined {\n return (\n cleanString(args.topicGlobalId) ??\n cleanString(args.topicNodeId) ??\n cleanString(args.topicId)\n );\n}\n\nexport async function resolveRequiredTopicAnchor(\n ctx: MutationCtx,\n topicRef: string,\n): Promise<TopicNodeDoc> {\n for (const candidate of topicNodeCandidates(topicRef)) {\n try {\n const direct = await ctx.db.get(candidate as Id<\"epistemicNodes\">);\n if (direct?.nodeType === \"topic\" && cleanString(direct.globalId)) {\n return direct as TopicNodeDoc;\n }\n } catch (_) {\n // Not a component-local epistemicNodes _id; try the globalId index next.\n }\n\n const byGlobalId = await ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_globalId\", (q) => q.eq(\"globalId\", candidate))\n .first();\n if (byGlobalId?.nodeType === \"topic\" && cleanString(byGlobalId.globalId)) {\n return byGlobalId as TopicNodeDoc;\n }\n }\n\n throw new Error(\n \"Belief creation requires topicGlobalId or topicNodeId for a topic node in epistemicNodes. Legacy topics-table IDs are not valid belief anchors.\",\n );\n}\n\nexport function scopeFromTopicAnchor(topicNode: TopicNodeDoc) {\n return {\n topicId: topicNode.globalId,\n projectId: cleanString(topicNode.projectId),\n tenantId: cleanString(topicNode.tenantId),\n workspaceId: cleanString(topicNode.workspaceId),\n source: \"topic\" as const,\n };\n}\n\nexport async function createRequiredBeliefTopicEdge(\n ctx: MutationCtx,\n args: {\n beliefNodeId: Id<\"epistemicNodes\">;\n beliefGlobalId: string;\n topicNode: TopicNodeDoc;\n createdBy: string;\n },\n) {\n const topicGlobalId = args.topicNode.globalId;\n const now = Date.now();\n\n // C2-RR.4 Defect E — query (and write) by canonical UUIDv7 endpoints, not\n // Convex doc ids. The endpoints are belief/topic globalIds.\n const existingEdges = await ctx.db\n .query(\"epistemicEdges\")\n .withIndex(\"by_from_to\", (q) =>\n q.eq(\"fromNodeId\", args.beliefGlobalId).eq(\"toNodeId\", topicGlobalId),\n )\n .collect();\n const existing = existingEdges.find((edge) => edge.edgeType === \"belongs_to\");\n const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();\n\n if (!existing) {\n await insertEpistemicEdge(ctx, {\n globalId: edgeGlobalId,\n fromNodeId: args.beliefGlobalId,\n toNodeId: topicGlobalId,\n sourceGlobalId: args.beliefGlobalId,\n targetGlobalId: topicGlobalId,\n edgeType: \"belongs_to\",\n weight: 1,\n confidence: 1,\n context: \"Belief creation topic anchor invariant.\",\n reasoningMethod: \"implicit\",\n derivationType: \"topic_scope_invariant\",\n metadata: {\n invariant: \"belief.topic_edge_required\",\n edgeUuid: edgeGlobalId,\n fromUuid: args.beliefGlobalId,\n toUuid: topicGlobalId,\n },\n createdBy: args.createdBy,\n createdAt: now,\n updatedAt: now,\n projectId: cleanString(args.topicNode.projectId),\n topicId: topicGlobalId,\n tenantId: cleanString(args.topicNode.tenantId),\n workspaceId: cleanString(args.topicNode.workspaceId),\n fromNodeType: \"belief\",\n toNodeType: \"topic\",\n fromLayer: \"L3\",\n toLayer: args.topicNode.epistemicLayer ?? \"ontological\",\n } as any);\n }\n\n await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {\n globalId: edgeGlobalId,\n fromGlobalId: args.beliefGlobalId,\n toGlobalId: topicGlobalId,\n edgeType: \"belongs_to\",\n weight: 1,\n confidence: 1,\n context: \"Belief creation topic anchor invariant.\",\n projectId: cleanString(args.topicNode.projectId),\n topicId: topicGlobalId,\n createdBy: args.createdBy,\n fromNodeType: \"belief\",\n toNodeType: \"topic\",\n fromLayer: \"L3\",\n toLayer: args.topicNode.epistemicLayer ?? \"ontological\",\n metadata: {\n invariant: \"belief.topic_edge_required\",\n edgeUuid: edgeGlobalId,\n fromUuid: args.beliefGlobalId,\n toUuid: topicGlobalId,\n },\n });\n}\n"]}
|
|
@@ -146,6 +146,35 @@ function debugGraphPrimitiveFallback(message, context) {
|
|
|
146
146
|
console.debug(message, context ?? {});
|
|
147
147
|
}
|
|
148
148
|
var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
|
|
149
|
+
async function resolveTopicNodeScopeOrNull(ctx, ref) {
|
|
150
|
+
if (!ctx?.db || typeof ctx.db.query !== "function") {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
let node = null;
|
|
154
|
+
try {
|
|
155
|
+
const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
|
|
156
|
+
if (byGlobalId && byGlobalId.nodeType === "topic") {
|
|
157
|
+
node = byGlobalId;
|
|
158
|
+
}
|
|
159
|
+
} catch (error) {
|
|
160
|
+
debugGraphPrimitiveFallback(
|
|
161
|
+
"[topicScope] topic-node scope lookup by globalId failed",
|
|
162
|
+
{ error, ref }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
if (!node) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
|
|
169
|
+
if (!scopeKey) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
topicId: scopeKey,
|
|
174
|
+
projectId: asMappedProjectId(node),
|
|
175
|
+
source: "topic_node"
|
|
176
|
+
};
|
|
177
|
+
}
|
|
149
178
|
function asMappedProjectId(topic) {
|
|
150
179
|
if (!topic) {
|
|
151
180
|
return;
|
|
@@ -286,6 +315,13 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
286
315
|
) ?? null;
|
|
287
316
|
}
|
|
288
317
|
if (!topic) {
|
|
318
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
319
|
+
ctx,
|
|
320
|
+
String(args.topicId)
|
|
321
|
+
);
|
|
322
|
+
if (nodeScope) {
|
|
323
|
+
return nodeScope;
|
|
324
|
+
}
|
|
289
325
|
throw new Error(`Topic not found: ${String(args.topicId)}`);
|
|
290
326
|
}
|
|
291
327
|
const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
|
|
@@ -356,6 +392,16 @@ async function resolveTopicProjectScope(ctx, args) {
|
|
|
356
392
|
source: "project_mapped_topic"
|
|
357
393
|
};
|
|
358
394
|
}
|
|
395
|
+
const nodeScope = await resolveTopicNodeScopeOrNull(
|
|
396
|
+
ctx,
|
|
397
|
+
String(args.projectId)
|
|
398
|
+
);
|
|
399
|
+
if (nodeScope) {
|
|
400
|
+
return {
|
|
401
|
+
...nodeScope,
|
|
402
|
+
projectId: nodeScope.projectId ?? String(args.projectId)
|
|
403
|
+
};
|
|
404
|
+
}
|
|
359
405
|
throw new Error(
|
|
360
406
|
`Legacy project scope ${String(args.projectId)} has no mapped topic.`
|
|
361
407
|
);
|
|
@@ -1240,14 +1286,14 @@ async function applyBeliefConfidenceChange(ctx, args) {
|
|
|
1240
1286
|
beliefConfidenceId
|
|
1241
1287
|
};
|
|
1242
1288
|
}
|
|
1243
|
-
function
|
|
1289
|
+
function propagationPressureLabel(edgeType, weight) {
|
|
1244
1290
|
if (edgeType === "contradicts" || edgeType === "refutes") {
|
|
1245
|
-
return "
|
|
1291
|
+
return "contradictory";
|
|
1246
1292
|
}
|
|
1247
1293
|
if ((edgeType === "supports" || edgeType === "informs") && weight < 0) {
|
|
1248
|
-
return "
|
|
1294
|
+
return "contradictory";
|
|
1249
1295
|
}
|
|
1250
|
-
return "
|
|
1296
|
+
return "supportive";
|
|
1251
1297
|
}
|
|
1252
1298
|
internalMutation({
|
|
1253
1299
|
args: {
|
|
@@ -1284,14 +1330,15 @@ internalMutation({
|
|
|
1284
1330
|
getNode: async (nodeId) => await ctx.db.get(nodeId)
|
|
1285
1331
|
});
|
|
1286
1332
|
for (const dispatch of dispatches) {
|
|
1333
|
+
const pressureLabel = propagationPressureLabel(dispatch.edgeType, dispatch.weight);
|
|
1287
1334
|
await applyBeliefConfidenceChange(ctx, {
|
|
1288
1335
|
nodeId: dispatch.targetNodeId,
|
|
1289
1336
|
belief: dispatch.opinion.b,
|
|
1290
1337
|
disbelief: dispatch.opinion.d,
|
|
1291
1338
|
uncertainty: dispatch.opinion.u,
|
|
1292
1339
|
baseRate: dispatch.opinion.a,
|
|
1293
|
-
trigger:
|
|
1294
|
-
rationale: `SL propagation via ${dispatch.edgeType} edge: ${dispatch.rationale}`,
|
|
1340
|
+
trigger: "propagation",
|
|
1341
|
+
rationale: `SL propagation via ${dispatch.edgeType} edge (pressure: ${pressureLabel}): ${dispatch.rationale}`,
|
|
1295
1342
|
authenticatedUserId: args.userId,
|
|
1296
1343
|
slOperator: dispatch.operator
|
|
1297
1344
|
});
|