@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
@@ -3,8 +3,9 @@ import { componentsGeneric, anyApi, mutationGeneric, internalMutationGeneric, qu
3
3
  import { v } from 'convex/values';
4
4
  import { requireProjectAccess, checkProjectAccess, checkScopeAccess } from '@lucern/access-control/access';
5
5
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
6
- import { generateGlobalId } from '@lucern/contracts/ids';
6
+ import { generateGlobalId, assertUuidV7Identity, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint } from '@lucern/contracts/ids';
7
7
  import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
8
+ import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
8
9
  import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
9
10
 
10
11
  // src/epistemicEvidenceHelpers.ts
@@ -161,6 +162,9 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
161
162
  type: mapProjectType(topic, metadata),
162
163
  description: readNonEmptyString(topic.description),
163
164
  ownerId: readNonEmptyString(metadata.ownerId) || readNonEmptyString(topic.createdBy) || "system",
165
+ // FR.7 creator-grant: surface the principal-shaped owner field (column-first,
166
+ // metadata fallback for legacy rows that recorded it in metadata).
167
+ ownerPrincipalId: readNonEmptyString(topic.ownerPrincipalId) || readNonEmptyString(metadata.ownerPrincipalId),
164
168
  sharedWith: readStringArray(metadata.sharedWith),
165
169
  visibility,
166
170
  tenantId: readNonEmptyString(topic.tenantId) || readNonEmptyString(metadata.tenantId),
@@ -355,6 +359,35 @@ function resolveGraphPrimitivesAppResolvers(_ctx) {
355
359
  };
356
360
  }
357
361
  var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
362
+ async function resolveTopicNodeScopeOrNull(ctx, ref) {
363
+ if (!ctx?.db || typeof ctx.db.query !== "function") {
364
+ return null;
365
+ }
366
+ let node = null;
367
+ try {
368
+ const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
369
+ if (byGlobalId && byGlobalId.nodeType === "topic") {
370
+ node = byGlobalId;
371
+ }
372
+ } catch (error) {
373
+ debugGraphPrimitiveFallback(
374
+ "[topicScope] topic-node scope lookup by globalId failed",
375
+ { error, ref }
376
+ );
377
+ }
378
+ if (!node) {
379
+ return null;
380
+ }
381
+ const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
382
+ if (!scopeKey) {
383
+ return null;
384
+ }
385
+ return {
386
+ topicId: scopeKey,
387
+ projectId: asMappedProjectId(node),
388
+ source: "topic_node"
389
+ };
390
+ }
358
391
  function asMappedProjectId(topic) {
359
392
  if (!topic) {
360
393
  return;
@@ -495,6 +528,13 @@ async function resolveTopicProjectScope(ctx, args) {
495
528
  ) ?? null;
496
529
  }
497
530
  if (!topic) {
531
+ const nodeScope = await resolveTopicNodeScopeOrNull(
532
+ ctx,
533
+ String(args.topicId)
534
+ );
535
+ if (nodeScope) {
536
+ return nodeScope;
537
+ }
498
538
  throw new Error(`Topic not found: ${String(args.topicId)}`);
499
539
  }
500
540
  const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
@@ -565,6 +605,16 @@ async function resolveTopicProjectScope(ctx, args) {
565
605
  source: "project_mapped_topic"
566
606
  };
567
607
  }
608
+ const nodeScope = await resolveTopicNodeScopeOrNull(
609
+ ctx,
610
+ String(args.projectId)
611
+ );
612
+ if (nodeScope) {
613
+ return {
614
+ ...nodeScope,
615
+ projectId: nodeScope.projectId ?? String(args.projectId)
616
+ };
617
+ }
568
618
  throw new Error(
569
619
  `Legacy project scope ${String(args.projectId)} has no mapped topic.`
570
620
  );
@@ -894,6 +944,52 @@ function assertTenantPackWorkspaceMutationAllowed(args) {
894
944
  }
895
945
  });
896
946
  }
947
+ async function insertEpistemicNode(ctx, doc) {
948
+ assertUuidV7Identity("epistemicNodes", doc.globalId);
949
+ return ctx.db.insert("epistemicNodes", doc);
950
+ }
951
+ async function assertExistingNodeEndpoint(ctx, endpointRole, endpoint) {
952
+ assertUuidShapedEdgeEndpoint(endpointRole, endpoint);
953
+ const node = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", endpoint)).first();
954
+ if (!node) {
955
+ throw new Error(
956
+ `edge_endpoint_not_canonical: epistemicEdges insert requires ${endpointRole} to be the globalId of an existing epistemicNodes row, received ${endpoint} (no node with that globalId)`
957
+ );
958
+ }
959
+ }
960
+ async function insertEpistemicEdge(ctx, doc) {
961
+ assertUuidV7Identity("epistemicEdges", doc.globalId);
962
+ assertStorageEdgeVocabulary(doc.edgeType);
963
+ if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
964
+ throw new Error(
965
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
966
+ );
967
+ }
968
+ if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
969
+ throw new Error(
970
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
971
+ );
972
+ }
973
+ await assertExistingNodeEndpoint(ctx, "fromNodeId", doc.fromNodeId);
974
+ await assertExistingNodeEndpoint(ctx, "toNodeId", doc.toNodeId);
975
+ if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
976
+ assertEdgePolicyAllowed(
977
+ edgePolicyManifest,
978
+ doc.edgeType,
979
+ {
980
+ kind: "epistemic_node",
981
+ nodeId: doc.fromNodeId,
982
+ nodeType: doc.fromNodeType
983
+ },
984
+ {
985
+ kind: "epistemic_node",
986
+ nodeId: doc.toNodeId,
987
+ nodeType: doc.toNodeType
988
+ }
989
+ );
990
+ }
991
+ return ctx.db.insert("epistemicEdges", doc);
992
+ }
897
993
 
898
994
  // src/epistemicEvidenceMutations.ts
899
995
  function assertSignedImpactScore(value, context) {
@@ -915,17 +1011,17 @@ function normalizeEvidenceRelation(relation, weight, context) {
915
1011
  return weight < 0 ? "contradicts" : "supports";
916
1012
  }
917
1013
  async function createEvidenceBeliefEdge(ctx, args) {
918
- const edgeGlobalId = crypto.randomUUID();
1014
+ const edgeGlobalId = generateGlobalId();
919
1015
  const confidence = Math.abs(args.weight);
920
1016
  const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
921
1017
  "by_from_to",
922
- (q) => q.eq("fromNodeId", args.evidenceNodeId).eq("toNodeId", args.beliefNodeId)
1018
+ (q) => q.eq("fromNodeId", args.evidenceGlobalId).eq("toNodeId", args.beliefGlobalId)
923
1019
  ).collect();
924
1020
  const existing = existingEdges.find((edge) => edge.edgeType === "informs");
925
1021
  const edgeDoc = {
926
1022
  globalId: edgeGlobalId,
927
- fromNodeId: args.evidenceNodeId,
928
- toNodeId: args.beliefNodeId,
1023
+ fromNodeId: args.evidenceGlobalId,
1024
+ toNodeId: args.beliefGlobalId,
929
1025
  sourceGlobalId: args.evidenceGlobalId,
930
1026
  targetGlobalId: args.beliefGlobalId,
931
1027
  edgeType: "informs",
@@ -957,7 +1053,7 @@ async function createEvidenceBeliefEdge(ctx, args) {
957
1053
  createdAt: existing.createdAt ?? edgeDoc.createdAt
958
1054
  });
959
1055
  } else {
960
- await ctx.db.insert("epistemicEdges", edgeDoc);
1056
+ await insertEpistemicEdge(ctx, edgeDoc);
961
1057
  }
962
1058
  await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
963
1059
  globalId: existing?.globalId ?? edgeGlobalId,
@@ -996,10 +1092,23 @@ var create = mutation({
996
1092
  sourceQuestionId: v.optional(v.string()),
997
1093
  userId: v.string(),
998
1094
  rationale: v.string(),
999
- // Classification fields (from AI tools)
1095
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
1096
+ sourceRef: v.optional(v.string()),
1097
+ sourceQuality: v.optional(
1098
+ v.union(
1099
+ v.literal("primary"),
1100
+ v.literal("analyzed"),
1101
+ v.literal("secondary"),
1102
+ v.literal("tertiary"),
1103
+ v.literal("unknown")
1104
+ )
1105
+ ),
1000
1106
  methodology: v.optional(v.string()),
1001
1107
  informationAsymmetry: v.optional(v.string()),
1002
1108
  sourceDescription: v.optional(v.string()),
1109
+ // signedImpact is derived from weight; accepted as an explicit override for
1110
+ // callers that already have the signed value (kernel parity).
1111
+ signedImpact: v.optional(v.number()),
1003
1112
  metadata: v.optional(v.any()),
1004
1113
  // Required belief impact link.
1005
1114
  linkedBeliefNodeId: v.id("epistemicNodes"),
@@ -1029,6 +1138,7 @@ var create = mutation({
1029
1138
  const kind = normalizeKind(args.kind);
1030
1139
  const sourceType = normalizeSourceType(args.sourceType);
1031
1140
  const weight = assertSignedImpactScore(args.weight, "Evidence creation");
1141
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Evidence creation signedImpact") : weight;
1032
1142
  const evidenceRelation = normalizeEvidenceRelation(
1033
1143
  args.evidenceRelation,
1034
1144
  weight,
@@ -1039,7 +1149,7 @@ var create = mutation({
1039
1149
  throw new Error("Evidence creation requires a linked belief node");
1040
1150
  }
1041
1151
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
1042
- const nodeId = await ctx.db.insert("epistemicNodes", {
1152
+ const nodeId = await insertEpistemicNode(ctx, {
1043
1153
  globalId,
1044
1154
  topicId: scope.topicId,
1045
1155
  projectId: scope.projectId,
@@ -1054,6 +1164,15 @@ var create = mutation({
1054
1164
  status: "active",
1055
1165
  epistemicLayer: "L2",
1056
1166
  sourceType,
1167
+ // RC.1 taxonomy fields — top-level projection
1168
+ evidenceRelation,
1169
+ signedImpact,
1170
+ targetBeliefId: String(args.linkedBeliefNodeId),
1171
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1172
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1173
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1174
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1175
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
1057
1176
  createdAt: now,
1058
1177
  updatedAt: now,
1059
1178
  createdBy: args.userId,
@@ -1089,7 +1208,6 @@ var create = mutation({
1089
1208
  text: args.text
1090
1209
  });
1091
1210
  await createEvidenceBeliefEdge(ctx, {
1092
- evidenceNodeId: nodeId,
1093
1211
  evidenceGlobalId: globalId,
1094
1212
  beliefNodeId: args.linkedBeliefNodeId,
1095
1213
  beliefGlobalId: linkedBeliefNode.globalId,
@@ -1159,7 +1277,22 @@ var createAndLink = mutation({
1159
1277
  beliefNodeId: v.id("epistemicNodes"),
1160
1278
  relation: v.union(v.literal("supports"), v.literal("contradicts")),
1161
1279
  weight: v.number(),
1162
- confidence: v.optional(v.number())
1280
+ confidence: v.optional(v.number()),
1281
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
1282
+ sourceRef: v.optional(v.string()),
1283
+ sourceQuality: v.optional(
1284
+ v.union(
1285
+ v.literal("primary"),
1286
+ v.literal("analyzed"),
1287
+ v.literal("secondary"),
1288
+ v.literal("tertiary"),
1289
+ v.literal("unknown")
1290
+ )
1291
+ ),
1292
+ methodology: v.optional(v.string()),
1293
+ informationAsymmetry: v.optional(v.string()),
1294
+ sourceDescription: v.optional(v.string()),
1295
+ signedImpact: v.optional(v.number())
1163
1296
  },
1164
1297
  returns: permissiveReturn,
1165
1298
  handler: async (ctx, args) => {
@@ -1174,6 +1307,7 @@ var createAndLink = mutation({
1174
1307
  const kind = normalizeKind(args.kind);
1175
1308
  const sourceType = normalizeSourceType(args.sourceType);
1176
1309
  const weight = assertSignedImpactScore(args.weight, "Evidence createAndLink");
1310
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Evidence createAndLink signedImpact") : weight;
1177
1311
  const relation = normalizeEvidenceRelation(
1178
1312
  args.relation,
1179
1313
  weight,
@@ -1184,7 +1318,7 @@ var createAndLink = mutation({
1184
1318
  if (!beliefNode || beliefNode.nodeType !== "belief") {
1185
1319
  throw new Error("Belief node not found for edge creation");
1186
1320
  }
1187
- const nodeId = await ctx.db.insert("epistemicNodes", {
1321
+ const nodeId = await insertEpistemicNode(ctx, {
1188
1322
  globalId,
1189
1323
  topicId: scope.topicId,
1190
1324
  projectId: scope.projectId,
@@ -1196,6 +1330,15 @@ var createAndLink = mutation({
1196
1330
  status: "active",
1197
1331
  epistemicLayer: "L2",
1198
1332
  sourceType,
1333
+ // RC.1 taxonomy fields — top-level projection
1334
+ evidenceRelation: relation,
1335
+ signedImpact,
1336
+ targetBeliefId: String(args.beliefNodeId),
1337
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1338
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1339
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1340
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1341
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
1199
1342
  createdAt: now,
1200
1343
  updatedAt: now,
1201
1344
  createdBy: args.userId,
@@ -1214,7 +1357,6 @@ var createAndLink = mutation({
1214
1357
  operation: "upsert"
1215
1358
  });
1216
1359
  const edgeGlobalId = await createEvidenceBeliefEdge(ctx, {
1217
- evidenceNodeId: nodeId,
1218
1360
  evidenceGlobalId: globalId,
1219
1361
  beliefNodeId: args.beliefNodeId,
1220
1362
  beliefGlobalId: beliefNode.globalId,
@@ -1287,6 +1429,21 @@ var internalCreate = internalMutation({
1287
1429
  evidenceRelation: v.optional(v.string()),
1288
1430
  weight: v.number(),
1289
1431
  confidence: v.optional(v.number()),
1432
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
1433
+ sourceRef: v.optional(v.string()),
1434
+ sourceQuality: v.optional(
1435
+ v.union(
1436
+ v.literal("primary"),
1437
+ v.literal("analyzed"),
1438
+ v.literal("secondary"),
1439
+ v.literal("tertiary"),
1440
+ v.literal("unknown")
1441
+ )
1442
+ ),
1443
+ methodology: v.optional(v.string()),
1444
+ informationAsymmetry: v.optional(v.string()),
1445
+ sourceDescription: v.optional(v.string()),
1446
+ signedImpact: v.optional(v.number()),
1290
1447
  metadata: v.optional(v.any()),
1291
1448
  runtimeToolName: v.optional(v.string()),
1292
1449
  runtimePackKey: v.optional(v.string()),
@@ -1321,6 +1478,7 @@ var internalCreate = internalMutation({
1321
1478
  const kind = normalizeKind(args.kind);
1322
1479
  const sourceType = normalizeSourceType(args.sourceType);
1323
1480
  const weight = assertSignedImpactScore(args.weight, "Internal evidence creation");
1481
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore(args.signedImpact, "Internal evidence creation signedImpact") : weight;
1324
1482
  const evidenceRelation = normalizeEvidenceRelation(
1325
1483
  args.evidenceRelation,
1326
1484
  weight,
@@ -1331,7 +1489,7 @@ var internalCreate = internalMutation({
1331
1489
  throw new Error("Internal evidence creation requires a linked belief node");
1332
1490
  }
1333
1491
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
1334
- const nodeId = await ctx.db.insert("epistemicNodes", {
1492
+ const nodeId = await insertEpistemicNode(ctx, {
1335
1493
  globalId,
1336
1494
  topicId: scope.topicId,
1337
1495
  projectId: scope.projectId,
@@ -1346,6 +1504,15 @@ var internalCreate = internalMutation({
1346
1504
  status: "active",
1347
1505
  epistemicLayer: "L2",
1348
1506
  sourceType,
1507
+ // RC.1 taxonomy fields — top-level projection
1508
+ evidenceRelation,
1509
+ signedImpact,
1510
+ targetBeliefId: String(args.linkedBeliefNodeId),
1511
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
1512
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
1513
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
1514
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
1515
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
1349
1516
  createdAt: now,
1350
1517
  updatedAt: now,
1351
1518
  createdBy: args.userId,
@@ -1391,7 +1558,6 @@ var internalCreate = internalMutation({
1391
1558
  operation: "upsert"
1392
1559
  });
1393
1560
  await createEvidenceBeliefEdge(ctx, {
1394
- evidenceNodeId: nodeId,
1395
1561
  evidenceGlobalId: globalId,
1396
1562
  beliefNodeId: args.linkedBeliefNodeId,
1397
1563
  beliefGlobalId: linkedBeliefNode.globalId,