@lucern/graph-primitives 1.0.22 → 1.0.24

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 (136) hide show
  1. package/dist/beliefDecay.js +49 -0
  2. package/dist/beliefDecay.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.js +99 -5
  4. package/dist/beliefEvidenceLinks.js.map +1 -1
  5. package/dist/beliefEvidenceLinks.operational.js +50 -5
  6. package/dist/beliefEvidenceLinks.operational.js.map +1 -1
  7. package/dist/contradictions.js +46 -0
  8. package/dist/contradictions.js.map +1 -1
  9. package/dist/edgeValidation.js +66 -1
  10. package/dist/edgeValidation.js.map +1 -1
  11. package/dist/entityBridge.js +66 -1
  12. package/dist/entityBridge.js.map +1 -1
  13. package/dist/entityCanonicalMatch.d.ts +40 -0
  14. package/dist/entityCanonicalMatch.js +33 -0
  15. package/dist/entityCanonicalMatch.js.map +1 -0
  16. package/dist/entityLifecycle.js +149 -39
  17. package/dist/entityLifecycle.js.map +1 -1
  18. package/dist/epistemicAnswers.js +64 -11
  19. package/dist/epistemicAnswers.js.map +1 -1
  20. package/dist/epistemicBeliefs.admin.js +63 -6
  21. package/dist/epistemicBeliefs.admin.js.map +1 -1
  22. package/dist/epistemicBeliefs.backfills.js +59 -2
  23. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  24. package/dist/epistemicBeliefs.confidence.d.ts +1 -1
  25. package/dist/epistemicBeliefs.confidence.js +70 -12
  26. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  27. package/dist/epistemicBeliefs.core.js +120 -17
  28. package/dist/epistemicBeliefs.core.js.map +1 -1
  29. package/dist/epistemicBeliefs.d.ts +1 -1
  30. package/dist/epistemicBeliefs.forkEvidence.js +13 -2
  31. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  32. package/dist/epistemicBeliefs.helpers.d.ts +18 -3
  33. package/dist/epistemicBeliefs.helpers.js +66 -6
  34. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  35. package/dist/epistemicBeliefs.internal.js +115 -12
  36. package/dist/epistemicBeliefs.internal.js.map +1 -1
  37. package/dist/epistemicBeliefs.js +132 -28
  38. package/dist/epistemicBeliefs.js.map +1 -1
  39. package/dist/epistemicBeliefs.lifecycle.js +70 -12
  40. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  41. package/dist/epistemicBeliefs.links.js +111 -10
  42. package/dist/epistemicBeliefs.links.js.map +1 -1
  43. package/dist/epistemicBeliefs.topicAnchor.js +48 -8
  44. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  45. package/dist/epistemicContracts.evaluators.js +70 -12
  46. package/dist/epistemicContracts.evaluators.js.map +1 -1
  47. package/dist/epistemicContracts.handlers.js +71 -16
  48. package/dist/epistemicContracts.handlers.js.map +1 -1
  49. package/dist/epistemicContracts.js +71 -16
  50. package/dist/epistemicContracts.js.map +1 -1
  51. package/dist/epistemicEdges.d.ts +1 -1
  52. package/dist/epistemicEdges.handlers.js +57 -3
  53. package/dist/epistemicEdges.handlers.js.map +1 -1
  54. package/dist/epistemicEdges.helpers.d.ts +2 -2
  55. package/dist/epistemicEdges.js +174 -4
  56. package/dist/epistemicEdges.js.map +1 -1
  57. package/dist/epistemicEdges.mutations.js +115 -1
  58. package/dist/epistemicEdges.mutations.js.map +1 -1
  59. package/dist/epistemicEdges.queries.js +46 -0
  60. package/dist/epistemicEdges.queries.js.map +1 -1
  61. package/dist/epistemicEdges.types.d.ts +1 -1
  62. package/dist/epistemicEvidence.d.ts +1 -1
  63. package/dist/epistemicEvidence.js +180 -14
  64. package/dist/epistemicEvidence.js.map +1 -1
  65. package/dist/epistemicEvidenceHelpers.d.ts +1 -1
  66. package/dist/epistemicEvidenceHelpers.js +49 -0
  67. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  68. package/dist/epistemicEvidenceMutations.js +180 -14
  69. package/dist/epistemicEvidenceMutations.js.map +1 -1
  70. package/dist/epistemicEvidenceQueries.js +49 -0
  71. package/dist/epistemicEvidenceQueries.js.map +1 -1
  72. package/dist/epistemicHelpers.js +11 -6
  73. package/dist/epistemicHelpers.js.map +1 -1
  74. package/dist/epistemicInsert.d.ts +8 -0
  75. package/dist/epistemicInsert.js +54 -0
  76. package/dist/epistemicInsert.js.map +1 -0
  77. package/dist/epistemicNodeCreation.js +11 -6
  78. package/dist/epistemicNodeCreation.js.map +1 -1
  79. package/dist/epistemicNodes.helpers.d.ts +1 -1
  80. package/dist/epistemicNodes.internal.js +53 -1
  81. package/dist/epistemicNodes.internal.js.map +1 -1
  82. package/dist/epistemicNodes.js +56 -4
  83. package/dist/epistemicNodes.js.map +1 -1
  84. package/dist/epistemicNodes.mutations.js +55 -3
  85. package/dist/epistemicNodes.mutations.js.map +1 -1
  86. package/dist/epistemicNodes.queries.js +46 -0
  87. package/dist/epistemicNodes.queries.js.map +1 -1
  88. package/dist/epistemicNodes.validators.d.ts +1 -1
  89. package/dist/epistemicQuestions.conviction.js +49 -0
  90. package/dist/epistemicQuestions.conviction.js.map +1 -1
  91. package/dist/epistemicQuestions.create.js +61 -7
  92. package/dist/epistemicQuestions.create.js.map +1 -1
  93. package/dist/epistemicQuestions.d.ts +1 -1
  94. package/dist/epistemicQuestions.evidence.js +56 -2
  95. package/dist/epistemicQuestions.evidence.js.map +1 -1
  96. package/dist/epistemicQuestions.helpers.d.ts +1 -1
  97. package/dist/epistemicQuestions.helpers.js +49 -0
  98. package/dist/epistemicQuestions.helpers.js.map +1 -1
  99. package/dist/epistemicQuestions.js +63 -9
  100. package/dist/epistemicQuestions.js.map +1 -1
  101. package/dist/epistemicQuestions.lifecycle.js +49 -0
  102. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  103. package/dist/epistemicQuestions.queries.js +49 -0
  104. package/dist/epistemicQuestions.queries.js.map +1 -1
  105. package/dist/epistemicQuestions.sprint.js +46 -0
  106. package/dist/epistemicQuestions.sprint.js.map +1 -1
  107. package/dist/epistemicQuestions.tail.js +56 -2
  108. package/dist/epistemicQuestions.tail.js.map +1 -1
  109. package/dist/epistemicSources.js +53 -2
  110. package/dist/epistemicSources.js.map +1 -1
  111. package/dist/helpers.js +66 -1
  112. package/dist/helpers.js.map +1 -1
  113. package/dist/index.d.ts +1 -1
  114. package/dist/index.js +379 -115
  115. package/dist/index.js.map +1 -1
  116. package/dist/proof-attestation.json +1 -1
  117. package/dist/questionEvidenceLinks.js +49 -0
  118. package/dist/questionEvidenceLinks.js.map +1 -1
  119. package/dist/resolvers.js +3 -0
  120. package/dist/resolvers.js.map +1 -1
  121. package/dist/scopeResolverCompat.d.ts +1 -1
  122. package/dist/scopeResolverCompat.js +46 -0
  123. package/dist/scopeResolverCompat.js.map +1 -1
  124. package/dist/topicProjectOverlay.d.ts +4 -0
  125. package/dist/topicProjectOverlay.js +3 -0
  126. package/dist/topicProjectOverlay.js.map +1 -1
  127. package/dist/{topicScope-By_zp4tt.d.ts → topicScope-7zhyeGl7.d.ts} +1 -1
  128. package/dist/topicScope.d.ts +1 -1
  129. package/dist/topicScope.js +46 -0
  130. package/dist/topicScope.js.map +1 -1
  131. package/dist/workflowBridge.js +46 -0
  132. package/dist/workflowBridge.js.map +1 -1
  133. package/dist/workspaceIsolation.d.ts +1 -1
  134. package/dist/workspaceIsolation.js +46 -0
  135. package/dist/workspaceIsolation.js.map +1 -1
  136. package/package.json +4 -4
@@ -2,9 +2,10 @@ import { v } from 'convex/values';
2
2
  import { requireProjectAccess, checkProjectAccess } from '@lucern/access-control/access';
3
3
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
4
4
  import { componentsGeneric, anyApi, mutationGeneric, internalMutationGeneric } from 'convex/server';
5
- import { generateGlobalId } from '@lucern/contracts/ids';
5
+ import { generateGlobalId, assertUuidV7Identity, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
6
6
  import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
7
7
  import '@lucern/access-control/audience';
8
+ import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
8
9
 
9
10
  // src/epistemicEvidenceMutations.ts
10
11
  var api = anyApi;
@@ -54,6 +55,35 @@ async function scheduleEmbeddingGeneration(args) {
54
55
  }
55
56
  }
56
57
  var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
58
+ async function resolveTopicNodeScopeOrNull(ctx, ref) {
59
+ if (!ctx?.db || typeof ctx.db.query !== "function") {
60
+ return null;
61
+ }
62
+ let node = null;
63
+ try {
64
+ const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
65
+ if (byGlobalId && byGlobalId.nodeType === "topic") {
66
+ node = byGlobalId;
67
+ }
68
+ } catch (error) {
69
+ debugGraphPrimitiveFallback(
70
+ "[topicScope] topic-node scope lookup by globalId failed",
71
+ { error, ref }
72
+ );
73
+ }
74
+ if (!node) {
75
+ return null;
76
+ }
77
+ const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
78
+ if (!scopeKey) {
79
+ return null;
80
+ }
81
+ return {
82
+ topicId: scopeKey,
83
+ projectId: asMappedProjectId(node),
84
+ source: "topic_node"
85
+ };
86
+ }
57
87
  function asMappedProjectId(topic) {
58
88
  if (!topic) {
59
89
  return;
@@ -194,6 +224,13 @@ async function resolveTopicProjectScope(ctx, args) {
194
224
  ) ?? null;
195
225
  }
196
226
  if (!topic) {
227
+ const nodeScope = await resolveTopicNodeScopeOrNull(
228
+ ctx,
229
+ String(args.topicId)
230
+ );
231
+ if (nodeScope) {
232
+ return nodeScope;
233
+ }
197
234
  throw new Error(`Topic not found: ${String(args.topicId)}`);
198
235
  }
199
236
  const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
@@ -264,6 +301,16 @@ async function resolveTopicProjectScope(ctx, args) {
264
301
  source: "project_mapped_topic"
265
302
  };
266
303
  }
304
+ const nodeScope = await resolveTopicNodeScopeOrNull(
305
+ ctx,
306
+ String(args.projectId)
307
+ );
308
+ if (nodeScope) {
309
+ return {
310
+ ...nodeScope,
311
+ projectId: nodeScope.projectId ?? String(args.projectId)
312
+ };
313
+ }
267
314
  throw new Error(
268
315
  `Legacy project scope ${String(args.projectId)} has no mapped topic.`
269
316
  );
@@ -482,6 +529,9 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
482
529
  type: mapProjectType(topic, metadata),
483
530
  description: readNonEmptyString(topic.description),
484
531
  ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
532
+ // FR.7 creator-grant: surface the principal-shaped owner field (column-first,
533
+ // metadata fallback for legacy rows that recorded it in metadata).
534
+ ownerPrincipalId: readNonEmptyString(topic.ownerPrincipalId) || readNonEmptyString(metadata.ownerPrincipalId),
485
535
  sharedWith: readStringArray(metadata.sharedWith),
486
536
  visibility,
487
537
  tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
@@ -760,6 +810,52 @@ async function resolveEvidenceScopeOrNull(ctx, args) {
760
810
  return null;
761
811
  }
762
812
  }
813
+ async function insertEpistemicNode(ctx, doc) {
814
+ assertUuidV7Identity("epistemicNodes", doc.globalId);
815
+ return ctx.db.insert("epistemicNodes", doc);
816
+ }
817
+ async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
818
+ assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
819
+ const node = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", endpoint)).first();
820
+ if (!node) {
821
+ throw new Error(
822
+ `edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
823
+ );
824
+ }
825
+ }
826
+ async function insertEpistemicEdge(ctx, doc) {
827
+ assertUuidV7Identity("epistemicEdges", doc.globalId);
828
+ assertStorageEdgeVocabulary(doc.edgeType);
829
+ if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
830
+ throw new Error(
831
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
832
+ );
833
+ }
834
+ if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
835
+ throw new Error(
836
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
837
+ );
838
+ }
839
+ await assertExistingNodeEndpoint(ctx, "fromNodeId", doc.fromNodeId);
840
+ await assertExistingNodeEndpoint(ctx, "toNodeId", doc.toNodeId);
841
+ if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
842
+ assertEdgePolicyAllowed(
843
+ edgePolicyManifest,
844
+ doc.edgeType,
845
+ {
846
+ kind: "epistemic_node",
847
+ nodeId: doc.fromNodeId,
848
+ nodeType: doc.fromNodeType
849
+ },
850
+ {
851
+ kind: "epistemic_node",
852
+ nodeId: doc.toNodeId,
853
+ nodeType: doc.toNodeType
854
+ }
855
+ );
856
+ }
857
+ return ctx.db.insert("epistemicEdges", doc);
858
+ }
763
859
 
764
860
  // src/epistemicEvidenceMutations.ts
765
861
  function assertSignedImpactScore(value, context) {
@@ -781,17 +877,17 @@ function normalizeEvidenceRelation(relation, weight, context) {
781
877
  return weight < 0 ? "contradicts" : "supports";
782
878
  }
783
879
  async function createEvidenceBeliefEdge(ctx, args) {
784
- const edgeGlobalId = crypto.randomUUID();
880
+ const edgeGlobalId = generateGlobalId();
785
881
  const confidence = Math.abs(args.weight);
786
882
  const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
787
883
  "by_from_to",
788
- (q) => q.eq("fromNodeId", args.evidenceNodeId).eq("toNodeId", args.beliefNodeId)
884
+ (q) => q.eq("fromNodeId", args.evidenceGlobalId).eq("toNodeId", args.beliefGlobalId)
789
885
  ).collect();
790
886
  const existing = existingEdges.find((edge) => edge.edgeType === "informs");
791
887
  const edgeDoc = {
792
888
  globalId: edgeGlobalId,
793
- fromNodeId: args.evidenceNodeId,
794
- toNodeId: args.beliefNodeId,
889
+ fromNodeId: args.evidenceGlobalId,
890
+ toNodeId: args.beliefGlobalId,
795
891
  sourceGlobalId: args.evidenceGlobalId,
796
892
  targetGlobalId: args.beliefGlobalId,
797
893
  edgeType: "informs",
@@ -823,7 +919,7 @@ async function createEvidenceBeliefEdge(ctx, args) {
823
919
  createdAt: existing.createdAt ?? edgeDoc.createdAt
824
920
  });
825
921
  } else {
826
- await ctx.db.insert("epistemicEdges", edgeDoc);
922
+ await insertEpistemicEdge(ctx, edgeDoc);
827
923
  }
828
924
  await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
829
925
  globalId: existing?.globalId ?? edgeGlobalId,
@@ -862,10 +958,23 @@ var create = mutation({
862
958
  sourceQuestionId: v.optional(v.string()),
863
959
  userId: v.string(),
864
960
  rationale: v.string(),
865
- // Classification fields (from AI tools)
961
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
962
+ sourceRef: v.optional(v.string()),
963
+ sourceQuality: v.optional(
964
+ v.union(
965
+ v.literal("primary"),
966
+ v.literal("analyzed"),
967
+ v.literal("secondary"),
968
+ v.literal("tertiary"),
969
+ v.literal("unknown")
970
+ )
971
+ ),
866
972
  methodology: v.optional(v.string()),
867
973
  informationAsymmetry: v.optional(v.string()),
868
974
  sourceDescription: v.optional(v.string()),
975
+ // signedImpact is derived from weight; accepted as an explicit override for
976
+ // callers that already have the signed value (kernel parity).
977
+ signedImpact: v.optional(v.number()),
869
978
  metadata: v.optional(v.any()),
870
979
  // Required belief impact link.
871
980
  linkedBeliefNodeId: v.id("epistemicNodes"),
@@ -895,6 +1004,7 @@ var create = mutation({
895
1004
  const kind = normalizeKind(args.kind);
896
1005
  const sourceType = normalizeSourceType(args.sourceType);
897
1006
  const weight = assertSignedImpactScore(args.weight, "Evidence creation");
1007
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Evidence creation signedImpact") : weight;
898
1008
  const evidenceRelation = normalizeEvidenceRelation(
899
1009
  args.evidenceRelation,
900
1010
  weight,
@@ -905,7 +1015,7 @@ var create = mutation({
905
1015
  throw new Error("Evidence creation requires a linked belief node");
906
1016
  }
907
1017
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
908
- const nodeId = await ctx.db.insert("epistemicNodes", {
1018
+ const nodeId = await insertEpistemicNode(ctx, {
909
1019
  globalId,
910
1020
  topicId: scope.topicId,
911
1021
  projectId: scope.projectId,
@@ -920,6 +1030,15 @@ var create = mutation({
920
1030
  status: "active",
921
1031
  epistemicLayer: "L2",
922
1032
  sourceType,
1033
+ // RC.1 taxonomy fields — top-level projection
1034
+ evidenceRelation,
1035
+ signedImpact,
1036
+ targetBeliefId: String(args.linkedBeliefNodeId),
1037
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1038
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1039
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1040
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1041
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
923
1042
  createdAt: now,
924
1043
  updatedAt: now,
925
1044
  createdBy: args.userId,
@@ -955,7 +1074,6 @@ var create = mutation({
955
1074
  text: args.text
956
1075
  });
957
1076
  await createEvidenceBeliefEdge(ctx, {
958
- evidenceNodeId: nodeId,
959
1077
  evidenceGlobalId: globalId,
960
1078
  beliefNodeId: args.linkedBeliefNodeId,
961
1079
  beliefGlobalId: linkedBeliefNode.globalId,
@@ -1025,7 +1143,22 @@ var createAndLink = mutation({
1025
1143
  beliefNodeId: v.id("epistemicNodes"),
1026
1144
  relation: v.union(v.literal("supports"), v.literal("contradicts")),
1027
1145
  weight: v.number(),
1028
- confidence: v.optional(v.number())
1146
+ confidence: v.optional(v.number()),
1147
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
1148
+ sourceRef: v.optional(v.string()),
1149
+ sourceQuality: v.optional(
1150
+ v.union(
1151
+ v.literal("primary"),
1152
+ v.literal("analyzed"),
1153
+ v.literal("secondary"),
1154
+ v.literal("tertiary"),
1155
+ v.literal("unknown")
1156
+ )
1157
+ ),
1158
+ methodology: v.optional(v.string()),
1159
+ informationAsymmetry: v.optional(v.string()),
1160
+ sourceDescription: v.optional(v.string()),
1161
+ signedImpact: v.optional(v.number())
1029
1162
  },
1030
1163
  returns: permissiveReturn,
1031
1164
  handler: async (ctx, args) => {
@@ -1040,6 +1173,7 @@ var createAndLink = mutation({
1040
1173
  const kind = normalizeKind(args.kind);
1041
1174
  const sourceType = normalizeSourceType(args.sourceType);
1042
1175
  const weight = assertSignedImpactScore(args.weight, "Evidence createAndLink");
1176
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Evidence createAndLink signedImpact") : weight;
1043
1177
  const relation = normalizeEvidenceRelation(
1044
1178
  args.relation,
1045
1179
  weight,
@@ -1050,7 +1184,7 @@ var createAndLink = mutation({
1050
1184
  if (!beliefNode || beliefNode.nodeType !== "belief") {
1051
1185
  throw new Error("Belief node not found for edge creation");
1052
1186
  }
1053
- const nodeId = await ctx.db.insert("epistemicNodes", {
1187
+ const nodeId = await insertEpistemicNode(ctx, {
1054
1188
  globalId,
1055
1189
  topicId: scope.topicId,
1056
1190
  projectId: scope.projectId,
@@ -1062,6 +1196,15 @@ var createAndLink = mutation({
1062
1196
  status: "active",
1063
1197
  epistemicLayer: "L2",
1064
1198
  sourceType,
1199
+ // RC.1 taxonomy fields — top-level projection
1200
+ evidenceRelation: relation,
1201
+ signedImpact,
1202
+ targetBeliefId: String(args.beliefNodeId),
1203
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1204
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1205
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1206
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1207
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
1065
1208
  createdAt: now,
1066
1209
  updatedAt: now,
1067
1210
  createdBy: args.userId,
@@ -1080,7 +1223,6 @@ var createAndLink = mutation({
1080
1223
  operation: "upsert"
1081
1224
  });
1082
1225
  const edgeGlobalId = await createEvidenceBeliefEdge(ctx, {
1083
- evidenceNodeId: nodeId,
1084
1226
  evidenceGlobalId: globalId,
1085
1227
  beliefNodeId: args.beliefNodeId,
1086
1228
  beliefGlobalId: beliefNode.globalId,
@@ -1153,6 +1295,21 @@ var internalCreate = internalMutation({
1153
1295
  evidenceRelation: v.optional(v.string()),
1154
1296
  weight: v.number(),
1155
1297
  confidence: v.optional(v.number()),
1298
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
1299
+ sourceRef: v.optional(v.string()),
1300
+ sourceQuality: v.optional(
1301
+ v.union(
1302
+ v.literal("primary"),
1303
+ v.literal("analyzed"),
1304
+ v.literal("secondary"),
1305
+ v.literal("tertiary"),
1306
+ v.literal("unknown")
1307
+ )
1308
+ ),
1309
+ methodology: v.optional(v.string()),
1310
+ informationAsymmetry: v.optional(v.string()),
1311
+ sourceDescription: v.optional(v.string()),
1312
+ signedImpact: v.optional(v.number()),
1156
1313
  metadata: v.optional(v.any()),
1157
1314
  runtimeToolName: v.optional(v.string()),
1158
1315
  runtimePackKey: v.optional(v.string()),
@@ -1187,6 +1344,7 @@ var internalCreate = internalMutation({
1187
1344
  const kind = normalizeKind(args.kind);
1188
1345
  const sourceType = normalizeSourceType(args.sourceType);
1189
1346
  const weight = assertSignedImpactScore(args.weight, "Internal evidence creation");
1347
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Internal evidence creation signedImpact") : weight;
1190
1348
  const evidenceRelation = normalizeEvidenceRelation(
1191
1349
  args.evidenceRelation,
1192
1350
  weight,
@@ -1197,7 +1355,7 @@ var internalCreate = internalMutation({
1197
1355
  throw new Error("Internal evidence creation requires a linked belief node");
1198
1356
  }
1199
1357
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
1200
- const nodeId = await ctx.db.insert("epistemicNodes", {
1358
+ const nodeId = await insertEpistemicNode(ctx, {
1201
1359
  globalId,
1202
1360
  topicId: scope.topicId,
1203
1361
  projectId: scope.projectId,
@@ -1212,6 +1370,15 @@ var internalCreate = internalMutation({
1212
1370
  status: "active",
1213
1371
  epistemicLayer: "L2",
1214
1372
  sourceType,
1373
+ // RC.1 taxonomy fields — top-level projection
1374
+ evidenceRelation,
1375
+ signedImpact,
1376
+ targetBeliefId: String(args.linkedBeliefNodeId),
1377
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1378
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1379
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1380
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1381
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
1215
1382
  createdAt: now,
1216
1383
  updatedAt: now,
1217
1384
  createdBy: args.userId,
@@ -1257,7 +1424,6 @@ var internalCreate = internalMutation({
1257
1424
  operation: "upsert"
1258
1425
  });
1259
1426
  await createEvidenceBeliefEdge(ctx, {
1260
- evidenceNodeId: nodeId,
1261
1427
  evidenceGlobalId: globalId,
1262
1428
  beliefNodeId: args.linkedBeliefNodeId,
1263
1429
  beliefGlobalId: linkedBeliefNode.globalId,