@lucern/graph-primitives 1.0.28 → 1.0.30

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 (319) hide show
  1. package/dist/{beliefDecay-DZ6tkLYq.d.ts → beliefDecay-BmkEk5OJ.d.ts} +3 -3
  2. package/dist/beliefDecay.d.ts +1 -1
  3. package/dist/beliefDecay.js +448 -314
  4. package/dist/beliefDecay.js.map +1 -1
  5. package/dist/{beliefEvidenceLinks-CWOXxxJg.d.ts → beliefEvidenceLinks-BzfjON_6.d.ts} +13 -13
  6. package/dist/beliefEvidenceLinks.d.ts +1 -1
  7. package/dist/beliefEvidenceLinks.js +843 -624
  8. package/dist/beliefEvidenceLinks.js.map +1 -1
  9. package/dist/beliefEvidenceLinks.operational.d.ts +7 -5
  10. package/dist/beliefEvidenceLinks.operational.js +91 -18
  11. package/dist/beliefEvidenceLinks.operational.js.map +1 -1
  12. package/dist/beliefLifecycle.js.map +1 -1
  13. package/dist/confidencePropagationDispatch.d.ts +28 -27
  14. package/dist/confidencePropagationDispatch.js +157 -99
  15. package/dist/confidencePropagationDispatch.js.map +1 -1
  16. package/dist/{contradictions-51VLsESq.d.ts → contradictions-BATPuZTL.d.ts} +10 -10
  17. package/dist/contradictions.d.ts +1 -1
  18. package/dist/contradictions.js +398 -228
  19. package/dist/contradictions.js.map +1 -1
  20. package/dist/convex.d.ts +65 -30
  21. package/dist/convex.js +7 -3
  22. package/dist/convex.js.map +1 -1
  23. package/dist/debug.js.map +1 -1
  24. package/dist/edgeValidation.js +293 -85
  25. package/dist/edgeValidation.js.map +1 -1
  26. package/dist/edges/contains.d.ts +1 -1
  27. package/dist/edges/contains.js.map +1 -1
  28. package/dist/edges/contradicts.d.ts +1 -1
  29. package/dist/edges/contradicts.js.map +1 -1
  30. package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
  31. package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
  32. package/dist/edges/depends-on.js.map +1 -0
  33. package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
  34. package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
  35. package/dist/edges/derived-from.js.map +1 -0
  36. package/dist/edges/elaborates.d.ts +1 -1
  37. package/dist/edges/elaborates.js.map +1 -1
  38. package/dist/edges/index.d.ts +7 -3
  39. package/dist/edges/index.js +7 -4
  40. package/dist/edges/index.js.map +1 -1
  41. package/dist/edges/informs.d.ts +1 -1
  42. package/dist/edges/informs.js.map +1 -1
  43. package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
  44. package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
  45. package/dist/edges/propagation-types.js.map +1 -0
  46. package/dist/edges/refutes.d.ts +1 -1
  47. package/dist/edges/refutes.js.map +1 -1
  48. package/dist/edges/supports.d.ts +1 -1
  49. package/dist/edges/supports.js.map +1 -1
  50. package/dist/edges/tests.d.ts +1 -1
  51. package/dist/edges/tests.js.map +1 -1
  52. package/dist/edges/utils.d.ts +1 -1
  53. package/dist/edges/utils.js.map +1 -1
  54. package/dist/embeddingTrigger.d.ts +14 -6
  55. package/dist/embeddingTrigger.js +11 -14
  56. package/dist/embeddingTrigger.js.map +1 -1
  57. package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
  58. package/dist/entityBridge.d.ts +1 -1
  59. package/dist/entityBridge.js +602 -225
  60. package/dist/entityBridge.js.map +1 -1
  61. package/dist/entityCanonicalMatch.d.ts +14 -12
  62. package/dist/entityCanonicalMatch.js.map +1 -1
  63. package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
  64. package/dist/entityLifecycle.d.ts +1 -1
  65. package/dist/entityLifecycle.js +857 -515
  66. package/dist/entityLifecycle.js.map +1 -1
  67. package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
  68. package/dist/entityValidation.d.ts +3 -1
  69. package/dist/entityValidation.js +60 -8
  70. package/dist/entityValidation.js.map +1 -1
  71. package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
  72. package/dist/epistemicAnswers.d.ts +1 -1
  73. package/dist/epistemicAnswers.js +587 -545
  74. package/dist/epistemicAnswers.js.map +1 -1
  75. package/dist/epistemicBeliefs.admin.d.ts +8 -8
  76. package/dist/epistemicBeliefs.admin.js +366 -203
  77. package/dist/epistemicBeliefs.admin.js.map +1 -1
  78. package/dist/epistemicBeliefs.backfills.d.ts +8 -8
  79. package/dist/epistemicBeliefs.backfills.js +655 -308
  80. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  81. package/dist/epistemicBeliefs.confidence.d.ts +19 -14
  82. package/dist/epistemicBeliefs.confidence.js +634 -423
  83. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  84. package/dist/epistemicBeliefs.core.d.ts +6 -6
  85. package/dist/epistemicBeliefs.core.js +719 -411
  86. package/dist/epistemicBeliefs.core.js.map +1 -1
  87. package/dist/epistemicBeliefs.d.ts +11 -8
  88. package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
  89. package/dist/epistemicBeliefs.forkEvidence.js +8 -28
  90. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  91. package/dist/epistemicBeliefs.helpers.d.ts +69 -74
  92. package/dist/epistemicBeliefs.helpers.js +359 -248
  93. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  94. package/dist/epistemicBeliefs.internal.d.ts +5 -5
  95. package/dist/epistemicBeliefs.internal.js +1246 -1044
  96. package/dist/epistemicBeliefs.internal.js.map +1 -1
  97. package/dist/epistemicBeliefs.js +4922 -3608
  98. package/dist/epistemicBeliefs.js.map +1 -1
  99. package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
  100. package/dist/epistemicBeliefs.lifecycle.js +1137 -818
  101. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  102. package/dist/epistemicBeliefs.links.d.ts +7 -7
  103. package/dist/epistemicBeliefs.links.js +408 -307
  104. package/dist/epistemicBeliefs.links.js.map +1 -1
  105. package/dist/epistemicBeliefs.queries.d.ts +4 -4
  106. package/dist/epistemicBeliefs.queries.js +175 -20
  107. package/dist/epistemicBeliefs.queries.js.map +1 -1
  108. package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
  109. package/dist/epistemicBeliefs.topicAnchor.js +12 -5
  110. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  111. package/dist/epistemicContracts.d.ts +28 -3
  112. package/dist/epistemicContracts.evaluators.d.ts +2 -0
  113. package/dist/epistemicContracts.evaluators.js +1063 -613
  114. package/dist/epistemicContracts.evaluators.js.map +1 -1
  115. package/dist/epistemicContracts.handlers.d.ts +15 -32
  116. package/dist/epistemicContracts.handlers.js +2086 -1644
  117. package/dist/epistemicContracts.handlers.js.map +1 -1
  118. package/dist/epistemicContracts.js +1131 -672
  119. package/dist/epistemicContracts.js.map +1 -1
  120. package/dist/epistemicContracts.metrics.d.ts +2 -0
  121. package/dist/epistemicContracts.metrics.js +375 -158
  122. package/dist/epistemicContracts.metrics.js.map +1 -1
  123. package/dist/epistemicContracts.types.d.ts +87 -81
  124. package/dist/epistemicEdgeCreation.d.ts +2 -0
  125. package/dist/epistemicEdgeCreation.js +87 -16
  126. package/dist/epistemicEdgeCreation.js.map +1 -1
  127. package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
  128. package/dist/epistemicEdges.d.ts +6 -5
  129. package/dist/epistemicEdges.handlers.d.ts +3 -3
  130. package/dist/epistemicEdges.handlers.js +129 -24
  131. package/dist/epistemicEdges.handlers.js.map +1 -1
  132. package/dist/epistemicEdges.helpers.d.ts +6 -4
  133. package/dist/epistemicEdges.helpers.js +37 -2
  134. package/dist/epistemicEdges.helpers.js.map +1 -1
  135. package/dist/epistemicEdges.js +1969 -1205
  136. package/dist/epistemicEdges.js.map +1 -1
  137. package/dist/epistemicEdges.mutations.d.ts +7 -7
  138. package/dist/epistemicEdges.mutations.js +960 -583
  139. package/dist/epistemicEdges.mutations.js.map +1 -1
  140. package/dist/epistemicEdges.queries.d.ts +16 -16
  141. package/dist/epistemicEdges.queries.js +639 -367
  142. package/dist/epistemicEdges.queries.js.map +1 -1
  143. package/dist/epistemicEdges.types.d.ts +10 -8
  144. package/dist/epistemicEvidence.d.ts +4 -1
  145. package/dist/epistemicEvidence.js +937 -536
  146. package/dist/epistemicEvidence.js.map +1 -1
  147. package/dist/epistemicEvidenceHelpers.d.ts +26 -10
  148. package/dist/epistemicEvidenceHelpers.js +239 -200
  149. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  150. package/dist/epistemicEvidenceMutations.d.ts +8 -8
  151. package/dist/epistemicEvidenceMutations.js +844 -696
  152. package/dist/epistemicEvidenceMutations.js.map +1 -1
  153. package/dist/epistemicEvidenceQueries.d.ts +8 -8
  154. package/dist/epistemicEvidenceQueries.js +514 -238
  155. package/dist/epistemicEvidenceQueries.js.map +1 -1
  156. package/dist/epistemicHelpers.d.ts +4 -2
  157. package/dist/epistemicHelpers.js +308 -134
  158. package/dist/epistemicHelpers.js.map +1 -1
  159. package/dist/epistemicInsert.d.ts +16 -4
  160. package/dist/epistemicInsert.js +6 -3
  161. package/dist/epistemicInsert.js.map +1 -1
  162. package/dist/epistemicLayerRules.d.ts +10 -8
  163. package/dist/epistemicLayerRules.js +1 -5
  164. package/dist/epistemicLayerRules.js.map +1 -1
  165. package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
  166. package/dist/epistemicLinking.d.ts +1 -1
  167. package/dist/epistemicLinking.js +177 -100
  168. package/dist/epistemicLinking.js.map +1 -1
  169. package/dist/epistemicNodeCreation.d.ts +2 -0
  170. package/dist/epistemicNodeCreation.js +203 -40
  171. package/dist/epistemicNodeCreation.js.map +1 -1
  172. package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
  173. package/dist/epistemicNodes.d.ts +3 -3
  174. package/dist/epistemicNodes.helpers.d.ts +24 -15
  175. package/dist/epistemicNodes.helpers.js.map +1 -1
  176. package/dist/epistemicNodes.internal.d.ts +6 -6
  177. package/dist/epistemicNodes.internal.js +389 -319
  178. package/dist/epistemicNodes.internal.js.map +1 -1
  179. package/dist/epistemicNodes.js +704 -508
  180. package/dist/epistemicNodes.js.map +1 -1
  181. package/dist/epistemicNodes.mutations.d.ts +6 -6
  182. package/dist/epistemicNodes.mutations.js +564 -467
  183. package/dist/epistemicNodes.mutations.js.map +1 -1
  184. package/dist/epistemicNodes.queries.d.ts +8 -8
  185. package/dist/epistemicNodes.queries.js +311 -314
  186. package/dist/epistemicNodes.queries.js.map +1 -1
  187. package/dist/epistemicNodes.validators.d.ts +2 -2
  188. package/dist/epistemicNodes.validators.js.map +1 -1
  189. package/dist/epistemicQuestions.conviction.d.ts +8 -8
  190. package/dist/epistemicQuestions.conviction.js +665 -484
  191. package/dist/epistemicQuestions.conviction.js.map +1 -1
  192. package/dist/epistemicQuestions.create.d.ts +4 -4
  193. package/dist/epistemicQuestions.create.js +640 -612
  194. package/dist/epistemicQuestions.create.js.map +1 -1
  195. package/dist/epistemicQuestions.d.ts +8 -5
  196. package/dist/epistemicQuestions.evidence.d.ts +2 -2
  197. package/dist/epistemicQuestions.evidence.js +475 -383
  198. package/dist/epistemicQuestions.evidence.js.map +1 -1
  199. package/dist/epistemicQuestions.helpers.d.ts +125 -24
  200. package/dist/epistemicQuestions.helpers.js +240 -209
  201. package/dist/epistemicQuestions.helpers.js.map +1 -1
  202. package/dist/epistemicQuestions.js +3474 -2823
  203. package/dist/epistemicQuestions.js.map +1 -1
  204. package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
  205. package/dist/epistemicQuestions.lifecycle.js +607 -546
  206. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  207. package/dist/epistemicQuestions.queries.d.ts +12 -7
  208. package/dist/epistemicQuestions.queries.js +305 -244
  209. package/dist/epistemicQuestions.queries.js.map +1 -1
  210. package/dist/epistemicQuestions.sprint.d.ts +2 -2
  211. package/dist/epistemicQuestions.sprint.js +600 -394
  212. package/dist/epistemicQuestions.sprint.js.map +1 -1
  213. package/dist/epistemicQuestions.tail.d.ts +6 -6
  214. package/dist/epistemicQuestions.tail.js +572 -433
  215. package/dist/epistemicQuestions.tail.js.map +1 -1
  216. package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
  217. package/dist/epistemicSources.d.ts +1 -1
  218. package/dist/epistemicSources.js +352 -312
  219. package/dist/epistemicSources.js.map +1 -1
  220. package/dist/evaluators/index.d.ts +8 -6
  221. package/dist/evaluators/index.js +399 -167
  222. package/dist/evaluators/index.js.map +1 -1
  223. package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
  224. package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
  225. package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
  226. package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
  227. package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
  228. package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
  229. package/dist/evaluators/shared.d.ts +2 -2
  230. package/dist/evaluators/shared.js +3 -1
  231. package/dist/evaluators/shared.js.map +1 -1
  232. package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
  233. package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
  234. package/dist/evaluators/test-runner-evaluator.js.map +1 -0
  235. package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
  236. package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
  237. package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
  238. package/dist/graphTypes.js +6 -2
  239. package/dist/graphTypes.js.map +1 -1
  240. package/dist/helpers.d.ts +2 -0
  241. package/dist/helpers.js +313 -93
  242. package/dist/helpers.js.map +1 -1
  243. package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
  244. package/dist/index.d.ts +87 -83
  245. package/dist/index.js +15677 -10594
  246. package/dist/index.js.map +1 -1
  247. package/dist/invariantEnforcement.d.ts +3 -3
  248. package/dist/invariantEnforcement.js.map +1 -1
  249. package/dist/logicalRoleInference.d.ts +2 -0
  250. package/dist/logicalRoleInference.js +1 -1
  251. package/dist/logicalRoleInference.js.map +1 -1
  252. package/dist/matcherFeedbackUtils.d.ts +2 -2
  253. package/dist/matcherFeedbackUtils.js.map +1 -1
  254. package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
  255. package/dist/ontology-matching.d.ts +1 -1
  256. package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
  257. package/dist/ontologyApproval.d.ts +1 -1
  258. package/dist/ontologyApproval.js +7 -1
  259. package/dist/ontologyApproval.js.map +1 -1
  260. package/dist/ontologyDefinitions.d.ts +14 -24
  261. package/dist/ontologyDefinitions.js +269 -34
  262. package/dist/ontologyDefinitions.js.map +1 -1
  263. package/dist/ontologyHelpers.d.ts +13 -13
  264. package/dist/ontologyHelpers.js.map +1 -1
  265. package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
  266. package/dist/ontologyRegistry.d.ts +1 -1
  267. package/dist/ontologyRegistry.js +34 -6
  268. package/dist/ontologyRegistry.js.map +1 -1
  269. package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
  270. package/dist/projectionReconciliation.d.ts +1 -1
  271. package/dist/projectionReconciliation.js +57 -10
  272. package/dist/projectionReconciliation.js.map +1 -1
  273. package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
  274. package/dist/projectionStaleness.d.ts +1 -1
  275. package/dist/projectionStaleness.js +8 -2
  276. package/dist/projectionStaleness.js.map +1 -1
  277. package/dist/proof-attestation.json +1 -1
  278. package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
  279. package/dist/questionEvidenceLinks.d.ts +1 -1
  280. package/dist/questionEvidenceLinks.js +564 -347
  281. package/dist/questionEvidenceLinks.js.map +1 -1
  282. package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
  283. package/dist/resolverTypes.d.ts +4 -2
  284. package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
  285. package/dist/resolvers.d.ts +5 -3
  286. package/dist/resolvers.js +121 -77
  287. package/dist/resolvers.js.map +1 -1
  288. package/dist/scopeResolverCompat.d.ts +10 -7
  289. package/dist/scopeResolverCompat.js +106 -123
  290. package/dist/scopeResolverCompat.js.map +1 -1
  291. package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
  292. package/dist/text-matching.d.ts +1 -1
  293. package/dist/topicOntologyResolver.d.ts +22 -21
  294. package/dist/topicOntologyResolver.js +54 -32
  295. package/dist/topicOntologyResolver.js.map +1 -1
  296. package/dist/topicProjectOverlay.d.ts +30 -20
  297. package/dist/topicProjectOverlay.js +120 -76
  298. package/dist/topicProjectOverlay.js.map +1 -1
  299. package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
  300. package/dist/topicScope.d.ts +3 -1
  301. package/dist/topicScope.js +104 -119
  302. package/dist/topicScope.js.map +1 -1
  303. package/dist/workflowBridge.d.ts +26 -15
  304. package/dist/workflowBridge.js +140 -144
  305. package/dist/workflowBridge.js.map +1 -1
  306. package/dist/workspaceIsolation.d.ts +14 -12
  307. package/dist/workspaceIsolation.js +108 -122
  308. package/dist/workspaceIsolation.js.map +1 -1
  309. package/package.json +4 -4
  310. package/dist/edges/dependsOn.js.map +0 -1
  311. package/dist/edges/derivedFrom.js.map +0 -1
  312. package/dist/edges/propagationTypes.js.map +0 -1
  313. package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
  314. package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
  315. package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
  316. package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
  317. package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
  318. package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
  319. package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
@@ -1,9 +1,592 @@
1
- import { v } from 'convex/values';
2
- import { requireProjectAccess } from '@lucern/access-control/access';
1
+ import { requireScopeWriteAccess } from '@lucern/access-control/access';
3
2
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
4
- import { componentsGeneric, anyApi, mutationGeneric } from 'convex/server';
3
+ import { v } from 'convex/values';
4
+ import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
5
+ import { componentsGeneric, mutationGeneric } from 'convex/server';
5
6
 
6
7
  // src/epistemicEdges.mutations.ts
8
+ var unsafeApi = unsafeConvexAnyApi(
9
+ "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
10
+ );
11
+ var api = unsafeApi;
12
+ componentsGeneric();
13
+ var internal = unsafeApi;
14
+ var mutation = mutationGeneric;
15
+
16
+ // src/graphTypes.ts
17
+ var EDGE_TYPE_TO_REL = {
18
+ // === THE SIX CANONICAL EPISTEMIC EDGE TYPES ===
19
+ supports: "SUPPORTS",
20
+ // L3↔L3: belief bears on belief (weight -1 to +1)
21
+ informs: "INFORMS",
22
+ // L2→L3: evidence bears on belief
23
+ depends_on: "DEPENDS_ON",
24
+ // L3→L3, Q→Q: structural gate
25
+ derived_from: "DERIVED_FROM",
26
+ // Any→Any: provenance chain (fork, synthesis, extraction, answer)
27
+ contains: "CONTAINS",
28
+ // Any→Any: hierarchy, scoping, membership
29
+ tests: "TESTS",
30
+ // Q→L3: question interrogates belief
31
+ // === L4 DECISION EDGES (derived_from with derivationType=decision) ===
32
+ // Kept as separate Neo4j relationship types for backward compat with L4 queries.
33
+ // New code should use derived_from + metadata.
34
+ based_on_belief: "BASED_ON_BELIEF",
35
+ based_on_question: "BASED_ON_QUESTION",
36
+ blocked_by_contradiction: "BLOCKED_BY_CONTRADICTION",
37
+ informed_by_theme: "INFORMED_BY_THEME",
38
+ // === ONTOLOGICAL EDGES (tenant-extensible, managed by ontology system) ===
39
+ works_at: "WORKS_AT",
40
+ invested_in: "INVESTED_IN",
41
+ competes_with: "COMPETES_WITH",
42
+ participates_in: "PARTICIPATES_IN",
43
+ founded_by: "FOUNDED_BY",
44
+ evaluates: "EVALUATES",
45
+ performs: "PERFORMS",
46
+ function_in: "FUNCTION_IN",
47
+ impacts: "IMPACTS",
48
+ raised_from: "RAISED_FROM",
49
+ mentioned_in: "MENTIONED_IN",
50
+ perspective_on: "PERSPECTIVE_ON",
51
+ about_entity: "ABOUT_ENTITY",
52
+ entity_referenced_in: "ENTITY_REFERENCED_IN"
53
+ };
54
+ function getNodeLayer(nodeType) {
55
+ const L4_TYPES = ["decision"];
56
+ const L3_TYPES = ["belief", "question", "theme", "deal"];
57
+ const L2_TYPES = ["claim", "evidence", "synthesis", "answer"];
58
+ const L1_TYPES = ["atomic_fact", "excerpt", "source"];
59
+ const ONTOLOGICAL_TYPES = [
60
+ "company",
61
+ "person",
62
+ "investor",
63
+ "function",
64
+ "value_chain"
65
+ ];
66
+ const ORGANIZATIONAL_TYPES = ["topic"];
67
+ if (L4_TYPES.includes(nodeType)) {
68
+ return "L4";
69
+ }
70
+ if (L3_TYPES.includes(nodeType)) {
71
+ return "L3";
72
+ }
73
+ if (L2_TYPES.includes(nodeType)) {
74
+ return "L2";
75
+ }
76
+ if (L1_TYPES.includes(nodeType)) {
77
+ return "L1";
78
+ }
79
+ if (ONTOLOGICAL_TYPES.includes(nodeType)) {
80
+ return "ontological";
81
+ }
82
+ if (ORGANIZATIONAL_TYPES.includes(nodeType)) {
83
+ return "organizational";
84
+ }
85
+ console.warn(`[GraphTypes] Unknown nodeType "${nodeType}", defaulting to L2`);
86
+ return "L2";
87
+ }
88
+ var CANONICAL_EPISTEMIC_TYPES = /* @__PURE__ */ new Set([
89
+ "supports",
90
+ "informs",
91
+ "depends_on",
92
+ "derived_from",
93
+ "contains",
94
+ "tests"
95
+ ]);
96
+ function isDeprecatedEdgeType(edgeType) {
97
+ if (CANONICAL_EPISTEMIC_TYPES.has(edgeType)) {
98
+ return false;
99
+ }
100
+ if (edgeType in EDGE_TYPE_TO_REL) {
101
+ return false;
102
+ }
103
+ return true;
104
+ }
105
+
106
+ // src/edgeValidation.ts
107
+ var VALID_LAYER_CONNECTIONS = {
108
+ ontological: /* @__PURE__ */ new Set(["ontological", "L1", "L2", "L3"]),
109
+ L1: /* @__PURE__ */ new Set(["L1", "L2"]),
110
+ L2: /* @__PURE__ */ new Set(["L1", "L2", "L3", "ontological"]),
111
+ L3: /* @__PURE__ */ new Set(["L2", "L3", "L4", "ontological", "organizational"]),
112
+ L4: /* @__PURE__ */ new Set(["L3", "L4"]),
113
+ organizational: /* @__PURE__ */ new Set(["organizational", "L3"])
114
+ };
115
+ function getLayerDepth(layer) {
116
+ switch (layer) {
117
+ case "L4":
118
+ return 4;
119
+ case "L3":
120
+ return 3;
121
+ case "L2":
122
+ return 2;
123
+ case "L1":
124
+ return 1;
125
+ case "ontological":
126
+ return 0;
127
+ default:
128
+ return -1;
129
+ }
130
+ }
131
+ function isValidLayerConnection(fromLayer, toLayer) {
132
+ if (!VALID_LAYER_CONNECTIONS[fromLayer].has(toLayer)) {
133
+ return false;
134
+ }
135
+ if (fromLayer === "ontological" || toLayer === "ontological") {
136
+ return true;
137
+ }
138
+ if (fromLayer === "organizational" || toLayer === "organizational") {
139
+ return true;
140
+ }
141
+ const fromDepth = getLayerDepth(fromLayer);
142
+ const toDepth = getLayerDepth(toLayer);
143
+ if (Math.abs(fromDepth - toDepth) > 1) {
144
+ return false;
145
+ }
146
+ return true;
147
+ }
148
+ var EDGE_LAYER_RULES = {
149
+ // === 6 Canonical Epistemic Types ===
150
+ supports: {
151
+ from: ["L3"],
152
+ to: ["L3"],
153
+ description: "Belief bears on Belief (weight: +1 supports, -1 contradicts)"
154
+ },
155
+ informs: {
156
+ from: ["L2"],
157
+ to: ["L3"],
158
+ description: "Evidence -> Belief (L2 -> L3)"
159
+ },
160
+ depends_on: {
161
+ from: ["L3"],
162
+ to: ["L3"],
163
+ description: "Belief B requires Belief A (structural gate)"
164
+ },
165
+ derived_from: {
166
+ from: ["L2", "L3", "L4"],
167
+ to: ["L1", "L2", "L3"],
168
+ description: "A was produced from B (provenance chain)"
169
+ },
170
+ contains: {
171
+ from: ["L3", "L4", "ontological"],
172
+ to: ["L2", "L3", "ontological"],
173
+ description: "A scopes/aggregates B (hierarchy)"
174
+ },
175
+ tests: {
176
+ from: ["L3"],
177
+ to: ["L3"],
178
+ description: "Question -> Belief (L3 -> L3)"
179
+ },
180
+ // === Structural / Lifecycle ===
181
+ supersedes: {
182
+ from: ["L3"],
183
+ to: ["L3"],
184
+ description: "NewNode -> OldNode (fork lineage)"
185
+ },
186
+ responds_to: {
187
+ from: ["L2", "L3"],
188
+ to: ["L3"],
189
+ description: "Answer -> Question (L2/L3 -> L3)"
190
+ },
191
+ belongs_to: {
192
+ from: ["L2", "L3", "ontological"],
193
+ to: ["L3"],
194
+ description: "Membership (migrating to contains)"
195
+ },
196
+ relates_to_thesis: {
197
+ from: ["L3"],
198
+ to: ["L3"],
199
+ description: "Belief -> Theme (L3 -> L3)"
200
+ },
201
+ // === Ontological (entity-entity or entity-epistemic bridge) ===
202
+ works_at: {
203
+ from: ["ontological"],
204
+ to: ["ontological"],
205
+ description: "Person -> Company"
206
+ },
207
+ invested_in: {
208
+ from: ["ontological"],
209
+ to: ["ontological"],
210
+ description: "Investor -> Company"
211
+ },
212
+ competes_with: {
213
+ from: ["ontological"],
214
+ to: ["ontological"],
215
+ description: "Company -> Company"
216
+ },
217
+ participates_in: {
218
+ from: ["ontological"],
219
+ to: ["ontological"],
220
+ description: "Company -> ValueChain"
221
+ },
222
+ founded_by: {
223
+ from: ["ontological"],
224
+ to: ["ontological"],
225
+ description: "Company -> Person"
226
+ },
227
+ evaluates: {
228
+ from: ["ontological"],
229
+ to: ["ontological"],
230
+ description: "Deal -> Company"
231
+ },
232
+ performs: {
233
+ from: ["ontological"],
234
+ to: ["ontological"],
235
+ description: "Company -> Function"
236
+ },
237
+ function_in: {
238
+ from: ["ontological"],
239
+ to: ["ontological"],
240
+ description: "Function -> ValueChain"
241
+ },
242
+ impacts: {
243
+ from: ["ontological", "L3"],
244
+ to: ["ontological"],
245
+ description: "Theme/Entity -> ValueChain"
246
+ },
247
+ raised_from: {
248
+ from: ["ontological"],
249
+ to: ["ontological"],
250
+ description: "Company -> Investor"
251
+ },
252
+ mentioned_in: {
253
+ from: ["ontological"],
254
+ to: ["L1", "L2"],
255
+ description: "Entity -> Source/Evidence"
256
+ },
257
+ perspective_on: {
258
+ from: ["ontological"],
259
+ to: ["L3"],
260
+ description: "Person -> Belief/Theme"
261
+ },
262
+ plays_theme: {
263
+ from: ["ontological"],
264
+ to: ["L3"],
265
+ description: "Deal -> Theme"
266
+ },
267
+ // C2-RR.4 — storage migration alias + the remaining 55 reachable edge types.
268
+ // Mirrors the kernel rule table
269
+ // (packages/reasoning-kernel/src/adapters/lib/edgeValidation.ts) so this
270
+ // graph-primitives write path admits the same public edge vocabulary. See the
271
+ // kernel file for the per-group rationale.
272
+ extracted_from: {
273
+ from: ["L2", "L3", "L4"],
274
+ to: ["L1", "L2", "L3"],
275
+ description: "Legacy storage migration alias for derived_from; public writes use derived_from"
276
+ },
277
+ qualifies: {
278
+ from: ["L2", "L3"],
279
+ to: ["L3"],
280
+ description: "Evidence/Belief qualifies a Belief"
281
+ },
282
+ contradicts: {
283
+ from: ["L2", "L3"],
284
+ to: ["L3"],
285
+ description: "Evidence/Belief contradicts a Belief"
286
+ },
287
+ reinforces: {
288
+ from: ["L2", "L3"],
289
+ to: ["L3"],
290
+ description: "Evidence/Belief reinforces a Belief"
291
+ },
292
+ corroborates: {
293
+ from: ["L2", "L3"],
294
+ to: ["L3"],
295
+ description: "Independent evidence/belief corroborates a Belief"
296
+ },
297
+ strengthened_by: {
298
+ from: ["L3"],
299
+ to: ["L2", "L3"],
300
+ description: "Belief is strengthened by Evidence/Belief"
301
+ },
302
+ weakened_by: {
303
+ from: ["L3"],
304
+ to: ["L2", "L3"],
305
+ description: "Belief is weakened by Evidence/Belief"
306
+ },
307
+ validated_by: {
308
+ from: ["L3"],
309
+ to: ["L2", "L3"],
310
+ description: "Belief is validated by Evidence/Belief"
311
+ },
312
+ falsified_by: {
313
+ from: ["L3"],
314
+ to: ["L2", "L3"],
315
+ description: "Belief is falsified by Evidence/Belief"
316
+ },
317
+ amplifies: {
318
+ from: ["L3"],
319
+ to: ["L3"],
320
+ description: "Belief amplifies another Belief"
321
+ },
322
+ precondition_for: {
323
+ from: ["L3"],
324
+ to: ["L3"],
325
+ description: "Belief is a precondition for another Belief"
326
+ },
327
+ prerequisite_for: {
328
+ from: ["L3"],
329
+ to: ["L3"],
330
+ description: "Belief is a prerequisite for another Belief"
331
+ },
332
+ required_for: {
333
+ from: ["L3"],
334
+ to: ["L3"],
335
+ description: "Belief is required for another Belief"
336
+ },
337
+ in_tension_with: {
338
+ from: ["L3"],
339
+ to: ["L3"],
340
+ description: "Belief is in tension with another Belief"
341
+ },
342
+ mutually_exclusive: {
343
+ from: ["L3"],
344
+ to: ["L3"],
345
+ description: "Beliefs cannot both hold"
346
+ },
347
+ exclusive_with: {
348
+ from: ["L3"],
349
+ to: ["L3"],
350
+ description: "Belief is exclusive with another Belief"
351
+ },
352
+ alternative_to: {
353
+ from: ["L3"],
354
+ to: ["L3"],
355
+ description: "Belief is an alternative to another Belief"
356
+ },
357
+ subsumes: {
358
+ from: ["L3"],
359
+ to: ["L3"],
360
+ description: "Belief subsumes a narrower Belief"
361
+ },
362
+ extends: {
363
+ from: ["L3"],
364
+ to: ["L3"],
365
+ description: "Belief extends another Belief"
366
+ },
367
+ refines: {
368
+ from: ["L3"],
369
+ to: ["L3"],
370
+ description: "Belief refines another Belief"
371
+ },
372
+ implements: {
373
+ from: ["L3"],
374
+ to: ["L3"],
375
+ description: "Belief implements an abstract Belief"
376
+ },
377
+ violates: {
378
+ from: ["L3"],
379
+ to: ["L3"],
380
+ description: "Belief violates a constraint Belief"
381
+ },
382
+ assumes: {
383
+ from: ["L3"],
384
+ to: ["L3"],
385
+ description: "Belief assumes another Belief"
386
+ },
387
+ would_predict: {
388
+ from: ["L3"],
389
+ to: ["L3"],
390
+ description: "Belief would predict another Belief"
391
+ },
392
+ analogous_to: {
393
+ from: ["L3"],
394
+ to: ["L3"],
395
+ description: "Belief is analogous to another Belief"
396
+ },
397
+ independent_of: {
398
+ from: ["L3"],
399
+ to: ["L3"],
400
+ description: "Belief is independent of another Belief"
401
+ },
402
+ correlates_with: {
403
+ from: ["L3"],
404
+ to: ["L3"],
405
+ description: "Belief correlates with another Belief"
406
+ },
407
+ co_changes_with: {
408
+ from: ["L3"],
409
+ to: ["L3"],
410
+ description: "Belief co-changes with another Belief"
411
+ },
412
+ counterfactual_of: {
413
+ from: ["L3"],
414
+ to: ["L3"],
415
+ description: "Belief is a counterfactual of another Belief"
416
+ },
417
+ parallel_to: {
418
+ from: ["L3"],
419
+ to: ["L3"],
420
+ description: "Belief runs parallel to another Belief"
421
+ },
422
+ cascade_from: {
423
+ from: ["L3"],
424
+ to: ["L3"],
425
+ description: "Cascade from an upstream Belief"
426
+ },
427
+ cascade_to: {
428
+ from: ["L3"],
429
+ to: ["L3"],
430
+ description: "Cascade to a downstream Belief"
431
+ },
432
+ collapses_if: {
433
+ from: ["L3"],
434
+ to: ["L3"],
435
+ description: "Belief collapses if another fails"
436
+ },
437
+ branches_from: {
438
+ from: ["L3"],
439
+ to: ["L3"],
440
+ description: "Belief branches from an ancestor Belief"
441
+ },
442
+ same_as: {
443
+ from: ["L2", "L3", "ontological"],
444
+ to: ["L2", "L3", "ontological"],
445
+ description: "Two nodes are the same entity"
446
+ },
447
+ answers: {
448
+ from: ["L2", "L3"],
449
+ to: ["L3"],
450
+ description: "Answer/Belief answers a Question"
451
+ },
452
+ partially_answers: {
453
+ from: ["L2", "L3"],
454
+ to: ["L3"],
455
+ description: "Answer/Belief partially answers a Question"
456
+ },
457
+ explores: {
458
+ from: ["L3"],
459
+ to: ["L3"],
460
+ description: "Question explores a Belief/Theme"
461
+ },
462
+ informed_by_theme: {
463
+ from: ["L3"],
464
+ to: ["L3"],
465
+ description: "Belief is informed by a Theme"
466
+ },
467
+ same_theme_as: {
468
+ from: ["L3"],
469
+ to: ["L3"],
470
+ description: "Two Beliefs share a Theme"
471
+ },
472
+ based_on: {
473
+ from: ["L4"],
474
+ to: ["L3"],
475
+ description: "Decision is based on a Belief/Question"
476
+ },
477
+ based_on_belief: {
478
+ from: ["L4"],
479
+ to: ["L3"],
480
+ description: "Decision is based on a Belief"
481
+ },
482
+ based_on_question: {
483
+ from: ["L4"],
484
+ to: ["L3"],
485
+ description: "Decision is based on a Question"
486
+ },
487
+ blocked_by_contradiction: {
488
+ from: ["L4"],
489
+ to: ["L3"],
490
+ description: "Decision is blocked by a Contradiction"
491
+ },
492
+ parent_of: {
493
+ from: ["L3", "L4", "ontological", "organizational"],
494
+ to: ["L2", "L3", "ontological", "organizational"],
495
+ description: "A is the parent of B"
496
+ },
497
+ child_of: {
498
+ from: ["L2", "L3", "ontological", "organizational"],
499
+ to: ["L3", "L4", "ontological", "organizational"],
500
+ description: "A is the child of B"
501
+ },
502
+ scoped_by: {
503
+ from: ["L2", "L3"],
504
+ to: ["L3", "organizational"],
505
+ description: "Object is scoped by a Topic/Theme"
506
+ },
507
+ cites: {
508
+ from: ["L2", "L3"],
509
+ to: ["L1", "L2"],
510
+ description: "Evidence/Belief cites a Source/Excerpt"
511
+ },
512
+ summarizes: {
513
+ from: ["L2", "L3"],
514
+ to: ["L1", "L2"],
515
+ description: "Synthesis/Evidence summarizes a Source/Evidence"
516
+ },
517
+ same_source_as: {
518
+ from: ["L1", "L2"],
519
+ to: ["L1", "L2"],
520
+ description: "Two nodes derive from the same Source"
521
+ },
522
+ migrating_from: {
523
+ from: ["L2", "L3", "L4"],
524
+ to: ["L1", "L2", "L3"],
525
+ description: "Migration lineage: from an ancestor"
526
+ },
527
+ migrating_to: {
528
+ from: ["L1", "L2", "L3"],
529
+ to: ["L2", "L3", "L4"],
530
+ description: "Migration lineage: to a successor"
531
+ },
532
+ about_entity: {
533
+ from: ["L2", "L3"],
534
+ to: ["ontological"],
535
+ description: "Belief/Evidence is about an Entity"
536
+ },
537
+ entity_referenced_in: {
538
+ from: ["ontological"],
539
+ to: ["L1", "L2"],
540
+ description: "Entity is referenced in a Source/Evidence"
541
+ },
542
+ related_to: {
543
+ from: ["L2", "L3", "ontological", "organizational"],
544
+ to: ["L2", "L3", "ontological", "organizational"],
545
+ description: "Lateral adjacency; no confidence pressure"
546
+ },
547
+ blocks: {
548
+ from: ["L3", "L4"],
549
+ to: ["L3", "L4"],
550
+ description: "A blocks B (structural gate)"
551
+ }
552
+ };
553
+ function validateEdgeLayers(edgeType, fromLayer, toLayer) {
554
+ const rules = EDGE_LAYER_RULES[edgeType];
555
+ if (!rules) {
556
+ console.warn(
557
+ `[EdgeValidation] Unknown edge type: ${edgeType}, allowing by default`
558
+ );
559
+ return { valid: true };
560
+ }
561
+ if (edgeType === "supersedes") {
562
+ if (fromLayer !== toLayer) {
563
+ return {
564
+ valid: false,
565
+ reason: `${edgeType} edges must be between nodes of the same layer. Got ${fromLayer} -> ${toLayer}`
566
+ };
567
+ }
568
+ return { valid: true };
569
+ }
570
+ if (!rules.from.includes(fromLayer)) {
571
+ return {
572
+ valid: false,
573
+ reason: `Edge type '${edgeType}' does not allow source layer ${fromLayer}. Allowed: ${rules.from.join(", ")}`
574
+ };
575
+ }
576
+ if (!rules.to.includes(toLayer)) {
577
+ return {
578
+ valid: false,
579
+ reason: `Edge type '${edgeType}' does not allow target layer ${toLayer}. Allowed: ${rules.to.join(", ")}`
580
+ };
581
+ }
582
+ if (!isValidLayerConnection(fromLayer, toLayer)) {
583
+ return {
584
+ valid: false,
585
+ reason: `Layer transition ${fromLayer} -> ${toLayer} is not permitted`
586
+ };
587
+ }
588
+ return { valid: true };
589
+ }
7
590
  v.union(
8
591
  v.literal("L4"),
9
592
  v.literal("L3"),
@@ -107,96 +690,6 @@ function buildEdgeNotFoundResult() {
107
690
  return result;
108
691
  }
109
692
 
110
- // src/graphTypes.ts
111
- var EDGE_TYPE_TO_REL = {
112
- // === THE SIX CANONICAL EPISTEMIC EDGE TYPES ===
113
- supports: "SUPPORTS",
114
- // L3↔L3: belief bears on belief (weight -1 to +1)
115
- informs: "INFORMS",
116
- // L2→L3: evidence bears on belief
117
- depends_on: "DEPENDS_ON",
118
- // L3→L3, Q→Q: structural gate
119
- derived_from: "DERIVED_FROM",
120
- // Any→Any: provenance chain (fork, synthesis, extraction, answer)
121
- contains: "CONTAINS",
122
- // Any→Any: hierarchy, scoping, membership
123
- tests: "TESTS",
124
- // Q→L3: question interrogates belief
125
- // === L4 DECISION EDGES (derived_from with derivationType=decision) ===
126
- // Kept as separate Neo4j relationship types for backward compat with L4 queries.
127
- // New code should use derived_from + metadata.
128
- based_on_belief: "BASED_ON_BELIEF",
129
- based_on_question: "BASED_ON_QUESTION",
130
- blocked_by_contradiction: "BLOCKED_BY_CONTRADICTION",
131
- informed_by_theme: "INFORMED_BY_THEME",
132
- // === ONTOLOGICAL EDGES (tenant-extensible, managed by ontology system) ===
133
- works_at: "WORKS_AT",
134
- invested_in: "INVESTED_IN",
135
- competes_with: "COMPETES_WITH",
136
- participates_in: "PARTICIPATES_IN",
137
- founded_by: "FOUNDED_BY",
138
- evaluates: "EVALUATES",
139
- performs: "PERFORMS",
140
- function_in: "FUNCTION_IN",
141
- impacts: "IMPACTS",
142
- raised_from: "RAISED_FROM",
143
- mentioned_in: "MENTIONED_IN",
144
- perspective_on: "PERSPECTIVE_ON",
145
- about_entity: "ABOUT_ENTITY",
146
- entity_referenced_in: "ENTITY_REFERENCED_IN"
147
- };
148
- function getNodeLayer(nodeType) {
149
- const L4_TYPES = ["decision"];
150
- const L3_TYPES = ["belief", "question", "theme", "deal"];
151
- const L2_TYPES = ["claim", "evidence", "synthesis", "answer"];
152
- const L1_TYPES = ["atomic_fact", "excerpt", "source"];
153
- const ONTOLOGICAL_TYPES = [
154
- "company",
155
- "person",
156
- "investor",
157
- "function",
158
- "value_chain"
159
- ];
160
- const ORGANIZATIONAL_TYPES = ["topic"];
161
- if (L4_TYPES.includes(nodeType)) {
162
- return "L4";
163
- }
164
- if (L3_TYPES.includes(nodeType)) {
165
- return "L3";
166
- }
167
- if (L2_TYPES.includes(nodeType)) {
168
- return "L2";
169
- }
170
- if (L1_TYPES.includes(nodeType)) {
171
- return "L1";
172
- }
173
- if (ONTOLOGICAL_TYPES.includes(nodeType)) {
174
- return "ontological";
175
- }
176
- if (ORGANIZATIONAL_TYPES.includes(nodeType)) {
177
- return "organizational";
178
- }
179
- console.warn(`[GraphTypes] Unknown nodeType "${nodeType}", defaulting to L2`);
180
- return "L2";
181
- }
182
- var CANONICAL_EPISTEMIC_TYPES = /* @__PURE__ */ new Set([
183
- "supports",
184
- "informs",
185
- "depends_on",
186
- "derived_from",
187
- "contains",
188
- "tests"
189
- ]);
190
- function isDeprecatedEdgeType(edgeType) {
191
- if (CANONICAL_EPISTEMIC_TYPES.has(edgeType)) return false;
192
- if (edgeType in EDGE_TYPE_TO_REL) return false;
193
- return true;
194
- }
195
- var api = anyApi;
196
- componentsGeneric();
197
- var internal = anyApi;
198
- var mutation = mutationGeneric;
199
-
200
693
  // src/debug.ts
201
694
  function isGraphPrimitiveDebugEnabled() {
202
695
  const env = globalThis.process?.env;
@@ -227,6 +720,10 @@ function readStringArray(value) {
227
720
  function readMetadata(topic) {
228
721
  return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
229
722
  }
723
+ function omitMetadataKey(metadata, key) {
724
+ const { [key]: _omitted, ...rest } = metadata;
725
+ return rest;
726
+ }
230
727
  function readLegacyProjectId(value) {
231
728
  if (!value) {
232
729
  return;
@@ -307,9 +804,12 @@ async function resolveTopicDoc(ctx, scopeId) {
307
804
  );
308
805
  }
309
806
  try {
310
- const topic = await ctx.runQuery(api.topics.getByLegacyScopeId, {
311
- projectId: String(scopeId)
312
- });
807
+ const topic = await ctx.runQuery(
808
+ api.topics.getByLegacyScopeId,
809
+ {
810
+ projectId: String(scopeId)
811
+ }
812
+ );
313
813
  if (topic?.name !== void 0 && topic?.type !== void 0) {
314
814
  return topic;
315
815
  }
@@ -329,8 +829,18 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
329
829
  const outwardId = idMode === "topic" ? topicId : storageProjectId;
330
830
  const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
331
831
  const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
332
- const createdAt = typeof topic.createdAt === "number" ? topic.createdAt : typeof topic._creationTime === "number" ? topic._creationTime : 0;
333
- const updatedAt = typeof topic.updatedAt === "number" ? topic.updatedAt : typeof metadata.updatedAt === "number" ? metadata.updatedAt : createdAt;
832
+ let createdAt = 0;
833
+ if (typeof topic.createdAt === "number") {
834
+ createdAt = topic.createdAt;
835
+ } else if (typeof topic._creationTime === "number") {
836
+ createdAt = topic._creationTime;
837
+ }
838
+ let updatedAt = createdAt;
839
+ if (typeof topic.updatedAt === "number") {
840
+ updatedAt = topic.updatedAt;
841
+ } else if (typeof metadata.updatedAt === "number") {
842
+ updatedAt = metadata.updatedAt;
843
+ }
334
844
  return {
335
845
  ...metadata,
336
846
  _id: outwardId,
@@ -399,90 +909,113 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
399
909
  if (!topic) {
400
910
  return null;
401
911
  }
402
- const nextMetadata = { ...readMetadata(topic) };
403
- const patch = {};
404
- const topicUpdateArgs = {
405
- id: String(topic._id)
912
+ const plan = buildTopicProjectOverlayPatchPlan(topic, value);
913
+ await applyTopicProjectOverlayPatch(ctx, topic, plan);
914
+ return materializeTopicProjectOverlay({
915
+ ...topic,
916
+ ...plan.patch,
917
+ metadata: plan.nextMetadata
918
+ });
919
+ }
920
+ function buildTopicProjectOverlayPatchPlan(topic, value) {
921
+ const plan = {
922
+ nextMetadata: { ...readMetadata(topic) },
923
+ patch: {},
924
+ topicUpdateArgs: {
925
+ id: String(topic._id)
926
+ }
406
927
  };
407
928
  for (const [key, rawValue] of Object.entries(value)) {
408
- switch (key) {
409
- case "_id":
410
- case "projectId":
411
- case "topicId":
412
- case "legacyProjectId":
413
- case "storageProjectId":
414
- break;
415
- case "name":
416
- case "description":
417
- patch[key] = rawValue;
418
- topicUpdateArgs[key] = rawValue;
419
- break;
420
- case "tenantId":
421
- case "workspaceId":
422
- case "ownerId":
423
- throw new Error(
424
- `patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
425
- );
426
- case "status": {
427
- const status = coerceStatus(rawValue);
428
- if (status) {
429
- patch.status = status;
430
- topicUpdateArgs.status = status;
431
- }
432
- break;
433
- }
434
- case "visibility": {
435
- const visibility = coerceVisibility(rawValue);
436
- if (visibility) {
437
- patch.visibility = visibility;
438
- topicUpdateArgs.visibility = visibility;
439
- }
440
- break;
441
- }
442
- case "type": {
443
- const projectType = readNonEmptyString(rawValue);
444
- if (projectType) {
445
- nextMetadata.projectType = projectType;
446
- } else {
447
- delete nextMetadata.projectType;
448
- }
449
- break;
450
- }
451
- case "updatedAt":
452
- case "createdAt":
453
- break;
454
- default:
455
- if (rawValue === void 0) {
456
- delete nextMetadata[key];
457
- } else {
458
- nextMetadata[key] = rawValue;
459
- }
460
- }
929
+ applyTopicProjectOverlayPatchEntry(plan, key, rawValue);
930
+ }
931
+ plan.patch.updatedAt = Date.now();
932
+ plan.patch.metadata = plan.nextMetadata;
933
+ plan.topicUpdateArgs.metadata = plan.nextMetadata;
934
+ return plan;
935
+ }
936
+ function applyTopicProjectOverlayPatchEntry(plan, key, rawValue) {
937
+ switch (key) {
938
+ case "_id":
939
+ case "projectId":
940
+ case "topicId":
941
+ case "legacyProjectId":
942
+ case "storageProjectId":
943
+ case "updatedAt":
944
+ case "createdAt":
945
+ return;
946
+ case "name":
947
+ case "description":
948
+ plan.patch[key] = rawValue;
949
+ plan.topicUpdateArgs[key] = rawValue;
950
+ return;
951
+ case "tenantId":
952
+ case "workspaceId":
953
+ case "ownerId":
954
+ throw new Error(
955
+ `patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
956
+ );
957
+ case "status":
958
+ applyTopicStatusPatch(plan, rawValue);
959
+ return;
960
+ case "visibility":
961
+ applyTopicVisibilityPatch(plan, rawValue);
962
+ return;
963
+ case "type":
964
+ applyTopicProjectTypePatch(plan, rawValue);
965
+ return;
966
+ default:
967
+ applyTopicMetadataPatch(plan, key, rawValue);
968
+ }
969
+ }
970
+ function applyTopicStatusPatch(plan, rawValue) {
971
+ const status = coerceStatus(rawValue);
972
+ if (status) {
973
+ plan.patch.status = status;
974
+ plan.topicUpdateArgs.status = status;
975
+ }
976
+ }
977
+ function applyTopicVisibilityPatch(plan, rawValue) {
978
+ const visibility = coerceVisibility(rawValue);
979
+ if (visibility) {
980
+ plan.patch.visibility = visibility;
981
+ plan.topicUpdateArgs.visibility = visibility;
982
+ }
983
+ }
984
+ function applyTopicProjectTypePatch(plan, rawValue) {
985
+ const projectType = readNonEmptyString(rawValue);
986
+ if (projectType) {
987
+ plan.nextMetadata.projectType = projectType;
988
+ return;
461
989
  }
462
- patch.updatedAt = Date.now();
463
- patch.metadata = nextMetadata;
464
- topicUpdateArgs.metadata = nextMetadata;
990
+ plan.nextMetadata = omitMetadataKey(plan.nextMetadata, "projectType");
991
+ }
992
+ function applyTopicMetadataPatch(plan, key, rawValue) {
993
+ if (rawValue === void 0) {
994
+ plan.nextMetadata = omitMetadataKey(plan.nextMetadata, key);
995
+ return;
996
+ }
997
+ plan.nextMetadata[key] = rawValue;
998
+ }
999
+ async function applyTopicProjectOverlayPatch(ctx, topic, plan) {
465
1000
  if (typeof ctx.runMutation === "function") {
466
1001
  try {
467
- await ctx.runMutation(api.topics.update, topicUpdateArgs);
1002
+ await ctx.runMutation(api.topics.update, plan.topicUpdateArgs);
468
1003
  } catch (error) {
469
- if (!isMissingLucernChildComponentError(error) || !ctx?.db || typeof ctx.db.patch !== "function") {
1004
+ if (!canPatchTopicViaLocalDb(ctx, error)) {
470
1005
  throw error;
471
1006
  }
472
- await ctx.db.patch(String(topic._id), patch);
1007
+ await ctx.db.patch(topic._id, plan.patch);
473
1008
  }
474
1009
  } else if (ctx?.db && typeof ctx.db.patch === "function") {
475
- await ctx.db.patch(String(topic._id), patch);
1010
+ await ctx.db.patch(topic._id, plan.patch);
476
1011
  } else {
477
1012
  throw new Error(
478
1013
  "Cannot patch topic without component adapter (ctx.runMutation unavailable)"
479
1014
  );
480
1015
  }
481
- return materializeTopicProjectOverlay({
482
- ...topic,
483
- ...patch,
484
- metadata: nextMetadata
485
- });
1016
+ }
1017
+ function canPatchTopicViaLocalDb(ctx, error) {
1018
+ return isMissingLucernChildComponentError(error) && Boolean(ctx?.db) && typeof ctx.db?.patch === "function";
486
1019
  }
487
1020
 
488
1021
  // src/resolvers.ts
@@ -510,7 +1043,7 @@ async function patchProjectWithTolerance(ctx, projectId, value) {
510
1043
  try {
511
1044
  await patchTopicProjectOverlay(ctx, projectId, value);
512
1045
  } catch (error) {
513
- if (!isAdvisoryTopicPatch(value) || !isMissingLucernChildComponentError2(error)) {
1046
+ if (!(isAdvisoryTopicPatch(value) && isMissingLucernChildComponentError2(error))) {
514
1047
  throw error;
515
1048
  }
516
1049
  console.warn(
@@ -577,13 +1110,15 @@ function asMappedProjectId(topic) {
577
1110
  if (!topic) {
578
1111
  return;
579
1112
  }
580
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD2]);
1113
+ const directLegacyProjectId = normalizeScopeValue(
1114
+ topic[LEGACY_SCOPE_FIELD2]
1115
+ );
581
1116
  if (directLegacyProjectId) {
582
1117
  return directLegacyProjectId;
583
1118
  }
584
1119
  const metadata = topic.metadata || {};
585
1120
  const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
586
- return candidate ? candidate : void 0;
1121
+ return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
587
1122
  }
588
1123
  function normalizeScopeValue(value) {
589
1124
  if (typeof value !== "string") {
@@ -608,8 +1143,9 @@ function pickPrimaryTopic(candidates) {
608
1143
  })[0];
609
1144
  }
610
1145
  async function findTopicsByScopeAlias(ctx, scopeId) {
1146
+ const query = ctx.db.query("topics");
611
1147
  try {
612
- return await ctx.db.query("topics").withIndex(
1148
+ return await query.withIndex(
613
1149
  "by_graph_scope_project",
614
1150
  (q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
615
1151
  ).collect();
@@ -621,7 +1157,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
621
1157
  scopeId
622
1158
  }
623
1159
  );
624
- const topics = await ctx.db.query("topics").collect();
1160
+ const topics = await query.collect();
625
1161
  return topics.filter((topic) => {
626
1162
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
627
1163
  const mappedProjectId = asMappedProjectId(topic);
@@ -677,424 +1213,253 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
677
1213
  let current = topic;
678
1214
  for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
679
1215
  current = await ctx.db.get(current.parentTopicId);
680
- if (!current) break;
1216
+ if (!current) {
1217
+ break;
1218
+ }
681
1219
  if (!tenantId) {
682
1220
  tenantId = normalizeScopeValue(current.tenantId);
683
1221
  }
684
1222
  if (!workspaceId) {
685
1223
  workspaceId = normalizeScopeValue(current.workspaceId);
686
1224
  }
687
- if (tenantId && workspaceId) break;
1225
+ if (tenantId && workspaceId) {
1226
+ break;
1227
+ }
688
1228
  }
689
1229
  return { tenantId, workspaceId };
690
1230
  }
691
1231
  async function resolveTopicProjectScope(ctx, args) {
692
1232
  if (args.topicId) {
693
- let topic = null;
694
- try {
695
- topic = await ctx.db.get(
696
- args.topicId
697
- );
698
- } catch (error) {
699
- debugGraphPrimitiveFallback(
700
- "[topicScope] Failed to load topic by direct id",
701
- {
702
- error,
703
- topicId: args.topicId
704
- }
705
- );
706
- }
707
- if (!topic) {
708
- topic = await tryResolveHostTopicById(ctx, String(args.topicId));
709
- }
710
- if (!topic) {
711
- topic = pickPrimaryTopic(
712
- await findTopicsByScopeAlias(ctx, String(args.topicId))
713
- ) ?? null;
714
- }
715
- if (!topic) {
716
- const nodeScope = await resolveTopicNodeScopeOrNull(
717
- ctx,
718
- String(args.topicId)
719
- );
720
- if (nodeScope) {
721
- return nodeScope;
722
- }
723
- throw new Error(`Topic not found: ${String(args.topicId)}`);
724
- }
725
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
726
- const mapped = asMappedProjectId(topic);
727
- if (mapped) {
728
- return {
729
- topicId: topic._id,
730
- projectId: mapped,
731
- tenantId: inherited.tenantId,
732
- workspaceId: inherited.workspaceId,
733
- source: "topic"
734
- };
735
- }
736
- return {
737
- topicId: topic._id,
738
- tenantId: inherited.tenantId,
739
- workspaceId: inherited.workspaceId,
740
- source: "topic"
741
- };
1233
+ return await resolveScopeFromTopicId(ctx, args.topicId);
742
1234
  }
743
1235
  if (args.projectId) {
744
- let directTopic = null;
745
- try {
746
- directTopic = await ctx.db.get(
747
- args.projectId
748
- );
749
- } catch (error) {
750
- debugGraphPrimitiveFallback(
751
- "[topicScope] Failed to load direct project topic",
752
- {
753
- error,
754
- projectId: args.projectId
755
- }
756
- );
757
- }
758
- if (directTopic) {
759
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
760
- const mapped = asMappedProjectId(directTopic);
761
- return {
762
- topicId: directTopic._id,
763
- projectId: mapped ?? args.projectId,
764
- tenantId: inherited.tenantId,
765
- workspaceId: inherited.workspaceId,
766
- source: "topic_inferred"
767
- };
768
- }
769
- directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
770
- if (directTopic) {
771
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
772
- const mapped = asMappedProjectId(directTopic);
773
- return {
774
- topicId: directTopic._id,
775
- projectId: mapped ?? args.projectId,
776
- tenantId: inherited.tenantId,
777
- workspaceId: inherited.workspaceId,
778
- source: "topic_inferred"
779
- };
780
- }
781
- const topics = await findTopicsByScopeAlias(ctx, args.projectId);
782
- const primary = pickPrimaryTopic(topics);
783
- if (primary) {
784
- const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
785
- return {
786
- topicId: primary._id,
787
- projectId: args.projectId,
788
- tenantId: inherited.tenantId,
789
- workspaceId: inherited.workspaceId,
790
- source: "project_mapped_topic"
791
- };
792
- }
793
- const nodeScope = await resolveTopicNodeScopeOrNull(
794
- ctx,
795
- String(args.projectId)
796
- );
797
- if (nodeScope) {
798
- return {
799
- ...nodeScope,
800
- projectId: nodeScope.projectId ?? String(args.projectId)
801
- };
802
- }
803
- throw new Error(
804
- `Legacy project scope ${String(args.projectId)} has no mapped topic.`
805
- );
1236
+ return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
1237
+ }
1238
+ throw new Error(
1239
+ "Missing scope: provide topicId (preferred) or legacy projectId alias."
1240
+ );
1241
+ }
1242
+ async function resolveScopeFromTopicId(ctx, topicId) {
1243
+ const topic = await resolveTopicDocFromTopicId(ctx, topicId);
1244
+ if (topic) {
1245
+ return await buildTopicScope(ctx, topic, "topic");
1246
+ }
1247
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
1248
+ if (nodeScope) {
1249
+ return nodeScope;
1250
+ }
1251
+ throw new Error(`Topic not found: ${String(topicId)}`);
1252
+ }
1253
+ async function resolveTopicDocFromTopicId(ctx, topicId) {
1254
+ const direct = await tryReadTopicDoc(ctx, topicId, {
1255
+ failureLog: "[topicScope] Failed to load topic by direct id",
1256
+ idLogKey: "topicId"
1257
+ });
1258
+ if (direct) {
1259
+ return direct;
1260
+ }
1261
+ const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
1262
+ if (hostTopic) {
1263
+ return hostTopic;
1264
+ }
1265
+ return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
1266
+ }
1267
+ async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
1268
+ const directTopic = await resolveDirectLegacyProjectTopic(
1269
+ ctx,
1270
+ legacyProjectId
1271
+ );
1272
+ if (directTopic) {
1273
+ return await buildTopicScope(ctx, directTopic, "topic_inferred", {
1274
+ fallbackProjectId: legacyProjectId
1275
+ });
1276
+ }
1277
+ const primary = pickPrimaryTopic(
1278
+ await findTopicsByScopeAlias(ctx, legacyProjectId)
1279
+ );
1280
+ if (primary) {
1281
+ return await buildTopicScope(ctx, primary, "project_mapped_topic", {
1282
+ fallbackProjectId: legacyProjectId
1283
+ });
1284
+ }
1285
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
1286
+ if (nodeScope) {
1287
+ return {
1288
+ ...nodeScope,
1289
+ projectId: nodeScope.projectId ?? legacyProjectId
1290
+ };
806
1291
  }
807
1292
  throw new Error(
808
- "Missing scope: provide topicId (preferred) or legacy projectId alias."
1293
+ `Legacy project scope ${legacyProjectId} has no mapped topic.`
809
1294
  );
810
1295
  }
1296
+ async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
1297
+ const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
1298
+ failureLog: "[topicScope] Failed to load direct project topic",
1299
+ idLogKey: "projectId"
1300
+ });
1301
+ return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
1302
+ }
1303
+ async function tryReadTopicDoc(ctx, id, log) {
1304
+ try {
1305
+ return await ctx.db.get(id);
1306
+ } catch (error) {
1307
+ debugGraphPrimitiveFallback(log.failureLog, {
1308
+ error,
1309
+ [log.idLogKey]: id
1310
+ });
1311
+ return null;
1312
+ }
1313
+ }
1314
+ async function buildTopicScope(ctx, topic, source, options = {}) {
1315
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
1316
+ const mapped = asMappedProjectId(topic);
1317
+ return {
1318
+ topicId: topic._id,
1319
+ ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
1320
+ tenantId: inherited.tenantId,
1321
+ workspaceId: inherited.workspaceId,
1322
+ source
1323
+ };
1324
+ }
811
1325
  var optionalScopeArgs = {
812
1326
  projectId: v.optional(v.string()),
813
1327
  topicId: v.optional(v.string())
814
1328
  };
815
1329
 
816
- // src/edgeValidation.ts
817
- function getLayerDepth(layer) {
818
- switch (layer) {
819
- case "L4":
820
- return 4;
821
- case "L3":
822
- return 3;
823
- case "L2":
824
- return 2;
825
- case "L1":
826
- return 1;
827
- case "ontological":
828
- return 0;
829
- default:
830
- return -1;
831
- }
1330
+ // src/epistemicEdges.mutations.ts
1331
+ var EPISTEMIC_LAYERS = /* @__PURE__ */ new Set([
1332
+ "L4",
1333
+ "L3",
1334
+ "L2",
1335
+ "L1",
1336
+ "ontological",
1337
+ "organizational"
1338
+ ]);
1339
+ function readOptionalString(value) {
1340
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
832
1341
  }
833
- function isValidLayerConnection(fromLayer, toLayer) {
834
- if (fromLayer === toLayer) {
835
- return true;
1342
+ function readOptionalNumber(value) {
1343
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1344
+ }
1345
+ function readConvexId(value) {
1346
+ const normalized = readOptionalString(value);
1347
+ return normalized;
1348
+ }
1349
+ function readRecord(value) {
1350
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1351
+ }
1352
+ function readEpistemicLayer(value) {
1353
+ const layer = readOptionalString(value);
1354
+ return layer && EPISTEMIC_LAYERS.has(layer) ? layer : void 0;
1355
+ }
1356
+ function readEdgeNodeRow(value) {
1357
+ const record = readRecord(value);
1358
+ if (!record) {
1359
+ return null;
836
1360
  }
837
- if (fromLayer === "ontological" && toLayer === "ontological") {
838
- return true;
1361
+ const id = readConvexId(record._id);
1362
+ const globalId = readOptionalString(record.globalId);
1363
+ const nodeType = readOptionalString(record.nodeType);
1364
+ if (!(id && globalId && nodeType)) {
1365
+ return null;
839
1366
  }
840
- if (fromLayer === "ontological" && (toLayer === "L3" || toLayer === "L2" || toLayer === "L1")) {
841
- return true;
1367
+ const node = { _id: id, globalId, nodeType };
1368
+ const epistemicLayer = readEpistemicLayer(record.epistemicLayer);
1369
+ if (epistemicLayer !== void 0) {
1370
+ node.epistemicLayer = epistemicLayer;
842
1371
  }
843
- if ((fromLayer === "L3" || fromLayer === "L2" || fromLayer === "L1") && toLayer === "ontological") {
844
- return true;
1372
+ const projectId = readOptionalString(record.projectId);
1373
+ if (projectId !== void 0) {
1374
+ node.projectId = projectId;
845
1375
  }
846
- if (fromLayer === "L2" && toLayer === "L1") {
847
- return true;
1376
+ return node;
1377
+ }
1378
+ function requireEdgeNodeRow(value, context) {
1379
+ const node = readEdgeNodeRow(value);
1380
+ if (!node) {
1381
+ throw new Error(`${context} requires a canonical epistemic node row.`);
848
1382
  }
849
- if (fromLayer === "L2" && toLayer === "L3") {
850
- return true;
1383
+ return node;
1384
+ }
1385
+ function readEdgeRow(value) {
1386
+ const record = readRecord(value);
1387
+ if (!record) {
1388
+ return null;
851
1389
  }
852
- if (fromLayer === "L3" && toLayer === "L2") {
853
- return true;
1390
+ const id = readConvexId(record._id);
1391
+ const globalId = readOptionalString(record.globalId);
1392
+ const edgeType = readOptionalString(record.edgeType);
1393
+ if (!(id && globalId && edgeType)) {
1394
+ return null;
854
1395
  }
855
- if (fromLayer === "L3" && toLayer === "L4") {
856
- return true;
1396
+ const edge = { _id: id, globalId, edgeType };
1397
+ const createdBy = readOptionalString(record.createdBy);
1398
+ if (createdBy !== void 0) {
1399
+ edge.createdBy = createdBy;
857
1400
  }
858
- if (fromLayer === "L4" && toLayer === "L3") {
859
- return true;
1401
+ const fromNodeId = readOptionalString(record.fromNodeId);
1402
+ if (fromNodeId !== void 0) {
1403
+ edge.fromNodeId = fromNodeId;
860
1404
  }
861
- if (fromLayer === "L3" && toLayer === "organizational") {
862
- return true;
1405
+ const projectId = readOptionalString(record.projectId);
1406
+ if (projectId !== void 0) {
1407
+ edge.projectId = projectId;
863
1408
  }
864
- if (fromLayer === "organizational" && toLayer === "L3") {
865
- return true;
1409
+ const toNodeId = readOptionalString(record.toNodeId);
1410
+ if (toNodeId !== void 0) {
1411
+ edge.toNodeId = toNodeId;
866
1412
  }
867
- const fromDepth = getLayerDepth(fromLayer);
868
- const toDepth = getLayerDepth(toLayer);
869
- if (Math.abs(fromDepth - toDepth) > 1) {
870
- return false;
1413
+ const confidence = readOptionalNumber(record.confidence);
1414
+ if (confidence !== void 0) {
1415
+ edge.confidence = confidence;
871
1416
  }
872
- return true;
873
- }
874
- var EDGE_LAYER_RULES = {
875
- // === 6 Canonical Epistemic Types ===
876
- supports: {
877
- from: ["L3"],
878
- to: ["L3"],
879
- description: "Belief bears on Belief (weight: +1 supports, -1 contradicts)"
880
- },
881
- informs: {
882
- from: ["L2"],
883
- to: ["L3"],
884
- description: "Evidence -> Belief (L2 -> L3)"
885
- },
886
- depends_on: {
887
- from: ["L3"],
888
- to: ["L3"],
889
- description: "Belief B requires Belief A (structural gate)"
890
- },
891
- derived_from: {
892
- from: ["L2", "L3", "L4"],
893
- to: ["L1", "L2", "L3"],
894
- description: "A was produced from B (provenance chain)"
895
- },
896
- contains: {
897
- from: ["L3", "L4", "ontological"],
898
- to: ["L2", "L3", "ontological"],
899
- description: "A scopes/aggregates B (hierarchy)"
900
- },
901
- tests: {
902
- from: ["L3"],
903
- to: ["L3"],
904
- description: "Question -> Belief (L3 -> L3)"
905
- },
906
- // === Structural / Lifecycle ===
907
- supersedes: {
908
- from: ["L3"],
909
- to: ["L3"],
910
- description: "NewNode -> OldNode (fork lineage)"
911
- },
912
- responds_to: {
913
- from: ["L2", "L3"],
914
- to: ["L3"],
915
- description: "Answer -> Question (L2/L3 -> L3)"
916
- },
917
- belongs_to: {
918
- from: ["L2", "L3", "ontological"],
919
- to: ["L3"],
920
- description: "Membership (migrating to contains)"
921
- },
922
- relates_to_thesis: {
923
- from: ["L3"],
924
- to: ["L3"],
925
- description: "Belief -> Theme (L3 -> L3)"
926
- },
927
- // === Ontological (entity-entity or entity-epistemic bridge) ===
928
- works_at: {
929
- from: ["ontological"],
930
- to: ["ontological"],
931
- description: "Person -> Company"
932
- },
933
- invested_in: {
934
- from: ["ontological"],
935
- to: ["ontological"],
936
- description: "Investor -> Company"
937
- },
938
- competes_with: {
939
- from: ["ontological"],
940
- to: ["ontological"],
941
- description: "Company -> Company"
942
- },
943
- participates_in: {
944
- from: ["ontological"],
945
- to: ["ontological"],
946
- description: "Company -> ValueChain"
947
- },
948
- founded_by: {
949
- from: ["ontological"],
950
- to: ["ontological"],
951
- description: "Company -> Person"
952
- },
953
- evaluates: {
954
- from: ["ontological"],
955
- to: ["ontological"],
956
- description: "Deal -> Company"
957
- },
958
- performs: {
959
- from: ["ontological"],
960
- to: ["ontological"],
961
- description: "Company -> Function"
962
- },
963
- function_in: {
964
- from: ["ontological"],
965
- to: ["ontological"],
966
- description: "Function -> ValueChain"
967
- },
968
- impacts: {
969
- from: ["ontological", "L3"],
970
- to: ["ontological"],
971
- description: "Theme/Entity -> ValueChain"
972
- },
973
- raised_from: {
974
- from: ["ontological"],
975
- to: ["ontological"],
976
- description: "Company -> Investor"
977
- },
978
- mentioned_in: {
979
- from: ["ontological"],
980
- to: ["L1", "L2"],
981
- description: "Entity -> Source/Evidence"
982
- },
983
- perspective_on: {
984
- from: ["ontological"],
985
- to: ["L3"],
986
- description: "Person -> Belief/Theme"
987
- },
988
- plays_theme: {
989
- from: ["ontological"],
990
- to: ["L3"],
991
- description: "Deal -> Theme"
992
- },
993
- // C2-RR.4 — storage migration alias + the remaining 55 reachable edge types.
994
- // Mirrors the kernel rule table
995
- // (packages/reasoning-kernel/src/adapters/lib/edgeValidation.ts) so this
996
- // graph-primitives write path admits the same public edge vocabulary. See the
997
- // kernel file for the per-group rationale.
998
- extracted_from: {
999
- from: ["L2", "L3", "L4"],
1000
- to: ["L1", "L2", "L3"],
1001
- description: "Legacy storage migration alias for derived_from; public writes use derived_from"
1002
- },
1003
- qualifies: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief qualifies a Belief" },
1004
- contradicts: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief contradicts a Belief" },
1005
- reinforces: { from: ["L2", "L3"], to: ["L3"], description: "Evidence/Belief reinforces a Belief" },
1006
- corroborates: { from: ["L2", "L3"], to: ["L3"], description: "Independent evidence/belief corroborates a Belief" },
1007
- strengthened_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is strengthened by Evidence/Belief" },
1008
- weakened_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is weakened by Evidence/Belief" },
1009
- validated_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is validated by Evidence/Belief" },
1010
- falsified_by: { from: ["L3"], to: ["L2", "L3"], description: "Belief is falsified by Evidence/Belief" },
1011
- amplifies: { from: ["L3"], to: ["L3"], description: "Belief amplifies another Belief" },
1012
- precondition_for: { from: ["L3"], to: ["L3"], description: "Belief is a precondition for another Belief" },
1013
- prerequisite_for: { from: ["L3"], to: ["L3"], description: "Belief is a prerequisite for another Belief" },
1014
- required_for: { from: ["L3"], to: ["L3"], description: "Belief is required for another Belief" },
1015
- in_tension_with: { from: ["L3"], to: ["L3"], description: "Belief is in tension with another Belief" },
1016
- mutually_exclusive: { from: ["L3"], to: ["L3"], description: "Beliefs cannot both hold" },
1017
- exclusive_with: { from: ["L3"], to: ["L3"], description: "Belief is exclusive with another Belief" },
1018
- alternative_to: { from: ["L3"], to: ["L3"], description: "Belief is an alternative to another Belief" },
1019
- subsumes: { from: ["L3"], to: ["L3"], description: "Belief subsumes a narrower Belief" },
1020
- extends: { from: ["L3"], to: ["L3"], description: "Belief extends another Belief" },
1021
- refines: { from: ["L3"], to: ["L3"], description: "Belief refines another Belief" },
1022
- implements: { from: ["L3"], to: ["L3"], description: "Belief implements an abstract Belief" },
1023
- violates: { from: ["L3"], to: ["L3"], description: "Belief violates a constraint Belief" },
1024
- assumes: { from: ["L3"], to: ["L3"], description: "Belief assumes another Belief" },
1025
- would_predict: { from: ["L3"], to: ["L3"], description: "Belief would predict another Belief" },
1026
- analogous_to: { from: ["L3"], to: ["L3"], description: "Belief is analogous to another Belief" },
1027
- independent_of: { from: ["L3"], to: ["L3"], description: "Belief is independent of another Belief" },
1028
- correlates_with: { from: ["L3"], to: ["L3"], description: "Belief correlates with another Belief" },
1029
- co_changes_with: { from: ["L3"], to: ["L3"], description: "Belief co-changes with another Belief" },
1030
- counterfactual_of: { from: ["L3"], to: ["L3"], description: "Belief is a counterfactual of another Belief" },
1031
- parallel_to: { from: ["L3"], to: ["L3"], description: "Belief runs parallel to another Belief" },
1032
- cascade_from: { from: ["L3"], to: ["L3"], description: "Cascade from an upstream Belief" },
1033
- cascade_to: { from: ["L3"], to: ["L3"], description: "Cascade to a downstream Belief" },
1034
- collapses_if: { from: ["L3"], to: ["L3"], description: "Belief collapses if another fails" },
1035
- branches_from: { from: ["L3"], to: ["L3"], description: "Belief branches from an ancestor Belief" },
1036
- same_as: { from: ["L2", "L3", "ontological"], to: ["L2", "L3", "ontological"], description: "Two nodes are the same entity" },
1037
- answers: { from: ["L2", "L3"], to: ["L3"], description: "Answer/Belief answers a Question" },
1038
- partially_answers: { from: ["L2", "L3"], to: ["L3"], description: "Answer/Belief partially answers a Question" },
1039
- explores: { from: ["L3"], to: ["L3"], description: "Question explores a Belief/Theme" },
1040
- informed_by_theme: { from: ["L3"], to: ["L3"], description: "Belief is informed by a Theme" },
1041
- same_theme_as: { from: ["L3"], to: ["L3"], description: "Two Beliefs share a Theme" },
1042
- based_on: { from: ["L4"], to: ["L3"], description: "Decision is based on a Belief/Question" },
1043
- based_on_belief: { from: ["L4"], to: ["L3"], description: "Decision is based on a Belief" },
1044
- based_on_question: { from: ["L4"], to: ["L3"], description: "Decision is based on a Question" },
1045
- blocked_by_contradiction: { from: ["L4"], to: ["L3"], description: "Decision is blocked by a Contradiction" },
1046
- parent_of: { from: ["L3", "L4", "ontological", "organizational"], to: ["L2", "L3", "ontological", "organizational"], description: "A is the parent of B" },
1047
- child_of: { from: ["L2", "L3", "ontological", "organizational"], to: ["L3", "L4", "ontological", "organizational"], description: "A is the child of B" },
1048
- scoped_by: { from: ["L2", "L3"], to: ["L3", "organizational"], description: "Object is scoped by a Topic/Theme" },
1049
- cites: { from: ["L2", "L3"], to: ["L1", "L2"], description: "Evidence/Belief cites a Source/Excerpt" },
1050
- summarizes: { from: ["L2", "L3"], to: ["L1", "L2"], description: "Synthesis/Evidence summarizes a Source/Evidence" },
1051
- same_source_as: { from: ["L1", "L2"], to: ["L1", "L2"], description: "Two nodes derive from the same Source" },
1052
- migrating_from: { from: ["L2", "L3", "L4"], to: ["L1", "L2", "L3"], description: "Migration lineage: from an ancestor" },
1053
- migrating_to: { from: ["L1", "L2", "L3"], to: ["L2", "L3", "L4"], description: "Migration lineage: to a successor" },
1054
- about_entity: { from: ["L2", "L3"], to: ["ontological"], description: "Belief/Evidence is about an Entity" },
1055
- entity_referenced_in: { from: ["ontological"], to: ["L1", "L2"], description: "Entity is referenced in a Source/Evidence" },
1056
- related_to: { from: ["L2", "L3", "ontological", "organizational"], to: ["L2", "L3", "ontological", "organizational"], description: "Lateral adjacency; no confidence pressure" },
1057
- blocks: { from: ["L3", "L4"], to: ["L3", "L4"], description: "A blocks B (structural gate)" }
1058
- };
1059
- function validateEdgeLayers(edgeType, fromLayer, toLayer) {
1060
- const rules = EDGE_LAYER_RULES[edgeType];
1061
- if (!rules) {
1062
- console.warn(
1063
- `[EdgeValidation] Unknown edge type: ${edgeType}, allowing by default`
1064
- );
1065
- return { valid: true };
1417
+ const weight = readOptionalNumber(record.weight);
1418
+ if (weight !== void 0) {
1419
+ edge.weight = weight;
1066
1420
  }
1067
- if (edgeType === "supersedes") {
1068
- if (fromLayer !== toLayer) {
1069
- return {
1070
- valid: false,
1071
- reason: `${edgeType} edges must be between nodes of the same layer. Got ${fromLayer} -> ${toLayer}`
1072
- };
1073
- }
1074
- return { valid: true };
1421
+ if ("context" in record) {
1422
+ edge.context = record.context;
1075
1423
  }
1076
- if (!rules.from.includes(fromLayer)) {
1077
- return {
1078
- valid: false,
1079
- reason: `Edge type '${edgeType}' does not allow source layer ${fromLayer}. Allowed: ${rules.from.join(", ")}`
1080
- };
1424
+ if ("description" in record) {
1425
+ edge.description = record.description;
1081
1426
  }
1082
- if (!rules.to.includes(toLayer)) {
1083
- return {
1084
- valid: false,
1085
- reason: `Edge type '${edgeType}' does not allow target layer ${toLayer}. Allowed: ${rules.to.join(", ")}`
1086
- };
1427
+ return edge;
1428
+ }
1429
+ function readEdgeRows(values) {
1430
+ return values.flatMap((value) => {
1431
+ const edge = readEdgeRow(value);
1432
+ return edge ? [edge] : [];
1433
+ });
1434
+ }
1435
+ function nodeEndpointRefs(nodeId, node) {
1436
+ const refs = /* @__PURE__ */ new Set([String(nodeId)]);
1437
+ if (node?.globalId) {
1438
+ refs.add(node.globalId);
1087
1439
  }
1088
- if (!isValidLayerConnection(fromLayer, toLayer)) {
1089
- return {
1090
- valid: false,
1091
- reason: `Layer transition ${fromLayer} -> ${toLayer} is not permitted`
1092
- };
1440
+ return [...refs];
1441
+ }
1442
+ async function collectEdgesBetween(ctx, fromRefs, toRefs) {
1443
+ const seen = /* @__PURE__ */ new Set();
1444
+ const edges = [];
1445
+ for (const fromRef of fromRefs) {
1446
+ for (const toRef of toRefs) {
1447
+ const rows = await ctx.db.query("epistemicEdges").withIndex(
1448
+ "by_from_to",
1449
+ (q) => q.eq("fromNodeId", fromRef).eq("toNodeId", toRef)
1450
+ ).collect();
1451
+ for (const edge of readEdgeRows(rows)) {
1452
+ const key = String(edge._id);
1453
+ if (seen.has(key)) {
1454
+ continue;
1455
+ }
1456
+ seen.add(key);
1457
+ edges.push(edge);
1458
+ }
1459
+ }
1093
1460
  }
1094
- return { valid: true };
1461
+ return edges;
1095
1462
  }
1096
-
1097
- // src/epistemicEdges.mutations.ts
1098
1463
  var create = mutation({
1099
1464
  args: {
1100
1465
  globalId: v.string(),
@@ -1111,21 +1476,24 @@ var create = mutation({
1111
1476
  },
1112
1477
  returns: permissiveReturn,
1113
1478
  handler: async (ctx, args) => {
1114
- const fromNode = await ctx.db.get(args.fromNodeId);
1115
- const toNode = await ctx.db.get(args.toNodeId);
1116
- if (!fromNode || !toNode) {
1117
- throw new Error("One or both nodes not found");
1118
- }
1479
+ const fromNode = requireEdgeNodeRow(
1480
+ await ctx.db.get(args.fromNodeId),
1481
+ "Create edge source"
1482
+ );
1483
+ const toNode = requireEdgeNodeRow(
1484
+ await ctx.db.get(args.toNodeId),
1485
+ "Create edge target"
1486
+ );
1119
1487
  const resolvedScope = args.topicId || args.projectId ? await resolveTopicProjectScope(ctx, {
1120
1488
  topicId: args.topicId,
1121
1489
  projectId: args.projectId
1122
1490
  }) : void 0;
1123
1491
  const resolvedProjectId = resolvedScope?.projectId ?? args.projectId;
1124
1492
  if (resolvedProjectId) {
1125
- await requireProjectAccess(ctx, resolvedProjectId, args.createdBy);
1493
+ await requireScopeWriteAccess(ctx, resolvedProjectId, args.createdBy);
1126
1494
  }
1127
- const fromLayer = fromNode.epistemicLayer || getNodeLayer(fromNode.nodeType);
1128
- const toLayer = toNode.epistemicLayer || getNodeLayer(toNode.nodeType);
1495
+ const fromLayer = fromNode.epistemicLayer ?? getNodeLayer(fromNode.nodeType);
1496
+ const toLayer = toNode.epistemicLayer ?? getNodeLayer(toNode.nodeType);
1129
1497
  if (!args.skipLayerValidation) {
1130
1498
  const validation = validateEdgeLayers(args.edgeType, fromLayer, toLayer);
1131
1499
  if (!validation.valid) {
@@ -1139,10 +1507,11 @@ var create = mutation({
1139
1507
  `FORBIDDEN: Edge type '${args.edgeType}' has been removed from StackOS schema.`
1140
1508
  );
1141
1509
  }
1142
- const existing = await ctx.db.query("epistemicEdges").withIndex(
1143
- "by_from_to",
1144
- (q) => q.eq("fromNodeId", args.fromNodeId).eq("toNodeId", args.toNodeId)
1145
- ).collect();
1510
+ const existing = await collectEdgesBetween(
1511
+ ctx,
1512
+ nodeEndpointRefs(args.fromNodeId, fromNode),
1513
+ nodeEndpointRefs(args.toNodeId, toNode)
1514
+ );
1146
1515
  const duplicateEdge = existing.find((e) => e.edgeType === args.edgeType);
1147
1516
  if (duplicateEdge) {
1148
1517
  return { edgeId: duplicateEdge._id, isDuplicate: true };
@@ -1219,12 +1588,12 @@ var update = mutation({
1219
1588
  returns: permissiveReturn,
1220
1589
  handler: async (ctx, args) => {
1221
1590
  const { edgeId, userId, ...updates } = args;
1222
- const edge = await ctx.db.get(edgeId);
1591
+ const edge = readEdgeRow(await ctx.db.get(edgeId));
1223
1592
  if (!edge) {
1224
1593
  throw new Error("Edge not found");
1225
1594
  }
1226
1595
  if (edge.projectId && userId) {
1227
- await requireProjectAccess(ctx, edge.projectId, userId);
1596
+ await requireScopeWriteAccess(ctx, edge.projectId, userId);
1228
1597
  }
1229
1598
  const cleanUpdates = {};
1230
1599
  for (const [key, value] of Object.entries(updates)) {
@@ -1260,12 +1629,12 @@ var remove = mutation({
1260
1629
  },
1261
1630
  returns: permissiveReturn,
1262
1631
  handler: async (ctx, args) => {
1263
- const edge = await ctx.db.get(args.edgeId);
1632
+ const edge = readEdgeRow(await ctx.db.get(args.edgeId));
1264
1633
  if (!edge) {
1265
1634
  return buildEdgeNotFoundResult();
1266
1635
  }
1267
1636
  if (edge.projectId && args.userId) {
1268
- await requireProjectAccess(ctx, edge.projectId, args.userId);
1637
+ await requireScopeWriteAccess(ctx, edge.projectId, args.userId);
1269
1638
  }
1270
1639
  if (edge.projectId) {
1271
1640
  await ctx.db.insert("epistemicAudit", {
@@ -1306,10 +1675,13 @@ var removeBetween = mutation({
1306
1675
  },
1307
1676
  returns: permissiveReturn,
1308
1677
  handler: async (ctx, args) => {
1309
- const edges = await ctx.db.query("epistemicEdges").withIndex(
1310
- "by_from_to",
1311
- (q) => q.eq("fromNodeId", args.fromNodeId).eq("toNodeId", args.toNodeId)
1312
- ).collect();
1678
+ const fromNode = readEdgeNodeRow(await ctx.db.get(args.fromNodeId));
1679
+ const toNode = readEdgeNodeRow(await ctx.db.get(args.toNodeId));
1680
+ const edges = await collectEdgesBetween(
1681
+ ctx,
1682
+ nodeEndpointRefs(args.fromNodeId, fromNode),
1683
+ nodeEndpointRefs(args.toNodeId, toNode)
1684
+ );
1313
1685
  let deleted = 0;
1314
1686
  for (const edge of edges) {
1315
1687
  if (!args.edgeType || edge.edgeType === args.edgeType) {
@@ -1346,19 +1718,23 @@ var batchCreate = mutation({
1346
1718
  const results = [];
1347
1719
  const errors = [];
1348
1720
  for (const edge of args.edges) {
1349
- const fromNode = await ctx.db.get(edge.fromNodeId);
1350
- const toNode = await ctx.db.get(edge.toNodeId);
1351
- if (!fromNode || !toNode) {
1721
+ const fromNode = readEdgeNodeRow(await ctx.db.get(edge.fromNodeId));
1722
+ const toNode = readEdgeNodeRow(await ctx.db.get(edge.toNodeId));
1723
+ if (!(fromNode && toNode)) {
1352
1724
  errors.push({
1353
1725
  globalId: edge.globalId,
1354
1726
  error: "One or both nodes not found"
1355
1727
  });
1356
1728
  continue;
1357
1729
  }
1358
- const fromLayer = fromNode.epistemicLayer || getNodeLayer(fromNode.nodeType);
1359
- const toLayer = toNode.epistemicLayer || getNodeLayer(toNode.nodeType);
1730
+ const fromLayer = fromNode.epistemicLayer ?? getNodeLayer(fromNode.nodeType);
1731
+ const toLayer = toNode.epistemicLayer ?? getNodeLayer(toNode.nodeType);
1360
1732
  if (!args.skipLayerValidation) {
1361
- const validation = validateEdgeLayers(edge.edgeType, fromLayer, toLayer);
1733
+ const validation = validateEdgeLayers(
1734
+ edge.edgeType,
1735
+ fromLayer,
1736
+ toLayer
1737
+ );
1362
1738
  if (!validation.valid) {
1363
1739
  errors.push({
1364
1740
  globalId: edge.globalId,
@@ -1393,9 +1769,7 @@ var batchCreate = mutation({
1393
1769
  results.push({ globalId: edge.globalId, edgeGlobalId: edge.globalId });
1394
1770
  }
1395
1771
  const projectIds = new Set(
1396
- args.edges.flatMap(
1397
- (edge) => typeof edge.projectId === "string" ? [edge.projectId] : []
1398
- )
1772
+ args.edges.flatMap((edge) => edge.projectId ? [edge.projectId] : [])
1399
1773
  );
1400
1774
  for (const pid of projectIds) {
1401
1775
  if (pid) {
@@ -1416,8 +1790,11 @@ var cleanupDeprecatedEdges = mutation({
1416
1790
  handler: async (ctx, args) => {
1417
1791
  const DEPRECATED_TYPES = ["contradicts"];
1418
1792
  const scopeId = args.topicId || args.projectId;
1419
- const allEdges = scopeId ? await ctx.db.query("epistemicEdges").withIndex("by_topic", (q) => q.eq("topicId", scopeId)).collect() : [];
1420
- const deprecatedEdges = allEdges.filter(
1793
+ const allEdges = scopeId ? await ctx.db.query("epistemicEdges").withIndex(
1794
+ "by_topic",
1795
+ (q) => q.eq("topicId", scopeId)
1796
+ ).collect() : [];
1797
+ const deprecatedEdges = readEdgeRows(allEdges).filter(
1421
1798
  (edge) => DEPRECATED_TYPES.includes(edge.edgeType)
1422
1799
  );
1423
1800
  if (args.dryRun) {
@@ -1460,15 +1837,15 @@ var deleteEdges = mutation({
1460
1837
  const deleted = [];
1461
1838
  const notFound = [];
1462
1839
  for (const edgeId of args.edgeIds) {
1463
- const edge = await ctx.db.get(edgeId);
1840
+ const edge = readEdgeRow(await ctx.db.get(edgeId));
1464
1841
  if (edge) {
1465
1842
  await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.deleteEdge, {
1466
1843
  globalId: edge.globalId
1467
1844
  });
1468
1845
  await ctx.db.delete(edgeId);
1469
- deleted.push(edgeId);
1846
+ deleted.push(String(edgeId));
1470
1847
  } else {
1471
- notFound.push(edgeId);
1848
+ notFound.push(String(edgeId));
1472
1849
  }
1473
1850
  }
1474
1851
  return {