@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.
Files changed (127) hide show
  1. package/dist/beliefDecay.js +46 -0
  2. package/dist/beliefDecay.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.js +87 -5
  4. package/dist/beliefEvidenceLinks.js.map +1 -1
  5. package/dist/beliefEvidenceLinks.operational.js +41 -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/entityLifecycle.js +90 -5
  14. package/dist/entityLifecycle.js.map +1 -1
  15. package/dist/epistemicAnswers.js +64 -11
  16. package/dist/epistemicAnswers.js.map +1 -1
  17. package/dist/epistemicBeliefs.admin.js +46 -0
  18. package/dist/epistemicBeliefs.admin.js.map +1 -1
  19. package/dist/epistemicBeliefs.backfills.js +46 -0
  20. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  21. package/dist/epistemicBeliefs.confidence.d.ts +1 -1
  22. package/dist/epistemicBeliefs.confidence.js +53 -6
  23. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  24. package/dist/epistemicBeliefs.core.js +91 -11
  25. package/dist/epistemicBeliefs.core.js.map +1 -1
  26. package/dist/epistemicBeliefs.d.ts +1 -1
  27. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  28. package/dist/epistemicBeliefs.helpers.d.ts +2 -2
  29. package/dist/epistemicBeliefs.helpers.js +46 -0
  30. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  31. package/dist/epistemicBeliefs.internal.js +90 -10
  32. package/dist/epistemicBeliefs.internal.js.map +1 -1
  33. package/dist/epistemicBeliefs.js +103 -22
  34. package/dist/epistemicBeliefs.js.map +1 -1
  35. package/dist/epistemicBeliefs.lifecycle.js +53 -6
  36. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  37. package/dist/epistemicBeliefs.links.js +85 -4
  38. package/dist/epistemicBeliefs.links.js.map +1 -1
  39. package/dist/epistemicBeliefs.topicAnchor.js +39 -8
  40. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  41. package/dist/epistemicContracts.evaluators.js +53 -6
  42. package/dist/epistemicContracts.evaluators.js.map +1 -1
  43. package/dist/epistemicContracts.handlers.js +54 -10
  44. package/dist/epistemicContracts.handlers.js.map +1 -1
  45. package/dist/epistemicContracts.js +54 -10
  46. package/dist/epistemicContracts.js.map +1 -1
  47. package/dist/epistemicEdges.d.ts +1 -1
  48. package/dist/epistemicEdges.handlers.js +48 -3
  49. package/dist/epistemicEdges.handlers.js.map +1 -1
  50. package/dist/epistemicEdges.helpers.d.ts +3 -3
  51. package/dist/epistemicEdges.js +162 -4
  52. package/dist/epistemicEdges.js.map +1 -1
  53. package/dist/epistemicEdges.mutations.js +112 -1
  54. package/dist/epistemicEdges.mutations.js.map +1 -1
  55. package/dist/epistemicEdges.queries.js +46 -0
  56. package/dist/epistemicEdges.queries.js.map +1 -1
  57. package/dist/epistemicEdges.types.d.ts +1 -1
  58. package/dist/epistemicEvidence.d.ts +1 -1
  59. package/dist/epistemicEvidence.js +168 -14
  60. package/dist/epistemicEvidence.js.map +1 -1
  61. package/dist/epistemicEvidenceHelpers.d.ts +1 -1
  62. package/dist/epistemicEvidenceHelpers.js +46 -0
  63. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  64. package/dist/epistemicEvidenceMutations.js +168 -14
  65. package/dist/epistemicEvidenceMutations.js.map +1 -1
  66. package/dist/epistemicEvidenceQueries.js +46 -0
  67. package/dist/epistemicEvidenceQueries.js.map +1 -1
  68. package/dist/epistemicHelpers.js +11 -6
  69. package/dist/epistemicHelpers.js.map +1 -1
  70. package/dist/epistemicInsert.d.ts +8 -0
  71. package/dist/epistemicInsert.js +45 -0
  72. package/dist/epistemicInsert.js.map +1 -0
  73. package/dist/epistemicNodeCreation.js +11 -6
  74. package/dist/epistemicNodeCreation.js.map +1 -1
  75. package/dist/epistemicNodes.helpers.d.ts +1 -1
  76. package/dist/epistemicNodes.internal.js +53 -1
  77. package/dist/epistemicNodes.internal.js.map +1 -1
  78. package/dist/epistemicNodes.js +56 -4
  79. package/dist/epistemicNodes.js.map +1 -1
  80. package/dist/epistemicNodes.mutations.js +55 -3
  81. package/dist/epistemicNodes.mutations.js.map +1 -1
  82. package/dist/epistemicNodes.queries.js +46 -0
  83. package/dist/epistemicNodes.queries.js.map +1 -1
  84. package/dist/epistemicNodes.validators.d.ts +1 -1
  85. package/dist/epistemicQuestions.conviction.js +46 -0
  86. package/dist/epistemicQuestions.conviction.js.map +1 -1
  87. package/dist/epistemicQuestions.create.js +58 -7
  88. package/dist/epistemicQuestions.create.js.map +1 -1
  89. package/dist/epistemicQuestions.d.ts +1 -1
  90. package/dist/epistemicQuestions.evidence.js +53 -2
  91. package/dist/epistemicQuestions.evidence.js.map +1 -1
  92. package/dist/epistemicQuestions.helpers.d.ts +1 -1
  93. package/dist/epistemicQuestions.helpers.js +46 -0
  94. package/dist/epistemicQuestions.helpers.js.map +1 -1
  95. package/dist/epistemicQuestions.js +60 -9
  96. package/dist/epistemicQuestions.js.map +1 -1
  97. package/dist/epistemicQuestions.lifecycle.js +46 -0
  98. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  99. package/dist/epistemicQuestions.queries.js +46 -0
  100. package/dist/epistemicQuestions.queries.js.map +1 -1
  101. package/dist/epistemicQuestions.sprint.js +46 -0
  102. package/dist/epistemicQuestions.sprint.js.map +1 -1
  103. package/dist/epistemicQuestions.tail.js +53 -2
  104. package/dist/epistemicQuestions.tail.js.map +1 -1
  105. package/dist/epistemicSources.js +53 -2
  106. package/dist/epistemicSources.js.map +1 -1
  107. package/dist/helpers.js +66 -1
  108. package/dist/helpers.js.map +1 -1
  109. package/dist/index.d.ts +1 -1
  110. package/dist/index.js +304 -76
  111. package/dist/index.js.map +1 -1
  112. package/dist/proof-attestation.json +1 -1
  113. package/dist/questionEvidenceLinks.js +46 -0
  114. package/dist/questionEvidenceLinks.js.map +1 -1
  115. package/dist/scopeResolverCompat.d.ts +1 -1
  116. package/dist/scopeResolverCompat.js +46 -0
  117. package/dist/scopeResolverCompat.js.map +1 -1
  118. package/dist/{topicScope-By_zp4tt.d.ts → topicScope-7zhyeGl7.d.ts} +1 -1
  119. package/dist/topicScope.d.ts +1 -1
  120. package/dist/topicScope.js +46 -0
  121. package/dist/topicScope.js.map +1 -1
  122. package/dist/workflowBridge.js +46 -0
  123. package/dist/workflowBridge.js.map +1 -1
  124. package/dist/workspaceIsolation.d.ts +1 -1
  125. package/dist/workspaceIsolation.js +46 -0
  126. package/dist/workspaceIsolation.js.map +1 -1
  127. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -7,7 +7,8 @@ import { componentsGeneric, anyApi, internalMutationGeneric, mutationGeneric, qu
7
7
  import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
8
8
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
9
9
  import { assertSchemaEnumValue } from '@lucern/contracts/schema-helpers/enumValidation';
10
- import { generateGlobalId, generateUuidV7, isUuidV7 } from '@lucern/contracts/ids';
10
+ import { generateGlobalId, assertUuidV7Identity, generateUuidV7, assertStorageEdgeVocabulary, assertCanonicalEdgeEndpoint, isUuidV7 } from '@lucern/contracts/ids';
11
+ import { assertEdgePolicyAllowed, edgePolicyManifest } from '@lucern/contracts';
11
12
  import { listAudienceRegistryRows } from '@lucern/access-control/audienceRegistry';
12
13
  import { scoreEntityTypeMatch, scoreEntityConnection, rankEntityTypeMatches, rankEntityConnections } from '@lucern/contracts/v1/ontologies/v1';
13
14
  import { wordTokenize, wordOverlapScore, tokenizeSearchText, tokenOverlapScore, stemToken, scoreLexicalSignals, scoreLexicalSignal, rerankLexicalWindow, rankWindowScore, prepareLexicalQuery, jaccardSimilarity, bigramTokenize } from '@lucern/contracts/text-matching.contract';
@@ -642,7 +643,72 @@ var EDGE_LAYER_RULES = {
642
643
  from: ["ontological"],
643
644
  to: ["L3"],
644
645
  description: "Deal -> Theme"
645
- }
646
+ },
647
+ // C2-RR.4 — storage migration alias + the remaining 55 reachable edge types.
648
+ // Mirrors the kernel rule table
649
+ // (packages/reasoning-kernel/src/adapters/lib/edgeValidation.ts) so this
650
+ // graph-primitives write path admits the same public edge vocabulary. See the
651
+ // kernel file for the per-group rationale.
652
+ extracted_from: {
653
+ from: ["L2", "L3", "L4"],
654
+ to: ["L1", "L2", "L3"],
655
+ description: "Legacy storage migration alias for derived_from; public writes use derived_from"
656
+ },
657
+ qualifies: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief qualifies a Belief" },
658
+ contradicts: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief contradicts a Belief" },
659
+ reinforces: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief reinforces a Belief" },
660
+ corroborates: { from: ["L2", "L3"], to: ["L3"], description: "Independent evidence/belief corroborates a Belief" },
661
+ strengthened_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is strengthened by Evidence/Belief" },
662
+ weakened_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is weakened by Evidence/Belief" },
663
+ validated_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is validated by Evidence/Belief" },
664
+ falsified_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is falsified by Evidence/Belief" },
665
+ amplifies: { from: ["L3"], to: ["L3"], description: "Belief amplifies another Belief" },
666
+ precondition_for: { from: ["L3"], to: ["L3"], description: "Belief is a precondition for another Belief" },
667
+ prerequisite_for: { from: ["L3"], to: ["L3"], description: "Belief is a prerequisite for another Belief" },
668
+ required_for: { from: ["L3"], to: ["L3"], description: "Belief is required for another Belief" },
669
+ in_tension_with: { from: ["L3"], to: ["L3"], description: "Belief is in tension with another Belief" },
670
+ mutually_exclusive: { from: ["L3"], to: ["L3"], description: "Beliefs cannot both hold" },
671
+ exclusive_with: { from: ["L3"], to: ["L3"], description: "Belief is exclusive with another Belief" },
672
+ alternative_to: { from: ["L3"], to: ["L3"], description: "Belief is an alternative to another Belief" },
673
+ subsumes: { from: ["L3"], to: ["L3"], description: "Belief subsumes a narrower Belief" },
674
+ extends: { from: ["L3"], to: ["L3"], description: "Belief extends another Belief" },
675
+ refines: { from: ["L3"], to: ["L3"], description: "Belief refines another Belief" },
676
+ implements: { from: ["L3"], to: ["L3"], description: "Belief implements an abstract Belief" },
677
+ violates: { from: ["L3"], to: ["L3"], description: "Belief violates a constraint Belief" },
678
+ assumes: { from: ["L3"], to: ["L3"], description: "Belief assumes another Belief" },
679
+ would_predict: { from: ["L3"], to: ["L3"], description: "Belief would predict another Belief" },
680
+ analogous_to: { from: ["L3"], to: ["L3"], description: "Belief is analogous to another Belief" },
681
+ independent_of: { from: ["L3"], to: ["L3"], description: "Belief is independent of another Belief" },
682
+ correlates_with: { from: ["L3"], to: ["L3"], description: "Belief correlates with another Belief" },
683
+ co_changes_with: { from: ["L3"], to: ["L3"], description: "Belief co-changes with another Belief" },
684
+ counterfactual_of: { from: ["L3"], to: ["L3"], description: "Belief is a counterfactual of another Belief" },
685
+ parallel_to: { from: ["L3"], to: ["L3"], description: "Belief runs parallel to another Belief" },
686
+ cascade_from: { from: ["L3"], to: ["L3"], description: "Cascade from an upstream Belief" },
687
+ cascade_to: { from: ["L3"], to: ["L3"], description: "Cascade to a downstream Belief" },
688
+ collapses_if: { from: ["L3"], to: ["L3"], description: "Belief collapses if another fails" },
689
+ branches_from: { from: ["L3"], to: ["L3"], description: "Belief branches from an ancestor Belief" },
690
+ same_as: { from: ["L2", "L3", "ontological"], to: ["L2", "L3", "ontological"], description: "Two nodes are the same entity" },
691
+ answers: { from: ["L2", "L3"], to: ["L3"], description: "Answer/Belief answers a Question" },
692
+ partially_answers: { from: ["L2", "L3"], to: ["L3"], description: "Answer/Belief partially answers a Question" },
693
+ explores: { from: ["L3"], to: ["L3"], description: "Question explores a Belief/Theme" },
694
+ informed_by_theme: { from: ["L3"], to: ["L3"], description: "Belief is informed by a Theme" },
695
+ same_theme_as: { from: ["L3"], to: ["L3"], description: "Two Beliefs share a Theme" },
696
+ based_on: { from: ["L4"], to: ["L3"], description: "Decision is based on a Belief/Question" },
697
+ based_on_belief: { from: ["L4"], to: ["L3"], description: "Decision is based on a Belief" },
698
+ based_on_question: { from: ["L4"], to: ["L3"], description: "Decision is based on a Question" },
699
+ blocked_by_contradiction: { from: ["L4"], to: ["L3"], description: "Decision is blocked by a Contradiction" },
700
+ parent_of: { from: ["L3", "L4", "ontological", "organizational"], to: ["L2", "L3", "ontological", "organizational"], description: "A is the parent of B" },
701
+ child_of: { from: ["L2", "L3", "ontological", "organizational"], to: ["L3", "L4", "ontological", "organizational"], description: "A is the child of B" },
702
+ scoped_by: { from: ["L2", "L3"], to: ["L3", "organizational"], description: "Object is scoped by a Topic/Theme" },
703
+ cites: { from: ["L2", "L3"], to: ["L1", "L2"], description: "Evidence/Belief cites a Source/Excerpt" },
704
+ summarizes: { from: ["L2", "L3"], to: ["L1", "L2"], description: "Synthesis/Evidence summarizes a Source/Evidence" },
705
+ same_source_as: { from: ["L1", "L2"], to: ["L1", "L2"], description: "Two nodes derive from the same Source" },
706
+ migrating_from: { from: ["L2", "L3", "L4"], to: ["L1", "L2", "L3"], description: "Migration lineage: from an ancestor" },
707
+ migrating_to: { from: ["L1", "L2", "L3"], to: ["L2", "L3", "L4"], description: "Migration lineage: to a successor" },
708
+ about_entity: { from: ["L2", "L3"], to: ["ontological"], description: "Belief/Evidence is about an Entity" },
709
+ entity_referenced_in: { from: ["ontological"], to: ["L1", "L2"], description: "Entity is referenced in a Source/Evidence" },
710
+ related_to: { from: ["L2", "L3", "ontological", "organizational"], to: ["L2", "L3", "ontological", "organizational"], description: "Lateral adjacency; no confidence pressure" },
711
+ blocks: { from: ["L3", "L4"], to: ["L3", "L4"], description: "A blocks B (structural gate)" }
646
712
  };
647
713
  function validateEdgeLayers(edgeType, fromLayer, toLayer) {
648
714
  const rules = EDGE_LAYER_RULES[edgeType];
@@ -1237,6 +1303,35 @@ __export(topicScope_exports, {
1237
1303
  resolveTopicProjectScope: () => resolveTopicProjectScope
1238
1304
  });
1239
1305
  var LEGACY_SCOPE_FIELD2 = "graphScopeProjectId";
1306
+ async function resolveTopicNodeScopeOrNull(ctx, ref) {
1307
+ if (!ctx?.db || typeof ctx.db.query !== "function") {
1308
+ return null;
1309
+ }
1310
+ let node = null;
1311
+ try {
1312
+ const byGlobalId = await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", ref)).first();
1313
+ if (byGlobalId && byGlobalId.nodeType === "topic") {
1314
+ node = byGlobalId;
1315
+ }
1316
+ } catch (error) {
1317
+ debugGraphPrimitiveFallback(
1318
+ "[topicScope] topic-node scope lookup by globalId failed",
1319
+ { error, ref }
1320
+ );
1321
+ }
1322
+ if (!node) {
1323
+ return null;
1324
+ }
1325
+ const scopeKey = normalizeScopeValue(node.topicId) ?? normalizeScopeValue(node.globalId);
1326
+ if (!scopeKey) {
1327
+ return null;
1328
+ }
1329
+ return {
1330
+ topicId: scopeKey,
1331
+ projectId: asMappedProjectId(node),
1332
+ source: "topic_node"
1333
+ };
1334
+ }
1240
1335
  function asMappedProjectId(topic) {
1241
1336
  if (!topic) {
1242
1337
  return;
@@ -1385,6 +1480,13 @@ async function resolveTopicProjectScope(ctx, args) {
1385
1480
  ) ?? null;
1386
1481
  }
1387
1482
  if (!topic) {
1483
+ const nodeScope = await resolveTopicNodeScopeOrNull(
1484
+ ctx,
1485
+ String(args.topicId)
1486
+ );
1487
+ if (nodeScope) {
1488
+ return nodeScope;
1489
+ }
1388
1490
  throw new Error(`Topic not found: ${String(args.topicId)}`);
1389
1491
  }
1390
1492
  const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
@@ -1455,6 +1557,16 @@ async function resolveTopicProjectScope(ctx, args) {
1455
1557
  source: "project_mapped_topic"
1456
1558
  };
1457
1559
  }
1560
+ const nodeScope = await resolveTopicNodeScopeOrNull(
1561
+ ctx,
1562
+ String(args.projectId)
1563
+ );
1564
+ if (nodeScope) {
1565
+ return {
1566
+ ...nodeScope,
1567
+ projectId: nodeScope.projectId ?? String(args.projectId)
1568
+ };
1569
+ }
1458
1570
  throw new Error(
1459
1571
  `Legacy project scope ${String(args.projectId)} has no mapped topic.`
1460
1572
  );
@@ -2351,14 +2463,14 @@ async function applyBeliefConfidenceChange(ctx, args) {
2351
2463
  beliefConfidenceId
2352
2464
  };
2353
2465
  }
2354
- function propagationTriggerForEdge(edgeType, weight) {
2466
+ function propagationPressureLabel(edgeType, weight) {
2355
2467
  if (edgeType === "contradicts" || edgeType === "refutes") {
2356
- return "contradiction_detected";
2468
+ return "contradictory";
2357
2469
  }
2358
2470
  if ((edgeType === "supports" || edgeType === "informs") && weight < 0) {
2359
- return "contradiction_detected";
2471
+ return "contradictory";
2360
2472
  }
2361
- return "evidence_added";
2473
+ return "supportive";
2362
2474
  }
2363
2475
  var propagateConfidenceChange = internalMutation({
2364
2476
  args: {
@@ -2395,14 +2507,15 @@ var propagateConfidenceChange = internalMutation({
2395
2507
  getNode: async (nodeId) => await ctx.db.get(nodeId)
2396
2508
  });
2397
2509
  for (const dispatch of dispatches) {
2510
+ const pressureLabel = propagationPressureLabel(dispatch.edgeType, dispatch.weight);
2398
2511
  await applyBeliefConfidenceChange(ctx, {
2399
2512
  nodeId: dispatch.targetNodeId,
2400
2513
  belief: dispatch.opinion.b,
2401
2514
  disbelief: dispatch.opinion.d,
2402
2515
  uncertainty: dispatch.opinion.u,
2403
2516
  baseRate: dispatch.opinion.a,
2404
- trigger: propagationTriggerForEdge(dispatch.edgeType, dispatch.weight),
2405
- rationale: `SL propagation via ${dispatch.edgeType} edge: ${dispatch.rationale}`,
2517
+ trigger: "propagation",
2518
+ rationale: `SL propagation via ${dispatch.edgeType} edge (pressure: ${pressureLabel}): ${dispatch.rationale}`,
2406
2519
  authenticatedUserId: args.userId,
2407
2520
  slOperator: dispatch.operator
2408
2521
  });
@@ -2522,6 +2635,43 @@ __export(globalId_exports, {
2522
2635
  generateUuidV7: () => generateUuidV7,
2523
2636
  isUuidV7: () => isUuidV7
2524
2637
  });
2638
+ async function insertEpistemicNode(ctx, doc) {
2639
+ assertUuidV7Identity("epistemicNodes", doc.globalId);
2640
+ return ctx.db.insert("epistemicNodes", doc);
2641
+ }
2642
+ async function insertEpistemicEdge(ctx, doc) {
2643
+ assertUuidV7Identity("epistemicEdges", doc.globalId);
2644
+ assertStorageEdgeVocabulary(doc.edgeType);
2645
+ if (!doc.fromNodeId || typeof doc.fromNodeId !== "string") {
2646
+ throw new Error(
2647
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty fromNodeId"
2648
+ );
2649
+ }
2650
+ if (!doc.toNodeId || typeof doc.toNodeId !== "string") {
2651
+ throw new Error(
2652
+ "edge_endpoint_missing: epistemicEdges insert requires a non-empty toNodeId"
2653
+ );
2654
+ }
2655
+ assertCanonicalEdgeEndpoint("fromNodeId", doc.fromNodeId);
2656
+ assertCanonicalEdgeEndpoint("toNodeId", doc.toNodeId);
2657
+ if (doc.fromNodeType && doc.toNodeType && doc.edgeType !== "extracted_from") {
2658
+ assertEdgePolicyAllowed(
2659
+ edgePolicyManifest,
2660
+ doc.edgeType,
2661
+ {
2662
+ kind: "epistemic_node",
2663
+ nodeId: doc.fromNodeId,
2664
+ nodeType: doc.fromNodeType
2665
+ },
2666
+ {
2667
+ kind: "epistemic_node",
2668
+ nodeId: doc.toNodeId,
2669
+ nodeType: doc.toNodeType
2670
+ }
2671
+ );
2672
+ }
2673
+ return ctx.db.insert("epistemicEdges", doc);
2674
+ }
2525
2675
 
2526
2676
  // src/epistemicBeliefs.topicAnchor.ts
2527
2677
  function cleanString(value) {
@@ -2573,18 +2723,15 @@ async function createRequiredBeliefTopicEdge(ctx, args) {
2573
2723
  const now = Date.now();
2574
2724
  const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
2575
2725
  "by_from_to",
2576
- (q) => q.eq("fromNodeId", String(args.beliefNodeId)).eq(
2577
- "toNodeId",
2578
- String(args.topicNode._id)
2579
- )
2726
+ (q) => q.eq("fromNodeId", args.beliefGlobalId).eq("toNodeId", topicGlobalId)
2580
2727
  ).collect();
2581
2728
  const existing = existingEdges.find((edge) => edge.edgeType === "belongs_to");
2582
2729
  const edgeGlobalId = cleanString(existing?.globalId) ?? generateUuidV7();
2583
2730
  if (!existing) {
2584
- await ctx.db.insert("epistemicEdges", {
2731
+ await insertEpistemicEdge(ctx, {
2585
2732
  globalId: edgeGlobalId,
2586
- fromNodeId: String(args.beliefNodeId),
2587
- toNodeId: String(args.topicNode._id),
2733
+ fromNodeId: args.beliefGlobalId,
2734
+ toNodeId: topicGlobalId,
2588
2735
  sourceGlobalId: args.beliefGlobalId,
2589
2736
  targetGlobalId: topicGlobalId,
2590
2737
  edgeType: "belongs_to",
@@ -2763,7 +2910,7 @@ var create = mutation({
2763
2910
  const pillar = normalizePillar(args.pillar);
2764
2911
  const additionalMeta = args.metadata || {};
2765
2912
  const beliefGlobalId = generateGlobalId();
2766
- const nodeId = await ctx.db.insert("epistemicNodes", {
2913
+ const nodeId = await insertEpistemicNode(ctx, {
2767
2914
  globalId: beliefGlobalId,
2768
2915
  nodeType: "belief",
2769
2916
  epistemicLayer: "L3",
@@ -2821,7 +2968,6 @@ var create = mutation({
2821
2968
  })
2822
2969
  );
2823
2970
  await createRequiredBeliefTopicEdge(ctx, {
2824
- beliefNodeId: nodeId,
2825
2971
  beliefGlobalId,
2826
2972
  topicNode,
2827
2973
  createdBy: authenticatedUserId
@@ -3236,7 +3382,7 @@ var forkBelief = mutation({
3236
3382
  });
3237
3383
  }
3238
3384
  const newBeliefGlobalId = generateGlobalId();
3239
- const newNodeId = await ctx.db.insert("epistemicNodes", {
3385
+ const newNodeId = await insertEpistemicNode(ctx, {
3240
3386
  globalId: newBeliefGlobalId,
3241
3387
  nodeType: "belief",
3242
3388
  epistemicLayer: "L3",
@@ -4024,10 +4170,11 @@ var linkEvidence = mutation({
4024
4170
  const edgeType = "informs";
4025
4171
  const logicalRole = evidenceNodeId ? await computeLogicalRole(ctx, evidenceNodeId, args.beliefNodeId) : "contributory";
4026
4172
  const edgeGlobalId = generateGlobalId();
4027
- await ctx.db.insert("epistemicEdges", {
4173
+ await insertEpistemicEdge(ctx, {
4028
4174
  globalId: edgeGlobalId,
4029
- fromNodeId: evidenceNodeId,
4030
- toNodeId: args.beliefNodeId,
4175
+ // C2-RR.4 Defect E — canonical UUIDv7 endpoints, not Convex doc ids.
4176
+ fromNodeId: evidenceGlobalId,
4177
+ toNodeId: belief.globalId,
4031
4178
  sourceGlobalId: evidenceGlobalId,
4032
4179
  targetGlobalId: belief.globalId,
4033
4180
  edgeType,
@@ -4823,7 +4970,7 @@ var internalCreate = internalMutation({
4823
4970
  opinion_u: 1,
4824
4971
  opinion_a: baseRate
4825
4972
  };
4826
- const nodeId = await ctx.db.insert("epistemicNodes", {
4973
+ const nodeId = await insertEpistemicNode(ctx, {
4827
4974
  globalId,
4828
4975
  topicId: scope.topicId,
4829
4976
  projectId: scope.projectId,
@@ -4879,7 +5026,6 @@ var internalCreate = internalMutation({
4879
5026
  })
4880
5027
  );
4881
5028
  await createRequiredBeliefTopicEdge(ctx, {
4882
- beliefNodeId: nodeId,
4883
5029
  beliefGlobalId: globalId,
4884
5030
  topicNode,
4885
5031
  createdBy: args.userId
@@ -6084,7 +6230,7 @@ async function createEpistemicNodeForInsight(ctx, _insightId, insight) {
6084
6230
  });
6085
6231
  return existing._id;
6086
6232
  }
6087
- const nodeId = await ctx.db.insert("epistemicNodes", {
6233
+ const nodeId = await insertEpistemicNode(ctx, {
6088
6234
  globalId,
6089
6235
  nodeType: "evidence",
6090
6236
  epistemicLayer: "L2",
@@ -6160,7 +6306,7 @@ async function createEpistemicNodeForBelief(ctx, beliefId, belief) {
6160
6306
  });
6161
6307
  return existing._id;
6162
6308
  }
6163
- const nodeId = await ctx.db.insert("epistemicNodes", {
6309
+ const nodeId = await insertEpistemicNode(ctx, {
6164
6310
  globalId,
6165
6311
  nodeType: "belief",
6166
6312
  epistemicLayer: "L3",
@@ -6208,7 +6354,7 @@ async function createEpistemicNodeForQuestion(ctx, _questionId, question) {
6208
6354
  return existing._id;
6209
6355
  }
6210
6356
  const sourceType = question.source === "manual" ? "human" : question.source === "ai_suggested" ? "ai_generated" : "ai_extracted";
6211
- const nodeId = await ctx.db.insert("epistemicNodes", {
6357
+ const nodeId = await insertEpistemicNode(ctx, {
6212
6358
  globalId,
6213
6359
  nodeType: "question",
6214
6360
  epistemicLayer: "L3",
@@ -6269,7 +6415,7 @@ async function createEpistemicNodeForArtifact(ctx, artifactId, artifact) {
6269
6415
  return existing._id;
6270
6416
  }
6271
6417
  const epistemicLayer = "L1";
6272
- const nodeId = await ctx.db.insert("epistemicNodes", {
6418
+ const nodeId = await insertEpistemicNode(ctx, {
6273
6419
  globalId,
6274
6420
  nodeType,
6275
6421
  epistemicLayer,
@@ -6333,7 +6479,7 @@ async function findOrCreateSourceNode(ctx, artifactId, createdBy, scopeProjectId
6333
6479
  title + (artifact.content?.slice(0, 500) || "")
6334
6480
  );
6335
6481
  const epistemicLayer = nodeType === "synthesis" ? "L2" : "L1";
6336
- const nodeId = await ctx.db.insert("epistemicNodes", {
6482
+ const nodeId = await insertEpistemicNode(ctx, {
6337
6483
  globalId,
6338
6484
  nodeType,
6339
6485
  epistemicLayer,
@@ -6796,7 +6942,7 @@ async function applyOperationalLinkEffects(ctx, args) {
6796
6942
  if (beliefSpineNode?.nodeType === "belief" && evidenceSpineNode?.nodeType === "evidence") {
6797
6943
  const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
6798
6944
  "by_from_to",
6799
- (q) => q.eq("fromNodeId", evidenceSpineNode._id).eq("toNodeId", beliefSpineNode._id)
6945
+ (q) => q.eq("fromNodeId", evidenceSpineNode.globalId).eq("toNodeId", beliefSpineNode.globalId)
6800
6946
  ).collect();
6801
6947
  for (const edge of existingEdges) {
6802
6948
  if (edge.edgeType === "informs") {
@@ -6806,12 +6952,13 @@ async function applyOperationalLinkEffects(ctx, args) {
6806
6952
  await ctx.db.delete(edge._id);
6807
6953
  }
6808
6954
  }
6809
- const globalId = `edge-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
6955
+ const globalId = generateGlobalId();
6810
6956
  const context = args.rationale || `Linked as ${args.relation}`;
6811
- await ctx.db.insert("epistemicEdges", {
6957
+ await insertEpistemicEdge(ctx, {
6812
6958
  globalId,
6813
- fromNodeId: evidenceSpineNode._id,
6814
- toNodeId: beliefSpineNode._id,
6959
+ // C2-RR.4 Defect E — canonical UUIDv7 endpoints, not Convex doc ids.
6960
+ fromNodeId: evidenceSpineNode.globalId,
6961
+ toNodeId: beliefSpineNode.globalId,
6815
6962
  sourceGlobalId: evidenceSpineNode.globalId,
6816
6963
  targetGlobalId: beliefSpineNode.globalId,
6817
6964
  edgeType: "informs",
@@ -8814,7 +8961,7 @@ var createEntity = mutation({
8814
8961
  };
8815
8962
  }
8816
8963
  const entityGlobalId = generateGlobalId();
8817
- const nodeId = await ctx.db.insert("epistemicNodes", {
8964
+ const nodeId = await insertEpistemicNode(ctx, {
8818
8965
  globalId: entityGlobalId,
8819
8966
  nodeType: args.nodeType,
8820
8967
  epistemicLayer: "ontological",
@@ -9066,10 +9213,11 @@ var mergeEntities = mutation({
9066
9213
  );
9067
9214
  }
9068
9215
  const edgeGlobalId = generateGlobalId();
9069
- await ctx.db.insert("epistemicEdges", {
9216
+ await insertEpistemicEdge(ctx, {
9070
9217
  globalId: edgeGlobalId,
9071
- fromNodeId: args.duplicateNodeId,
9072
- toNodeId: args.canonicalNodeId,
9218
+ // C2-RR.4 Defect E — canonical UUIDv7 endpoints, not Convex doc ids.
9219
+ fromNodeId: duplicate.globalId,
9220
+ toNodeId: canonical.globalId,
9073
9221
  sourceGlobalId: duplicate.globalId,
9074
9222
  targetGlobalId: canonical.globalId,
9075
9223
  edgeType: "derived_from",
@@ -10354,7 +10502,7 @@ var create4 = mutation({
10354
10502
  }
10355
10503
  }
10356
10504
  }
10357
- const nodeId = await ctx.db.insert("epistemicNodes", {
10505
+ const nodeId = await insertEpistemicNode(ctx, {
10358
10506
  globalId,
10359
10507
  projectId: topicId,
10360
10508
  topicId: questionNode.topicId,
@@ -10409,7 +10557,7 @@ var create4 = mutation({
10409
10557
  }
10410
10558
  );
10411
10559
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10412
- globalId: crypto.randomUUID(),
10560
+ globalId: generateGlobalId(),
10413
10561
  fromGlobalId: globalId,
10414
10562
  toGlobalId: questionNode.globalId,
10415
10563
  edgeType: "responds_to",
@@ -10423,7 +10571,7 @@ var create4 = mutation({
10423
10571
  });
10424
10572
  for (const oldAnswer of activeAnswersForQuestion) {
10425
10573
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10426
- globalId: crypto.randomUUID(),
10574
+ globalId: generateGlobalId(),
10427
10575
  fromGlobalId: globalId,
10428
10576
  toGlobalId: oldAnswer.globalId,
10429
10577
  edgeType: "supersedes",
@@ -10440,7 +10588,7 @@ var create4 = mutation({
10440
10588
  const evNode = await ctx.db.get(evId);
10441
10589
  if (evNode) {
10442
10590
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10443
- globalId: crypto.randomUUID(),
10591
+ globalId: generateGlobalId(),
10444
10592
  fromGlobalId: globalId,
10445
10593
  toGlobalId: evNode.globalId,
10446
10594
  edgeType: "derived_from",
@@ -10462,7 +10610,7 @@ var create4 = mutation({
10462
10610
  const evidenceNode = await ctx.db.get(edge.fromNodeId);
10463
10611
  if (evidenceNode) {
10464
10612
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10465
- globalId: crypto.randomUUID(),
10613
+ globalId: generateGlobalId(),
10466
10614
  fromGlobalId: evidenceNode.globalId,
10467
10615
  toGlobalId: globalId,
10468
10616
  edgeType: "derived_from",
@@ -10554,7 +10702,7 @@ var createInternal = internalMutation({
10554
10702
  }
10555
10703
  }
10556
10704
  }
10557
- const nodeId = await ctx.db.insert("epistemicNodes", {
10705
+ const nodeId = await insertEpistemicNode(ctx, {
10558
10706
  globalId,
10559
10707
  projectId: topicId,
10560
10708
  topicId: questionNode.topicId,
@@ -10610,7 +10758,7 @@ var createInternal = internalMutation({
10610
10758
  }
10611
10759
  );
10612
10760
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10613
- globalId: crypto.randomUUID(),
10761
+ globalId: generateGlobalId(),
10614
10762
  fromGlobalId: globalId,
10615
10763
  toGlobalId: questionNode.globalId,
10616
10764
  edgeType: "responds_to",
@@ -10624,7 +10772,7 @@ var createInternal = internalMutation({
10624
10772
  });
10625
10773
  for (const oldAnswer of activeAnswersForQuestion) {
10626
10774
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10627
- globalId: crypto.randomUUID(),
10775
+ globalId: generateGlobalId(),
10628
10776
  fromGlobalId: globalId,
10629
10777
  toGlobalId: oldAnswer.globalId,
10630
10778
  edgeType: "supersedes",
@@ -10641,7 +10789,7 @@ var createInternal = internalMutation({
10641
10789
  const evNode = await ctx.db.get(evId);
10642
10790
  if (evNode) {
10643
10791
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10644
- globalId: crypto.randomUUID(),
10792
+ globalId: generateGlobalId(),
10645
10793
  fromGlobalId: globalId,
10646
10794
  toGlobalId: evNode.globalId,
10647
10795
  edgeType: "derived_from",
@@ -10663,7 +10811,7 @@ var createInternal = internalMutation({
10663
10811
  const evidenceNode = await ctx.db.get(edge.fromNodeId);
10664
10812
  if (evidenceNode) {
10665
10813
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
10666
- globalId: crypto.randomUUID(),
10814
+ globalId: generateGlobalId(),
10667
10815
  fromGlobalId: evidenceNode.globalId,
10668
10816
  toGlobalId: globalId,
10669
10817
  edgeType: "derived_from",
@@ -11880,11 +12028,21 @@ var mirrorEdgeToConvex = internalMutation({
11880
12028
  console.log(`[Dual-Write] Edge already exists: ${args.globalId}`);
11881
12029
  return buildEdgeMirrorWriteResult(existing._id, true);
11882
12030
  }
12031
+ if (!toNode) {
12032
+ console.log(
12033
+ `[Dual-Write] Skipping mirror - to-node not in Convex: ${args.toGlobalId} (edge ${args.globalId} type ${args.edgeType})`
12034
+ );
12035
+ return buildEdgeMirrorSkippedResult();
12036
+ }
11883
12037
  const now = Date.now();
11884
- const edgeId = await ctx.db.insert("epistemicEdges", {
12038
+ const edgeId = await insertEpistemicEdge(ctx, {
11885
12039
  globalId: args.globalId,
11886
- fromNodeId: fromNode._id,
11887
- toNodeId: toNode?._id,
12040
+ // C2-RR.4 Defect E — endpoints are canonical node globalIds, not Convex
12041
+ // doc ids. fromNode/toNode are resolved by_globalId above, so their
12042
+ // stored globalId equals args.from/toGlobalId; persisting the doc _id here
12043
+ // was the "mixed _id/globalId" defect.
12044
+ fromNodeId: fromNode.globalId,
12045
+ toNodeId: toNode.globalId,
11888
12046
  sourceGlobalId: args.fromGlobalId,
11889
12047
  targetGlobalId: args.toGlobalId,
11890
12048
  // Preserve the canonical string value even when the local schema lags.
@@ -12230,17 +12388,17 @@ function normalizeEvidenceRelation(relation, weight, context) {
12230
12388
  return weight < 0 ? "contradicts" : "supports";
12231
12389
  }
12232
12390
  async function createEvidenceBeliefEdge(ctx, args) {
12233
- const edgeGlobalId = crypto.randomUUID();
12391
+ const edgeGlobalId = generateGlobalId();
12234
12392
  const confidence = Math.abs(args.weight);
12235
12393
  const existingEdges = await ctx.db.query("epistemicEdges").withIndex(
12236
12394
  "by_from_to",
12237
- (q) => q.eq("fromNodeId", args.evidenceNodeId).eq("toNodeId", args.beliefNodeId)
12395
+ (q) => q.eq("fromNodeId", args.evidenceGlobalId).eq("toNodeId", args.beliefGlobalId)
12238
12396
  ).collect();
12239
12397
  const existing = existingEdges.find((edge) => edge.edgeType === "informs");
12240
12398
  const edgeDoc = {
12241
12399
  globalId: edgeGlobalId,
12242
- fromNodeId: args.evidenceNodeId,
12243
- toNodeId: args.beliefNodeId,
12400
+ fromNodeId: args.evidenceGlobalId,
12401
+ toNodeId: args.beliefGlobalId,
12244
12402
  sourceGlobalId: args.evidenceGlobalId,
12245
12403
  targetGlobalId: args.beliefGlobalId,
12246
12404
  edgeType: "informs",
@@ -12272,7 +12430,7 @@ async function createEvidenceBeliefEdge(ctx, args) {
12272
12430
  createdAt: existing.createdAt ?? edgeDoc.createdAt
12273
12431
  });
12274
12432
  } else {
12275
- await ctx.db.insert("epistemicEdges", edgeDoc);
12433
+ await insertEpistemicEdge(ctx, edgeDoc);
12276
12434
  }
12277
12435
  await ctx.scheduler.runAfter(5e3, internal.neo4jEdgeAPI.createEdge, {
12278
12436
  globalId: existing?.globalId ?? edgeGlobalId,
@@ -12311,10 +12469,23 @@ var create6 = mutation({
12311
12469
  sourceQuestionId: v.optional(v.string()),
12312
12470
  userId: v.string(),
12313
12471
  rationale: v.string(),
12314
- // Classification fields (from AI tools)
12472
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
12473
+ sourceRef: v.optional(v.string()),
12474
+ sourceQuality: v.optional(
12475
+ v.union(
12476
+ v.literal("primary"),
12477
+ v.literal("analyzed"),
12478
+ v.literal("secondary"),
12479
+ v.literal("tertiary"),
12480
+ v.literal("unknown")
12481
+ )
12482
+ ),
12315
12483
  methodology: v.optional(v.string()),
12316
12484
  informationAsymmetry: v.optional(v.string()),
12317
12485
  sourceDescription: v.optional(v.string()),
12486
+ // signedImpact is derived from weight; accepted as an explicit override for
12487
+ // callers that already have the signed value (kernel parity).
12488
+ signedImpact: v.optional(v.number()),
12318
12489
  metadata: v.optional(v.any()),
12319
12490
  // Required belief impact link.
12320
12491
  linkedBeliefNodeId: v.id("epistemicNodes"),
@@ -12344,6 +12515,7 @@ var create6 = mutation({
12344
12515
  const kind = normalizeKind(args.kind);
12345
12516
  const sourceType = normalizeSourceType(args.sourceType);
12346
12517
  const weight = assertSignedImpactScore2(args.weight, "Evidence creation");
12518
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore2(args.signedImpact, "Evidence creation signedImpact") : weight;
12347
12519
  const evidenceRelation = normalizeEvidenceRelation(
12348
12520
  args.evidenceRelation,
12349
12521
  weight,
@@ -12354,7 +12526,7 @@ var create6 = mutation({
12354
12526
  throw new Error("Evidence creation requires a linked belief node");
12355
12527
  }
12356
12528
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
12357
- const nodeId = await ctx.db.insert("epistemicNodes", {
12529
+ const nodeId = await insertEpistemicNode(ctx, {
12358
12530
  globalId,
12359
12531
  topicId: scope.topicId,
12360
12532
  projectId: scope.projectId,
@@ -12369,6 +12541,15 @@ var create6 = mutation({
12369
12541
  status: "active",
12370
12542
  epistemicLayer: "L2",
12371
12543
  sourceType,
12544
+ // RC.1 taxonomy fields — top-level projection
12545
+ evidenceRelation,
12546
+ signedImpact,
12547
+ targetBeliefId: String(args.linkedBeliefNodeId),
12548
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
12549
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
12550
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
12551
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
12552
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
12372
12553
  createdAt: now,
12373
12554
  updatedAt: now,
12374
12555
  createdBy: args.userId,
@@ -12404,7 +12585,6 @@ var create6 = mutation({
12404
12585
  text: args.text
12405
12586
  });
12406
12587
  await createEvidenceBeliefEdge(ctx, {
12407
- evidenceNodeId: nodeId,
12408
12588
  evidenceGlobalId: globalId,
12409
12589
  beliefNodeId: args.linkedBeliefNodeId,
12410
12590
  beliefGlobalId: linkedBeliefNode.globalId,
@@ -12474,7 +12654,22 @@ var createAndLink = mutation({
12474
12654
  beliefNodeId: v.id("epistemicNodes"),
12475
12655
  relation: v.union(v.literal("supports"), v.literal("contradicts")),
12476
12656
  weight: v.number(),
12477
- confidence: v.optional(v.number())
12657
+ confidence: v.optional(v.number()),
12658
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
12659
+ sourceRef: v.optional(v.string()),
12660
+ sourceQuality: v.optional(
12661
+ v.union(
12662
+ v.literal("primary"),
12663
+ v.literal("analyzed"),
12664
+ v.literal("secondary"),
12665
+ v.literal("tertiary"),
12666
+ v.literal("unknown")
12667
+ )
12668
+ ),
12669
+ methodology: v.optional(v.string()),
12670
+ informationAsymmetry: v.optional(v.string()),
12671
+ sourceDescription: v.optional(v.string()),
12672
+ signedImpact: v.optional(v.number())
12478
12673
  },
12479
12674
  returns: permissiveReturn,
12480
12675
  handler: async (ctx, args) => {
@@ -12489,6 +12684,7 @@ var createAndLink = mutation({
12489
12684
  const kind = normalizeKind(args.kind);
12490
12685
  const sourceType = normalizeSourceType(args.sourceType);
12491
12686
  const weight = assertSignedImpactScore2(args.weight, "Evidence createAndLink");
12687
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore2(args.signedImpact, "Evidence createAndLink signedImpact") : weight;
12492
12688
  const relation = normalizeEvidenceRelation(
12493
12689
  args.relation,
12494
12690
  weight,
@@ -12499,7 +12695,7 @@ var createAndLink = mutation({
12499
12695
  if (!beliefNode || beliefNode.nodeType !== "belief") {
12500
12696
  throw new Error("Belief node not found for edge creation");
12501
12697
  }
12502
- const nodeId = await ctx.db.insert("epistemicNodes", {
12698
+ const nodeId = await insertEpistemicNode(ctx, {
12503
12699
  globalId,
12504
12700
  topicId: scope.topicId,
12505
12701
  projectId: scope.projectId,
@@ -12511,6 +12707,15 @@ var createAndLink = mutation({
12511
12707
  status: "active",
12512
12708
  epistemicLayer: "L2",
12513
12709
  sourceType,
12710
+ // RC.1 taxonomy fields — top-level projection
12711
+ evidenceRelation: relation,
12712
+ signedImpact,
12713
+ targetBeliefId: String(args.beliefNodeId),
12714
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
12715
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
12716
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
12717
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
12718
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
12514
12719
  createdAt: now,
12515
12720
  updatedAt: now,
12516
12721
  createdBy: args.userId,
@@ -12529,7 +12734,6 @@ var createAndLink = mutation({
12529
12734
  operation: "upsert"
12530
12735
  });
12531
12736
  const edgeGlobalId = await createEvidenceBeliefEdge(ctx, {
12532
- evidenceNodeId: nodeId,
12533
12737
  evidenceGlobalId: globalId,
12534
12738
  beliefNodeId: args.beliefNodeId,
12535
12739
  beliefGlobalId: beliefNode.globalId,
@@ -12602,6 +12806,21 @@ var internalCreate2 = internalMutation({
12602
12806
  evidenceRelation: v.optional(v.string()),
12603
12807
  weight: v.number(),
12604
12808
  confidence: v.optional(v.number()),
12809
+ // RC.1 taxonomy fields — top-level projection (mirroring kernel evidenceCreate.ts)
12810
+ sourceRef: v.optional(v.string()),
12811
+ sourceQuality: v.optional(
12812
+ v.union(
12813
+ v.literal("primary"),
12814
+ v.literal("analyzed"),
12815
+ v.literal("secondary"),
12816
+ v.literal("tertiary"),
12817
+ v.literal("unknown")
12818
+ )
12819
+ ),
12820
+ methodology: v.optional(v.string()),
12821
+ informationAsymmetry: v.optional(v.string()),
12822
+ sourceDescription: v.optional(v.string()),
12823
+ signedImpact: v.optional(v.number()),
12605
12824
  metadata: v.optional(v.any()),
12606
12825
  runtimeToolName: v.optional(v.string()),
12607
12826
  runtimePackKey: v.optional(v.string()),
@@ -12636,6 +12855,7 @@ var internalCreate2 = internalMutation({
12636
12855
  const kind = normalizeKind(args.kind);
12637
12856
  const sourceType = normalizeSourceType(args.sourceType);
12638
12857
  const weight = assertSignedImpactScore2(args.weight, "Internal evidence creation");
12858
+ const signedImpact = args.signedImpact !== void 0 ? assertSignedImpactScore2(args.signedImpact, "Internal evidence creation signedImpact") : weight;
12639
12859
  const evidenceRelation = normalizeEvidenceRelation(
12640
12860
  args.evidenceRelation,
12641
12861
  weight,
@@ -12646,7 +12866,7 @@ var internalCreate2 = internalMutation({
12646
12866
  throw new Error("Internal evidence creation requires a linked belief node");
12647
12867
  }
12648
12868
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
12649
- const nodeId = await ctx.db.insert("epistemicNodes", {
12869
+ const nodeId = await insertEpistemicNode(ctx, {
12650
12870
  globalId,
12651
12871
  topicId: scope.topicId,
12652
12872
  projectId: scope.projectId,
@@ -12661,6 +12881,15 @@ var internalCreate2 = internalMutation({
12661
12881
  status: "active",
12662
12882
  epistemicLayer: "L2",
12663
12883
  sourceType,
12884
+ // RC.1 taxonomy fields — top-level projection
12885
+ evidenceRelation,
12886
+ signedImpact,
12887
+ targetBeliefId: String(args.linkedBeliefNodeId),
12888
+ ...typeof args.sourceRef === "string" && args.sourceRef.trim().length > 0 ? { sourceRef: args.sourceRef.trim() } : {},
12889
+ ...typeof args.sourceQuality === "string" && args.sourceQuality.length > 0 ? { sourceQuality: args.sourceQuality } : {},
12890
+ ...typeof args.methodology === "string" && args.methodology.length > 0 ? { methodology: args.methodology } : {},
12891
+ ...typeof args.informationAsymmetry === "string" && args.informationAsymmetry.length > 0 ? { informationAsymmetry: args.informationAsymmetry } : {},
12892
+ ...typeof args.sourceDescription === "string" && args.sourceDescription.trim().length > 0 ? { sourceDescription: args.sourceDescription.trim() } : {},
12664
12893
  createdAt: now,
12665
12894
  updatedAt: now,
12666
12895
  createdBy: args.userId,
@@ -12706,7 +12935,6 @@ var internalCreate2 = internalMutation({
12706
12935
  operation: "upsert"
12707
12936
  });
12708
12937
  await createEvidenceBeliefEdge(ctx, {
12709
- evidenceNodeId: nodeId,
12710
12938
  evidenceGlobalId: globalId,
12711
12939
  beliefNodeId: args.linkedBeliefNodeId,
12712
12940
  beliefGlobalId: linkedBeliefNode.globalId,
@@ -14235,7 +14463,7 @@ var create7 = mutation({
14235
14463
  "Workspace-scoped reasoning isolation requires topicId or projectId for non-ontological node creation."
14236
14464
  );
14237
14465
  }
14238
- const nodeId = await ctx.db.insert("epistemicNodes", {
14466
+ const nodeId = await insertEpistemicNode(ctx, {
14239
14467
  globalId: args.globalId,
14240
14468
  nodeType: args.nodeType,
14241
14469
  epistemicLayer,
@@ -14400,7 +14628,7 @@ var supersede = mutation({
14400
14628
  });
14401
14629
  const now = Date.now();
14402
14630
  const epistemicLayer = oldNode.epistemicLayer || getNodeLayer(oldNode.nodeType);
14403
- const newNodeId = await ctx.db.insert("epistemicNodes", {
14631
+ const newNodeId = await insertEpistemicNode(ctx, {
14404
14632
  globalId: args.newGlobalId,
14405
14633
  nodeType: oldNode.nodeType,
14406
14634
  epistemicLayer,
@@ -14606,7 +14834,7 @@ var batchCreate2 = mutation({
14606
14834
  });
14607
14835
  const epistemicLayer = getNodeLayer(node.nodeType);
14608
14836
  const resolvedScope = await resolveNodeScope(node);
14609
- const nodeId = await ctx.db.insert("epistemicNodes", {
14837
+ const nodeId = await insertEpistemicNode(ctx, {
14610
14838
  ...node,
14611
14839
  epistemicLayer,
14612
14840
  // Phase 2B: Auto-derived from nodeType
@@ -14708,7 +14936,7 @@ var createInternal2 = internalMutation({
14708
14936
  })() : void 0;
14709
14937
  const contentHash = args.contentHash || `${args.nodeType}:${args.canonicalText}`.slice(0, 64);
14710
14938
  const epistemicLayer = args.epistemicLayer || getNodeLayer(args.nodeType);
14711
- const nodeId = await ctx.db.insert("epistemicNodes", {
14939
+ const nodeId = await insertEpistemicNode(ctx, {
14712
14940
  globalId: args.globalId,
14713
14941
  nodeType: args.nodeType,
14714
14942
  epistemicLayer,
@@ -15316,7 +15544,7 @@ var create8 = mutation({
15316
15544
  const globalId = generateGlobalId();
15317
15545
  const contentHash = generateContentHash6(args.question);
15318
15546
  const category = normalizeCategory(args.category);
15319
- const nodeId = await ctx.db.insert("epistemicNodes", {
15547
+ const nodeId = await insertEpistemicNode(ctx, {
15320
15548
  globalId,
15321
15549
  topicId: scope.topicId,
15322
15550
  projectId: scope.projectId,
@@ -15484,7 +15712,7 @@ var createBatch = mutation({
15484
15712
  const globalId = generateGlobalId();
15485
15713
  const contentHash = generateContentHash6(q.question);
15486
15714
  const category = normalizeCategory(q.category);
15487
- const nodeId = await ctx.db.insert("epistemicNodes", {
15715
+ const nodeId = await insertEpistemicNode(ctx, {
15488
15716
  globalId,
15489
15717
  topicId: scope.topicId,
15490
15718
  projectId: scope.projectId,
@@ -15536,7 +15764,7 @@ var createBatch = mutation({
15536
15764
  const beliefNode = await ctx.db.get(q.linkedBeliefNodeId);
15537
15765
  if (beliefNode) {
15538
15766
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
15539
- globalId: crypto.randomUUID(),
15767
+ globalId: generateGlobalId(),
15540
15768
  fromGlobalId: beliefNode.globalId,
15541
15769
  toGlobalId: globalId,
15542
15770
  edgeType: "tests",
@@ -15600,7 +15828,7 @@ var internalCreate3 = internalMutation({
15600
15828
  const globalId = generateGlobalId();
15601
15829
  const contentHash = generateContentHash6(args.question);
15602
15830
  const category = normalizeCategory(args.category);
15603
- const nodeId = await ctx.db.insert("epistemicNodes", {
15831
+ const nodeId = await insertEpistemicNode(ctx, {
15604
15832
  globalId,
15605
15833
  topicId: scope.topicId,
15606
15834
  projectId: scope.projectId,
@@ -15632,7 +15860,7 @@ var internalCreate3 = internalMutation({
15632
15860
  const beliefNode = await ctx.db.get(args.linkedBeliefNodeId);
15633
15861
  if (beliefNode) {
15634
15862
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
15635
- globalId: crypto.randomUUID(),
15863
+ globalId: generateGlobalId(),
15636
15864
  fromGlobalId: beliefNode.globalId,
15637
15865
  toGlobalId: globalId,
15638
15866
  edgeType: "tests",
@@ -15703,7 +15931,7 @@ var addQuestion = mutation({
15703
15931
  const contentHash = generateContentHash6(args.question);
15704
15932
  const category = normalizeCategory(args.category);
15705
15933
  const additionalMetadata = args.metadata && typeof args.metadata === "object" ? args.metadata : {};
15706
- const nodeId = await ctx.db.insert("epistemicNodes", {
15934
+ const nodeId = await insertEpistemicNode(ctx, {
15707
15935
  globalId,
15708
15936
  topicId: scope.topicId,
15709
15937
  projectId: scope.projectId,
@@ -16377,7 +16605,7 @@ var consolidate = mutation({
16377
16605
  const now = Date.now();
16378
16606
  const globalId = generateGlobalId();
16379
16607
  const contentHash = generateContentHash6(args.consolidatedQuestion);
16380
- const newNodeId = await ctx.db.insert("epistemicNodes", {
16608
+ const newNodeId = await insertEpistemicNode(ctx, {
16381
16609
  globalId,
16382
16610
  projectId: scope.projectId,
16383
16611
  topicId: scope.topicId,
@@ -16642,7 +16870,7 @@ var createEvidenceFromScoredQuestion = internalMutation({
16642
16870
  A: ${args.answerText}`;
16643
16871
  const globalId = generateGlobalId();
16644
16872
  const contentHash = `evidence:${args.questionNodeId}:scored`;
16645
- const evidenceNodeId = await ctx.db.insert("epistemicNodes", {
16873
+ const evidenceNodeId = await insertEpistemicNode(ctx, {
16646
16874
  globalId,
16647
16875
  projectId: args.projectId,
16648
16876
  topicId: normalizeQuestionTopicId(args.topicId),
@@ -18116,7 +18344,7 @@ var upsertSource = mutation({
18116
18344
  capturedAt: normalizeNumber(args.capturedAt),
18117
18345
  metadata: metadataPatch
18118
18346
  });
18119
- const nodeId = await ctx.db.insert("epistemicNodes", {
18347
+ const nodeId = await insertEpistemicNode(ctx, {
18120
18348
  globalId,
18121
18349
  topicId: scope.topicId,
18122
18350
  projectId: scope.projectId,