@lucern/graph-primitives 1.0.16 → 1.0.17

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.
Files changed (65) hide show
  1. package/dist/beliefEvidenceLinks.js +144 -99
  2. package/dist/beliefEvidenceLinks.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.operational.d.ts +29 -0
  4. package/dist/beliefEvidenceLinks.operational.js +157 -0
  5. package/dist/beliefEvidenceLinks.operational.js.map +1 -0
  6. package/dist/{beliefLifecycle-y8WLXqQj.d.ts → beliefLifecycle-CXwdDw5e.d.ts} +7 -4
  7. package/dist/beliefLifecycle.d.ts +1 -1
  8. package/dist/beliefLifecycle.js +75 -18
  9. package/dist/beliefLifecycle.js.map +1 -1
  10. package/dist/epistemicBeliefs.admin.js.map +1 -1
  11. package/dist/epistemicBeliefs.backfills.d.ts +1 -1
  12. package/dist/epistemicBeliefs.backfills.js +63 -35
  13. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  14. package/dist/epistemicBeliefs.confidence.d.ts +1 -1
  15. package/dist/epistemicBeliefs.confidence.js +70 -41
  16. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  17. package/dist/epistemicBeliefs.core.js +957 -566
  18. package/dist/epistemicBeliefs.core.js.map +1 -1
  19. package/dist/epistemicBeliefs.d.ts +2 -2
  20. package/dist/epistemicBeliefs.forkEvidence.d.ts +18 -0
  21. package/dist/epistemicBeliefs.forkEvidence.js +121 -0
  22. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -0
  23. package/dist/epistemicBeliefs.helpers.d.ts +2 -2
  24. package/dist/epistemicBeliefs.helpers.js +60 -32
  25. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  26. package/dist/epistemicBeliefs.internal.js +174 -39
  27. package/dist/epistemicBeliefs.internal.js.map +1 -1
  28. package/dist/epistemicBeliefs.js +436 -72
  29. package/dist/epistemicBeliefs.js.map +1 -1
  30. package/dist/epistemicBeliefs.lifecycle.d.ts +2 -2
  31. package/dist/epistemicBeliefs.lifecycle.js +75 -47
  32. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  33. package/dist/epistemicBeliefs.links.js +46 -1
  34. package/dist/epistemicBeliefs.links.js.map +1 -1
  35. package/dist/epistemicBeliefs.topicAnchor.d.ts +29 -0
  36. package/dist/epistemicBeliefs.topicAnchor.js +105 -0
  37. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -0
  38. package/dist/epistemicContracts.evaluators.js +71 -42
  39. package/dist/epistemicContracts.evaluators.js.map +1 -1
  40. package/dist/epistemicContracts.handlers.js +71 -42
  41. package/dist/epistemicContracts.handlers.js.map +1 -1
  42. package/dist/epistemicContracts.js +71 -42
  43. package/dist/epistemicContracts.js.map +1 -1
  44. package/dist/epistemicContracts.metrics.js +1 -1
  45. package/dist/epistemicContracts.metrics.js.map +1 -1
  46. package/dist/epistemicContracts.types.d.ts +1 -1
  47. package/dist/epistemicEdges.helpers.d.ts +1 -1
  48. package/dist/epistemicEvidence.js +172 -81
  49. package/dist/epistemicEvidence.js.map +1 -1
  50. package/dist/epistemicEvidenceMutations.js +172 -81
  51. package/dist/epistemicEvidenceMutations.js.map +1 -1
  52. package/dist/epistemicNodes.internal.js.map +1 -1
  53. package/dist/epistemicNodes.js +2 -2
  54. package/dist/epistemicNodes.js.map +1 -1
  55. package/dist/epistemicNodes.mutations.js +2 -2
  56. package/dist/epistemicNodes.mutations.js.map +1 -1
  57. package/dist/evaluators/index.js +1 -1
  58. package/dist/evaluators/index.js.map +1 -1
  59. package/dist/index.d.ts +2 -2
  60. package/dist/index.js +767 -236
  61. package/dist/index.js.map +1 -1
  62. package/dist/invariantEnforcement.js +2 -2
  63. package/dist/invariantEnforcement.js.map +1 -1
  64. package/dist/proof-attestation.json +3 -3
  65. package/package.json +4 -4
@@ -773,6 +773,91 @@ async function resolveEvidenceScopeOrNull(ctx, args) {
773
773
  }
774
774
 
775
775
  // src/epistemicEvidenceMutations.ts
776
+ function assertSignedImpactScore(value, context) {
777
+ if (typeof value !== "number" || !Number.isFinite(value) || value === 0 || value < -1 || value > 1) {
778
+ throw new Error(`${context} requires explicit nonzero weight in [-1, 1]`);
779
+ }
780
+ return value;
781
+ }
782
+ function normalizeEvidenceRelation(relation, weight, context) {
783
+ if (relation === "supports" || relation === "contradicts") {
784
+ if (relation === "supports" && weight < 0) {
785
+ throw new Error(`${context} supports relation requires positive weight`);
786
+ }
787
+ if (relation === "contradicts" && weight > 0) {
788
+ throw new Error(`${context} contradicts relation requires negative weight`);
789
+ }
790
+ return relation;
791
+ }
792
+ return weight < 0 ? "contradicts" : "supports";
793
+ }
794
+ async function createEvidenceBeliefEdge(ctx, args) {
795
+ const edgeGlobalId = crypto.randomUUID();
796
+ const confidence = Math.abs(args.weight);
797
+ const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
798
+ "by_from_to",
799
+ (q) => q.eq("fromNodeId", args.evidenceNodeId).eq("toNodeId", args.beliefNodeId)
800
+ ).collect();
801
+ const existing = existingEdges.find((edge) => edge.edgeType === "informs");
802
+ const edgeDoc = {
803
+ globalId: edgeGlobalId,
804
+ fromNodeId: args.evidenceNodeId,
805
+ toNodeId: args.beliefNodeId,
806
+ sourceGlobalId: args.evidenceGlobalId,
807
+ targetGlobalId: args.beliefGlobalId,
808
+ edgeType: "informs",
809
+ weight: args.weight,
810
+ confidence,
811
+ context: args.rationale,
812
+ reasoningMethod: "testimonial",
813
+ derivationType: "evidence_sl_scoring",
814
+ metadata: {
815
+ relation: args.relation,
816
+ confidence,
817
+ impactScore: args.weight,
818
+ invariant: "evidence.belief_impact_required"
819
+ },
820
+ createdBy: args.userId,
821
+ createdAt: Date.now(),
822
+ updatedAt: Date.now(),
823
+ topicId: args.topicId,
824
+ projectId: args.projectId,
825
+ fromNodeType: "evidence",
826
+ toNodeType: "belief",
827
+ fromLayer: "L2",
828
+ toLayer: "L3"
829
+ };
830
+ if (existing) {
831
+ await ctx.db.patch(existing._id, {
832
+ ...edgeDoc,
833
+ globalId: existing.globalId,
834
+ createdAt: existing.createdAt ?? edgeDoc.createdAt
835
+ });
836
+ } else {
837
+ await ctx.db.insert("epistemicEdges", edgeDoc);
838
+ }
839
+ await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
840
+ globalId: existing?.globalId ?? edgeGlobalId,
841
+ fromGlobalId: args.evidenceGlobalId,
842
+ toGlobalId: args.beliefGlobalId,
843
+ edgeType: "informs",
844
+ weight: args.weight,
845
+ confidence,
846
+ createdBy: args.userId,
847
+ topicId: args.projectId ?? args.topicId,
848
+ fromNodeType: "evidence",
849
+ toNodeType: "belief",
850
+ fromLayer: "L2",
851
+ toLayer: "L3",
852
+ metadata: {
853
+ relation: args.relation,
854
+ confidence,
855
+ impactScore: args.weight,
856
+ invariant: "evidence.belief_impact_required"
857
+ }
858
+ });
859
+ return existing?.globalId ?? edgeGlobalId;
860
+ }
776
861
  var create = mutation({
777
862
  args: {
778
863
  ...optionalEvidenceScopeArgs,
@@ -793,11 +878,12 @@ var create = mutation({
793
878
  informationAsymmetry: v.optional(v.string()),
794
879
  sourceDescription: v.optional(v.string()),
795
880
  metadata: v.optional(v.any()),
796
- // Optional linking to beliefs
797
- linkedBeliefNodeId: v.optional(v.id("epistemicNodes")),
881
+ // Required belief impact link.
882
+ linkedBeliefNodeId: v.id("epistemicNodes"),
798
883
  evidenceRelation: v.optional(
799
884
  v.union(v.literal("supports"), v.literal("contradicts"))
800
885
  ),
886
+ weight: v.number(),
801
887
  confidence: v.optional(v.number())
802
888
  },
803
889
  returns: permissiveReturn,
@@ -819,6 +905,16 @@ var create = mutation({
819
905
  const contentHash = generateContentHash(args.text);
820
906
  const kind = normalizeKind(args.kind);
821
907
  const sourceType = normalizeSourceType(args.sourceType);
908
+ const weight = assertSignedImpactScore(args.weight, "Evidence creation");
909
+ const evidenceRelation = normalizeEvidenceRelation(
910
+ args.evidenceRelation,
911
+ weight,
912
+ "Evidence creation"
913
+ );
914
+ const linkedBeliefNode = await ctx.db.get(args.linkedBeliefNodeId);
915
+ if (!linkedBeliefNode || linkedBeliefNode.nodeType !== "belief") {
916
+ throw new Error("Evidence creation requires a linked belief node");
917
+ }
822
918
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
823
919
  const nodeId = await ctx.db.insert("epistemicNodes", {
824
920
  globalId,
@@ -846,8 +942,10 @@ var create = mutation({
846
942
  sourceQuestionId: args.sourceQuestionId,
847
943
  rationale: args.rationale,
848
944
  linkedBeliefNodeId: args.linkedBeliefNodeId,
849
- evidenceRelation: args.evidenceRelation,
850
- confidence: args.confidence,
945
+ evidenceRelation,
946
+ confidence: Math.abs(weight),
947
+ weight,
948
+ impactScore: weight,
851
949
  methodology: args.methodology,
852
950
  informationAsymmetry: args.informationAsymmetry,
853
951
  sourceDescription: args.sourceDescription,
@@ -867,29 +965,18 @@ var create = mutation({
867
965
  nodeType: "evidence",
868
966
  text: args.text
869
967
  });
870
- if (args.linkedBeliefNodeId && args.evidenceRelation) {
871
- const beliefNode = await ctx.db.get(args.linkedBeliefNodeId);
872
- if (beliefNode) {
873
- const weight = args.evidenceRelation === "supports" ? 1 : -1;
874
- await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
875
- globalId: crypto.randomUUID(),
876
- fromGlobalId: globalId,
877
- toGlobalId: beliefNode.globalId,
878
- edgeType: "informs",
879
- weight: weight * (args.confidence || 0.7),
880
- createdBy: args.userId,
881
- topicId: scope.projectId ? String(scope.projectId) : void 0,
882
- fromNodeType: "evidence",
883
- toNodeType: "belief",
884
- fromLayer: "L2",
885
- toLayer: "L3",
886
- metadata: {
887
- relation: args.evidenceRelation,
888
- confidence: args.confidence
889
- }
890
- });
891
- }
892
- }
968
+ await createEvidenceBeliefEdge(ctx, {
969
+ evidenceNodeId: nodeId,
970
+ evidenceGlobalId: globalId,
971
+ beliefNodeId: args.linkedBeliefNodeId,
972
+ beliefGlobalId: linkedBeliefNode.globalId,
973
+ relation: evidenceRelation,
974
+ weight,
975
+ userId: args.userId,
976
+ topicId: scope.topicId ? String(scope.topicId) : void 0,
977
+ projectId: scope.projectId ? String(scope.projectId) : void 0,
978
+ rationale: args.rationale
979
+ });
893
980
  await ctx.db.insert("epistemicAudit", {
894
981
  entityType: "evidence",
895
982
  entityId: nodeId,
@@ -904,7 +991,8 @@ var create = mutation({
904
991
  kind,
905
992
  sourceType,
906
993
  linkedBeliefNodeId: args.linkedBeliefNodeId,
907
- evidenceRelation: args.evidenceRelation
994
+ evidenceRelation,
995
+ weight
908
996
  }
909
997
  });
910
998
  if (scope.projectId || scope.topicId) {
@@ -947,6 +1035,7 @@ var createAndLink = mutation({
947
1035
  userId: v.string(),
948
1036
  beliefNodeId: v.id("epistemicNodes"),
949
1037
  relation: v.union(v.literal("supports"), v.literal("contradicts")),
1038
+ weight: v.number(),
950
1039
  confidence: v.optional(v.number())
951
1040
  },
952
1041
  returns: permissiveReturn,
@@ -961,7 +1050,17 @@ var createAndLink = mutation({
961
1050
  const contentHash = generateContentHash(args.text);
962
1051
  const kind = normalizeKind(args.kind);
963
1052
  const sourceType = normalizeSourceType(args.sourceType);
964
- const confidence = args.confidence ?? 0.7;
1053
+ const weight = assertSignedImpactScore(args.weight, "Evidence createAndLink");
1054
+ const relation = normalizeEvidenceRelation(
1055
+ args.relation,
1056
+ weight,
1057
+ "Evidence createAndLink"
1058
+ );
1059
+ const confidence = Math.abs(weight);
1060
+ const beliefNode = await ctx.db.get(args.beliefNodeId);
1061
+ if (!beliefNode || beliefNode.nodeType !== "belief") {
1062
+ throw new Error("Belief node not found for edge creation");
1063
+ }
965
1064
  const nodeId = await ctx.db.insert("epistemicNodes", {
966
1065
  globalId,
967
1066
  topicId: scope.topicId,
@@ -981,36 +1080,26 @@ var createAndLink = mutation({
981
1080
  kind,
982
1081
  tags: args.tags || [],
983
1082
  linkedBeliefNodeId: args.beliefNodeId,
984
- evidenceRelation: args.relation,
985
- confidence
1083
+ evidenceRelation: relation,
1084
+ confidence,
1085
+ weight,
1086
+ impactScore: weight
986
1087
  }
987
1088
  });
988
1089
  await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
989
1090
  nodeId,
990
1091
  operation: "upsert"
991
1092
  });
992
- const beliefNode = await ctx.db.get(args.beliefNodeId);
993
- if (!beliefNode) {
994
- throw new Error("Belief node not found for edge creation");
995
- }
996
- const weight = args.relation === "supports" ? confidence : -confidence;
997
- const edgeGlobalId = crypto.randomUUID();
998
- await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
999
- globalId: edgeGlobalId,
1000
- fromGlobalId: globalId,
1001
- toGlobalId: beliefNode.globalId,
1002
- edgeType: "informs",
1093
+ const edgeGlobalId = await createEvidenceBeliefEdge(ctx, {
1094
+ evidenceNodeId: nodeId,
1095
+ evidenceGlobalId: globalId,
1096
+ beliefNodeId: args.beliefNodeId,
1097
+ beliefGlobalId: beliefNode.globalId,
1098
+ relation,
1003
1099
  weight,
1004
- createdBy: args.userId,
1005
- topicId: scope.projectId,
1006
- fromNodeType: "evidence",
1007
- toNodeType: "belief",
1008
- fromLayer: "L2",
1009
- toLayer: "L3",
1010
- metadata: {
1011
- relation: args.relation,
1012
- confidence
1013
- }
1100
+ userId: args.userId,
1101
+ topicId: scope.topicId ? String(scope.topicId) : void 0,
1102
+ projectId: scope.projectId ? String(scope.projectId) : void 0
1014
1103
  });
1015
1104
  await markProjectGraphDirty(ctx, scope.projectId, String(scope.topicId));
1016
1105
  return { nodeId, edgeGlobalId };
@@ -1071,8 +1160,9 @@ var internalCreate = internalMutation({
1071
1160
  sourceQuestionId: v.optional(v.string()),
1072
1161
  userId: v.string(),
1073
1162
  rationale: v.string(),
1074
- linkedBeliefNodeId: v.optional(v.id("epistemicNodes")),
1163
+ linkedBeliefNodeId: v.id("epistemicNodes"),
1075
1164
  evidenceRelation: v.optional(v.string()),
1165
+ weight: v.number(),
1076
1166
  confidence: v.optional(v.number()),
1077
1167
  metadata: v.optional(v.any()),
1078
1168
  runtimeToolName: v.optional(v.string()),
@@ -1107,6 +1197,16 @@ var internalCreate = internalMutation({
1107
1197
  const contentHash = generateContentHash(args.text);
1108
1198
  const kind = normalizeKind(args.kind);
1109
1199
  const sourceType = normalizeSourceType(args.sourceType);
1200
+ const weight = assertSignedImpactScore(args.weight, "Internal evidence creation");
1201
+ const evidenceRelation = normalizeEvidenceRelation(
1202
+ args.evidenceRelation,
1203
+ weight,
1204
+ "Internal evidence creation"
1205
+ );
1206
+ const linkedBeliefNode = await ctx.db.get(args.linkedBeliefNodeId);
1207
+ if (!linkedBeliefNode || linkedBeliefNode.nodeType !== "belief") {
1208
+ throw new Error("Internal evidence creation requires a linked belief node");
1209
+ }
1110
1210
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
1111
1211
  const nodeId = await ctx.db.insert("epistemicNodes", {
1112
1212
  globalId,
@@ -1134,8 +1234,10 @@ var internalCreate = internalMutation({
1134
1234
  sourceQuestionId: args.sourceQuestionId,
1135
1235
  rationale: args.rationale,
1136
1236
  linkedBeliefNodeId: args.linkedBeliefNodeId,
1137
- evidenceRelation: args.evidenceRelation,
1138
- confidence: args.confidence,
1237
+ evidenceRelation,
1238
+ confidence: Math.abs(weight),
1239
+ weight,
1240
+ impactScore: weight,
1139
1241
  ...additionalMetadata
1140
1242
  }
1141
1243
  });
@@ -1155,8 +1257,9 @@ var internalCreate = internalMutation({
1155
1257
  externalSourceType: args.externalSourceType,
1156
1258
  sourceUrl: args.sourceUrl,
1157
1259
  linkedBeliefNodeId: args.linkedBeliefNodeId,
1158
- evidenceRelation: args.evidenceRelation,
1159
- confidence: args.confidence
1260
+ evidenceRelation,
1261
+ confidence: Math.abs(weight),
1262
+ weight
1160
1263
  },
1161
1264
  triggeringAction: "epistemicEvidence.internalCreate"
1162
1265
  });
@@ -1164,30 +1267,18 @@ var internalCreate = internalMutation({
1164
1267
  nodeId,
1165
1268
  operation: "upsert"
1166
1269
  });
1167
- if (args.linkedBeliefNodeId && args.evidenceRelation) {
1168
- const beliefNode = await ctx.db.get(args.linkedBeliefNodeId);
1169
- if (beliefNode) {
1170
- const confidence = args.confidence ?? 0.7;
1171
- const weight = args.evidenceRelation === "supports" ? confidence : -confidence;
1172
- await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
1173
- globalId: crypto.randomUUID(),
1174
- fromGlobalId: globalId,
1175
- toGlobalId: beliefNode.globalId,
1176
- edgeType: "informs",
1177
- weight,
1178
- createdBy: args.userId,
1179
- topicId: scope.projectId ? String(scope.projectId) : void 0,
1180
- fromNodeType: "evidence",
1181
- toNodeType: "belief",
1182
- fromLayer: "L2",
1183
- toLayer: "L3",
1184
- metadata: {
1185
- relation: args.evidenceRelation,
1186
- confidence
1187
- }
1188
- });
1189
- }
1190
- }
1270
+ await createEvidenceBeliefEdge(ctx, {
1271
+ evidenceNodeId: nodeId,
1272
+ evidenceGlobalId: globalId,
1273
+ beliefNodeId: args.linkedBeliefNodeId,
1274
+ beliefGlobalId: linkedBeliefNode.globalId,
1275
+ relation: evidenceRelation,
1276
+ weight,
1277
+ userId: args.userId,
1278
+ topicId: scope.topicId ? String(scope.topicId) : void 0,
1279
+ projectId: scope.projectId ? String(scope.projectId) : void 0,
1280
+ rationale: args.rationale
1281
+ });
1191
1282
  if (scope.projectId || scope.topicId) {
1192
1283
  await ctx.scheduler.runAfter(
1193
1284
  0,