@lucern/graph-primitives 1.0.29 → 1.0.31

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 +395 -225
  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 +854 -480
  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 +365 -166
  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 -289
  80. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  81. package/dist/epistemicBeliefs.confidence.d.ts +19 -15
  82. package/dist/epistemicBeliefs.confidence.js +633 -386
  83. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  84. package/dist/epistemicBeliefs.core.d.ts +6 -6
  85. package/dist/epistemicBeliefs.core.js +717 -371
  86. package/dist/epistemicBeliefs.core.js.map +1 -1
  87. package/dist/epistemicBeliefs.d.ts +11 -9
  88. package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
  89. package/dist/epistemicBeliefs.forkEvidence.js +8 -8
  90. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  91. package/dist/epistemicBeliefs.helpers.d.ts +68 -49
  92. package/dist/epistemicBeliefs.helpers.js +358 -211
  93. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  94. package/dist/epistemicBeliefs.internal.d.ts +5 -5
  95. package/dist/epistemicBeliefs.internal.js +1248 -1026
  96. package/dist/epistemicBeliefs.internal.js.map +1 -1
  97. package/dist/epistemicBeliefs.js +4942 -3590
  98. package/dist/epistemicBeliefs.js.map +1 -1
  99. package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
  100. package/dist/epistemicBeliefs.lifecycle.js +1138 -781
  101. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  102. package/dist/epistemicBeliefs.links.d.ts +7 -7
  103. package/dist/epistemicBeliefs.links.js +404 -267
  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 +1062 -576
  114. package/dist/epistemicContracts.evaluators.js.map +1 -1
  115. package/dist/epistemicContracts.handlers.d.ts +15 -32
  116. package/dist/epistemicContracts.handlers.js +1829 -1351
  117. package/dist/epistemicContracts.handlers.js.map +1 -1
  118. package/dist/epistemicContracts.js +1131 -636
  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 +1966 -1202
  136. package/dist/epistemicEdges.js.map +1 -1
  137. package/dist/epistemicEdges.mutations.d.ts +7 -7
  138. package/dist/epistemicEdges.mutations.js +956 -579
  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 +933 -532
  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 +840 -692
  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 +700 -504
  180. package/dist/epistemicNodes.js.map +1 -1
  181. package/dist/epistemicNodes.mutations.d.ts +6 -6
  182. package/dist/epistemicNodes.mutations.js +560 -463
  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 +351 -311
  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 +86 -83
  245. package/dist/index.js +16914 -11760
  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,12 +1,16 @@
1
- import { v } from 'convex/values';
2
- import { componentsGeneric, anyApi, queryGeneric, mutationGeneric } from 'convex/server';
3
1
  import { checkProjectAccess, requireScopeWriteAccess } from '@lucern/access-control/access';
4
2
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
3
+ import { v } from 'convex/values';
4
+ import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
5
+ import { componentsGeneric, queryGeneric, mutationGeneric } from 'convex/server';
5
6
 
6
7
  // src/contradictions.ts
7
- var api = anyApi;
8
+ var unsafeApi = unsafeConvexAnyApi(
9
+ "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
10
+ );
11
+ var api = unsafeApi;
8
12
  componentsGeneric();
9
- var internal = anyApi;
13
+ var internal = unsafeApi;
10
14
  var mutation = mutationGeneric;
11
15
  var query = queryGeneric;
12
16
 
@@ -21,8 +25,6 @@ function debugGraphPrimitiveFallback(message, context) {
21
25
  }
22
26
  console.debug(message, context ?? {});
23
27
  }
24
-
25
- // src/topicScope.ts
26
28
  var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
27
29
  async function resolveTopicNodeScopeOrNull(ctx, ref) {
28
30
  if (!ctx?.db || typeof ctx.db.query !== "function") {
@@ -57,13 +59,15 @@ function asMappedProjectId(topic) {
57
59
  if (!topic) {
58
60
  return;
59
61
  }
60
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
62
+ const directLegacyProjectId = normalizeScopeValue(
63
+ topic[LEGACY_SCOPE_FIELD]
64
+ );
61
65
  if (directLegacyProjectId) {
62
66
  return directLegacyProjectId;
63
67
  }
64
68
  const metadata = topic.metadata || {};
65
69
  const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
66
- return candidate ? candidate : void 0;
70
+ return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
67
71
  }
68
72
  function normalizeScopeValue(value) {
69
73
  if (typeof value !== "string") {
@@ -88,8 +92,9 @@ function pickPrimaryTopic(candidates) {
88
92
  })[0];
89
93
  }
90
94
  async function findTopicsByScopeAlias(ctx, scopeId) {
95
+ const query2 = ctx.db.query("topics");
91
96
  try {
92
- return await ctx.db.query("topics").withIndex(
97
+ return await query2.withIndex(
93
98
  "by_graph_scope_project",
94
99
  (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
95
100
  ).collect();
@@ -101,7 +106,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
101
106
  scopeId
102
107
  }
103
108
  );
104
- const topics = await ctx.db.query("topics").collect();
109
+ const topics = await query2.collect();
105
110
  return topics.filter((topic) => {
106
111
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
107
112
  const mappedProjectId = asMappedProjectId(topic);
@@ -157,137 +162,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
157
162
  let current = topic;
158
163
  for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
159
164
  current = await ctx.db.get(current.parentTopicId);
160
- if (!current) break;
165
+ if (!current) {
166
+ break;
167
+ }
161
168
  if (!tenantId) {
162
169
  tenantId = normalizeScopeValue(current.tenantId);
163
170
  }
164
171
  if (!workspaceId) {
165
172
  workspaceId = normalizeScopeValue(current.workspaceId);
166
173
  }
167
- if (tenantId && workspaceId) break;
174
+ if (tenantId && workspaceId) {
175
+ break;
176
+ }
168
177
  }
169
178
  return { tenantId, workspaceId };
170
179
  }
171
180
  async function resolveTopicProjectScope(ctx, args) {
172
181
  if (args.topicId) {
173
- let topic = null;
174
- try {
175
- topic = await ctx.db.get(
176
- args.topicId
177
- );
178
- } catch (error) {
179
- debugGraphPrimitiveFallback(
180
- "[topicScope] Failed to load topic by direct id",
181
- {
182
- error,
183
- topicId: args.topicId
184
- }
185
- );
186
- }
187
- if (!topic) {
188
- topic = await tryResolveHostTopicById(ctx, String(args.topicId));
189
- }
190
- if (!topic) {
191
- topic = pickPrimaryTopic(
192
- await findTopicsByScopeAlias(ctx, String(args.topicId))
193
- ) ?? null;
194
- }
195
- if (!topic) {
196
- const nodeScope = await resolveTopicNodeScopeOrNull(
197
- ctx,
198
- String(args.topicId)
199
- );
200
- if (nodeScope) {
201
- return nodeScope;
202
- }
203
- throw new Error(`Topic not found: ${String(args.topicId)}`);
204
- }
205
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
206
- const mapped = asMappedProjectId(topic);
207
- if (mapped) {
208
- return {
209
- topicId: topic._id,
210
- projectId: mapped,
211
- tenantId: inherited.tenantId,
212
- workspaceId: inherited.workspaceId,
213
- source: "topic"
214
- };
215
- }
216
- return {
217
- topicId: topic._id,
218
- tenantId: inherited.tenantId,
219
- workspaceId: inherited.workspaceId,
220
- source: "topic"
221
- };
182
+ return await resolveScopeFromTopicId(ctx, args.topicId);
222
183
  }
223
184
  if (args.projectId) {
224
- let directTopic = null;
225
- try {
226
- directTopic = await ctx.db.get(
227
- args.projectId
228
- );
229
- } catch (error) {
230
- debugGraphPrimitiveFallback(
231
- "[topicScope] Failed to load direct project topic",
232
- {
233
- error,
234
- projectId: args.projectId
235
- }
236
- );
237
- }
238
- if (directTopic) {
239
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
240
- const mapped = asMappedProjectId(directTopic);
241
- return {
242
- topicId: directTopic._id,
243
- projectId: mapped ?? args.projectId,
244
- tenantId: inherited.tenantId,
245
- workspaceId: inherited.workspaceId,
246
- source: "topic_inferred"
247
- };
248
- }
249
- directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
250
- if (directTopic) {
251
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
252
- const mapped = asMappedProjectId(directTopic);
253
- return {
254
- topicId: directTopic._id,
255
- projectId: mapped ?? args.projectId,
256
- tenantId: inherited.tenantId,
257
- workspaceId: inherited.workspaceId,
258
- source: "topic_inferred"
259
- };
260
- }
261
- const topics = await findTopicsByScopeAlias(ctx, args.projectId);
262
- const primary = pickPrimaryTopic(topics);
263
- if (primary) {
264
- const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
265
- return {
266
- topicId: primary._id,
267
- projectId: args.projectId,
268
- tenantId: inherited.tenantId,
269
- workspaceId: inherited.workspaceId,
270
- source: "project_mapped_topic"
271
- };
272
- }
273
- const nodeScope = await resolveTopicNodeScopeOrNull(
274
- ctx,
275
- String(args.projectId)
276
- );
277
- if (nodeScope) {
278
- return {
279
- ...nodeScope,
280
- projectId: nodeScope.projectId ?? String(args.projectId)
281
- };
282
- }
283
- throw new Error(
284
- `Legacy project scope ${String(args.projectId)} has no mapped topic.`
285
- );
185
+ return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
286
186
  }
287
187
  throw new Error(
288
188
  "Missing scope: provide topicId (preferred) or legacy projectId alias."
289
189
  );
290
190
  }
191
+ async function resolveScopeFromTopicId(ctx, topicId) {
192
+ const topic = await resolveTopicDocFromTopicId(ctx, topicId);
193
+ if (topic) {
194
+ return await buildTopicScope(ctx, topic, "topic");
195
+ }
196
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
197
+ if (nodeScope) {
198
+ return nodeScope;
199
+ }
200
+ throw new Error(`Topic not found: ${String(topicId)}`);
201
+ }
202
+ async function resolveTopicDocFromTopicId(ctx, topicId) {
203
+ const direct = await tryReadTopicDoc(ctx, topicId, {
204
+ failureLog: "[topicScope] Failed to load topic by direct id",
205
+ idLogKey: "topicId"
206
+ });
207
+ if (direct) {
208
+ return direct;
209
+ }
210
+ const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
211
+ if (hostTopic) {
212
+ return hostTopic;
213
+ }
214
+ return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
215
+ }
216
+ async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
217
+ const directTopic = await resolveDirectLegacyProjectTopic(
218
+ ctx,
219
+ legacyProjectId
220
+ );
221
+ if (directTopic) {
222
+ return await buildTopicScope(ctx, directTopic, "topic_inferred", {
223
+ fallbackProjectId: legacyProjectId
224
+ });
225
+ }
226
+ const primary = pickPrimaryTopic(
227
+ await findTopicsByScopeAlias(ctx, legacyProjectId)
228
+ );
229
+ if (primary) {
230
+ return await buildTopicScope(ctx, primary, "project_mapped_topic", {
231
+ fallbackProjectId: legacyProjectId
232
+ });
233
+ }
234
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
235
+ if (nodeScope) {
236
+ return {
237
+ ...nodeScope,
238
+ projectId: nodeScope.projectId ?? legacyProjectId
239
+ };
240
+ }
241
+ throw new Error(
242
+ `Legacy project scope ${legacyProjectId} has no mapped topic.`
243
+ );
244
+ }
245
+ async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
246
+ const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
247
+ failureLog: "[topicScope] Failed to load direct project topic",
248
+ idLogKey: "projectId"
249
+ });
250
+ return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
251
+ }
252
+ async function tryReadTopicDoc(ctx, id, log) {
253
+ try {
254
+ return await ctx.db.get(id);
255
+ } catch (error) {
256
+ debugGraphPrimitiveFallback(log.failureLog, {
257
+ error,
258
+ [log.idLogKey]: id
259
+ });
260
+ return null;
261
+ }
262
+ }
263
+ async function buildTopicScope(ctx, topic, source, options = {}) {
264
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
265
+ const mapped = asMappedProjectId(topic);
266
+ return {
267
+ topicId: topic._id,
268
+ ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
269
+ tenantId: inherited.tenantId,
270
+ workspaceId: inherited.workspaceId,
271
+ source
272
+ };
273
+ }
291
274
  var optionalScopeArgs = {
292
275
  projectId: v.optional(v.string()),
293
276
  topicId: v.optional(v.string())
@@ -305,7 +288,7 @@ function normalizeScopeValue2(value) {
305
288
  async function resolveScope(ctx, args) {
306
289
  const topicId = normalizeScopeValue2(args.topicId);
307
290
  const projectId = normalizeScopeValue2(args.projectId);
308
- if (!topicId && !projectId) {
291
+ if (!(topicId || projectId)) {
309
292
  return null;
310
293
  }
311
294
  try {
@@ -344,10 +327,162 @@ async function resolveScopeSoft(ctx, args) {
344
327
  ...projectId ? { projectId } : {}
345
328
  };
346
329
  }
330
+
331
+ // src/contradictions.ts
347
332
  v.id("epistemicNodes");
348
333
  v.id("epistemicNodes");
349
334
  var DEFAULT_CONTRADICTION_SOURCE = "evidence_links";
350
335
  var TUPLE_SPACE_CONTRADICTION_SOURCE = "tuple_space";
336
+ function isRecord(value) {
337
+ return typeof value === "object" && value !== null;
338
+ }
339
+ function readConvexId(value) {
340
+ return typeof value === "string" && value.length > 0 ? value : null;
341
+ }
342
+ function readOptionalNumber(value) {
343
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
344
+ }
345
+ function readOptionalString(value) {
346
+ return typeof value === "string" ? value : void 0;
347
+ }
348
+ function readIdArray(value) {
349
+ if (!Array.isArray(value)) {
350
+ return [];
351
+ }
352
+ return value.flatMap((entry) => {
353
+ const id = readConvexId(entry);
354
+ return id ? [id] : [];
355
+ });
356
+ }
357
+ function readContradictionSource(value) {
358
+ if (value === DEFAULT_CONTRADICTION_SOURCE) {
359
+ return DEFAULT_CONTRADICTION_SOURCE;
360
+ }
361
+ if (value === TUPLE_SPACE_CONTRADICTION_SOURCE) {
362
+ return TUPLE_SPACE_CONTRADICTION_SOURCE;
363
+ }
364
+ return null;
365
+ }
366
+ function readContradictionStatus(value) {
367
+ return value === "unresolved" || value === "investigating" || value === "resolved_support" || value === "resolved_contra" || value === "belief_forked" ? value : null;
368
+ }
369
+ function readContradictionSeverity(value) {
370
+ return value === "critical" || value === "significant" || value === "minor" ? value : null;
371
+ }
372
+ function readAiAnalysis(value) {
373
+ if (!isRecord(value)) {
374
+ return null;
375
+ }
376
+ if (typeof value.summary !== "string" || typeof value.likelyExplanation !== "string" || typeof value.suggestedResolution !== "string" || typeof value.confidenceInAnalysis !== "number" || typeof value.analyzedAt !== "number") {
377
+ return null;
378
+ }
379
+ return {
380
+ analyzedAt: value.analyzedAt,
381
+ confidenceInAnalysis: value.confidenceInAnalysis,
382
+ likelyExplanation: value.likelyExplanation,
383
+ suggestedResolution: value.suggestedResolution,
384
+ summary: value.summary
385
+ };
386
+ }
387
+ function readBeliefRecord(value) {
388
+ if (!isRecord(value)) {
389
+ return null;
390
+ }
391
+ const id = readConvexId(value._id);
392
+ const canonicalText = readOptionalString(value.canonicalText) ?? readOptionalString(value.belief);
393
+ const status = readOptionalString(value.status);
394
+ if (!(id && canonicalText && status)) {
395
+ return null;
396
+ }
397
+ return {
398
+ _id: id,
399
+ canonicalText,
400
+ criticality: readOptionalString(value.criticality) ?? null,
401
+ status
402
+ };
403
+ }
404
+ function readEvidenceLink(value) {
405
+ if (!isRecord(value)) {
406
+ return null;
407
+ }
408
+ const insightId = readConvexId(value.insightId);
409
+ if (!insightId || value.relation !== "supports" && value.relation !== "contradicts") {
410
+ return null;
411
+ }
412
+ return {
413
+ insightId,
414
+ relation: value.relation
415
+ };
416
+ }
417
+ function readContradictionRow(value) {
418
+ if (!isRecord(value)) {
419
+ return null;
420
+ }
421
+ const id = readConvexId(value._id);
422
+ const beliefId = readConvexId(value.beliefId);
423
+ const severity = readContradictionSeverity(value.severity);
424
+ const status = readContradictionStatus(value.status);
425
+ if (!(id && beliefId && severity && status)) {
426
+ return null;
427
+ }
428
+ return {
429
+ _id: id,
430
+ aiAnalysis: readAiAnalysis(value.aiAnalysis),
431
+ beliefBId: readConvexId(value.beliefBId),
432
+ beliefId,
433
+ contradictingInsightIds: readIdArray(
434
+ value.contradictingInsightIds
435
+ ),
436
+ createdBy: readOptionalString(value.createdBy),
437
+ description: readOptionalString(value.description) ?? null,
438
+ detectedAt: readOptionalNumber(value.detectedAt),
439
+ detectionMethod: readOptionalString(value.detectionMethod) ?? null,
440
+ projectId: readOptionalString(value.projectId) ?? null,
441
+ resolution: value.resolution,
442
+ resolutionSprintId: readOptionalString(value.resolutionSprintId) ?? null,
443
+ resolvedAt: readOptionalNumber(value.resolvedAt) ?? null,
444
+ severity,
445
+ source: readContradictionSource(value.source),
446
+ status,
447
+ supportingInsightIds: readIdArray(
448
+ value.supportingInsightIds
449
+ ),
450
+ topicId: readOptionalString(value.topicId) ?? readOptionalString(value.projectId) ?? ""
451
+ };
452
+ }
453
+ function readRowList(values, reader) {
454
+ return values.flatMap((value) => {
455
+ const row = reader(value);
456
+ return row ? [row] : [];
457
+ });
458
+ }
459
+ function getContradictionSeverity(criticality) {
460
+ if (criticality === "blocking") {
461
+ return "critical";
462
+ }
463
+ if (criticality === "supporting") {
464
+ return "minor";
465
+ }
466
+ return "significant";
467
+ }
468
+ function extractContradictionEvidence(evidenceLinks) {
469
+ const supportingInsightIds = [];
470
+ const contradictingInsightIds = [];
471
+ for (const link of evidenceLinks) {
472
+ if (link.relation === "supports") {
473
+ supportingInsightIds.push(link.insightId);
474
+ continue;
475
+ }
476
+ if (link.relation === "contradicts") {
477
+ contradictingInsightIds.push(link.insightId);
478
+ }
479
+ }
480
+ return { supportingInsightIds, contradictingInsightIds };
481
+ }
482
+ function getNewEvidenceIds(existingIds, latestIds) {
483
+ const existing = new Set(existingIds);
484
+ return latestIds.filter((id) => !existing.has(id));
485
+ }
351
486
  function contradictionSourceOf(contradiction) {
352
487
  return contradiction?.source === TUPLE_SPACE_CONTRADICTION_SOURCE ? TUPLE_SPACE_CONTRADICTION_SOURCE : DEFAULT_CONTRADICTION_SOURCE;
353
488
  }
@@ -363,18 +498,24 @@ var detectContradictions = query({
363
498
  if (!projectId) {
364
499
  return [];
365
500
  }
366
- const beliefs = await ctx.runQuery(
367
- internal.epistemicBeliefs.internalGetByProject,
368
- {
369
- projectId
370
- }
501
+ const beliefs = readRowList(
502
+ await ctx.runQuery(
503
+ internal.epistemicBeliefs.internalGetByProject,
504
+ {
505
+ projectId
506
+ }
507
+ ),
508
+ readBeliefRecord
371
509
  );
372
510
  const contradictionCandidates = [];
373
511
  for (const belief of beliefs) {
374
- const evidenceLinks = await ctx.db.query("beliefEvidenceLinks").withIndex(
375
- "by_beliefId",
376
- (q) => q.eq("beliefId", belief._id)
377
- ).collect();
512
+ const evidenceLinks = readRowList(
513
+ await ctx.db.query("beliefEvidenceLinks").withIndex(
514
+ "by_beliefId",
515
+ (q) => q.eq("beliefId", belief._id)
516
+ ).collect(),
517
+ readEvidenceLink
518
+ );
378
519
  const supportingLinks = evidenceLinks.filter(
379
520
  (l) => l.relation === "supports"
380
521
  );
@@ -388,10 +529,13 @@ var detectContradictions = query({
388
529
  const contradictingInsights = await Promise.all(
389
530
  contradictingLinks.map((l) => ctx.db.get(l.insightId))
390
531
  );
391
- const existingContradictions = await ctx.db.query("contradictions").withIndex(
392
- "by_beliefId",
393
- (q) => q.eq("beliefId", belief._id)
394
- ).collect();
532
+ const existingContradictions = readRowList(
533
+ await ctx.db.query("contradictions").withIndex(
534
+ "by_beliefId",
535
+ (q) => q.eq("beliefId", belief._id)
536
+ ).collect(),
537
+ readContradictionRow
538
+ );
395
539
  const existingContradiction = existingContradictions.find(
396
540
  (candidate) => contradictionSourceOf(candidate) === DEFAULT_CONTRADICTION_SOURCE
397
541
  );
@@ -401,11 +545,10 @@ var detectContradictions = query({
401
545
  contradictionCandidates.push({
402
546
  beliefId: belief._id,
403
547
  belief,
404
- supportingInsights: supportingInsights.filter(
405
- Boolean
406
- ),
407
- contradictingInsights: contradictingInsights.filter(
408
- Boolean
548
+ supportingInsights: readRowList(supportingInsights, readBeliefRecord),
549
+ contradictingInsights: readRowList(
550
+ contradictingInsights,
551
+ readBeliefRecord
409
552
  ),
410
553
  existingContradiction: existingContradiction ?? void 0
411
554
  });
@@ -445,15 +588,21 @@ var getByProject = query({
445
588
  let contradictions;
446
589
  if (args.status) {
447
590
  const status = args.status;
448
- contradictions = await ctx.db.query("contradictions").withIndex(
449
- "by_topic_status",
450
- (q) => q.eq("topicId", String(scope.topicId ?? projectId)).eq("status", status)
451
- ).order("desc").take(scanLimit);
591
+ contradictions = readRowList(
592
+ await ctx.db.query("contradictions").withIndex(
593
+ "by_topic_status",
594
+ (q) => q.eq("topicId", String(scope.topicId ?? projectId)).eq("status", status)
595
+ ).order("desc").take(scanLimit),
596
+ readContradictionRow
597
+ );
452
598
  } else {
453
- contradictions = await ctx.db.query("contradictions").withIndex(
454
- "by_topicId",
455
- (q) => q.eq("topicId", String(scope.topicId ?? projectId))
456
- ).order("desc").take(scanLimit);
599
+ contradictions = readRowList(
600
+ await ctx.db.query("contradictions").withIndex(
601
+ "by_topicId",
602
+ (q) => q.eq("topicId", String(scope.topicId ?? projectId))
603
+ ).order("desc").take(scanLimit),
604
+ readContradictionRow
605
+ );
457
606
  }
458
607
  const enriched = await Promise.all(
459
608
  contradictions.slice(0, pageSize).map(async (c) => {
@@ -491,10 +640,13 @@ var getUnresolvedCount = query({
491
640
  minor: 0
492
641
  };
493
642
  }
494
- const contradictions = await ctx.db.query("contradictions").withIndex(
495
- "by_topic_status",
496
- (q) => q.eq("topicId", String(scope.topicId ?? projectId)).eq("status", "unresolved")
497
- ).collect();
643
+ const contradictions = readRowList(
644
+ await ctx.db.query("contradictions").withIndex(
645
+ "by_topic_status",
646
+ (q) => q.eq("topicId", String(scope.topicId ?? projectId)).eq("status", "unresolved")
647
+ ).collect(),
648
+ readContradictionRow
649
+ );
498
650
  const critical = contradictions.filter(
499
651
  (c) => c.severity === "critical"
500
652
  ).length;
@@ -514,7 +666,9 @@ var getById = query({
514
666
  args: { contradictionId: v.id("contradictions") },
515
667
  returns: permissiveReturn,
516
668
  handler: async (ctx, args) => {
517
- const contradiction = await ctx.db.get(args.contradictionId);
669
+ const contradiction = readContradictionRow(
670
+ await ctx.db.get(args.contradictionId)
671
+ );
518
672
  if (!contradiction) {
519
673
  return null;
520
674
  }
@@ -547,10 +701,7 @@ var create = mutation({
547
701
  v.literal("minor")
548
702
  ),
549
703
  source: v.optional(
550
- v.union(
551
- v.literal("evidence_links"),
552
- v.literal("tuple_space")
553
- )
704
+ v.union(v.literal("evidence_links"), v.literal("tuple_space"))
554
705
  ),
555
706
  description: v.optional(v.string()),
556
707
  detectionMethod: v.optional(
@@ -584,7 +735,13 @@ var create = mutation({
584
735
  }
585
736
  const now = Date.now();
586
737
  const source = args.source ?? DEFAULT_CONTRADICTION_SOURCE;
587
- const existingRows = await ctx.db.query("contradictions").withIndex("by_beliefId", (q) => q.eq("beliefId", args.beliefId)).collect();
738
+ const existingRows = readRowList(
739
+ await ctx.db.query("contradictions").withIndex(
740
+ "by_beliefId",
741
+ (q) => q.eq("beliefId", args.beliefId)
742
+ ).collect(),
743
+ readContradictionRow
744
+ );
588
745
  const existing = existingRows.find(
589
746
  (row) => contradictionSourceOf(row) === source && (args.beliefBId ? String(row.beliefBId ?? "") === String(args.beliefBId) : true)
590
747
  );
@@ -646,7 +803,9 @@ var updateStatus = mutation({
646
803
  },
647
804
  returns: permissiveReturn,
648
805
  handler: async (ctx, args) => {
649
- const existing = await ctx.db.get(args.contradictionId);
806
+ const existing = readContradictionRow(
807
+ await ctx.db.get(args.contradictionId)
808
+ );
650
809
  if (!existing) {
651
810
  throw new Error("Contradiction not found");
652
811
  }
@@ -697,7 +856,9 @@ var resolve = mutation({
697
856
  },
698
857
  returns: permissiveReturn,
699
858
  handler: async (ctx, args) => {
700
- const existing = await ctx.db.get(args.contradictionId);
859
+ const existing = readContradictionRow(
860
+ await ctx.db.get(args.contradictionId)
861
+ );
701
862
  if (!existing) {
702
863
  throw new Error("Contradiction not found");
703
864
  }
@@ -756,7 +917,9 @@ var updateSeverity = mutation({
756
917
  },
757
918
  returns: permissiveReturn,
758
919
  handler: async (ctx, args) => {
759
- const existing = await ctx.db.get(args.contradictionId);
920
+ const existing = readContradictionRow(
921
+ await ctx.db.get(args.contradictionId)
922
+ );
760
923
  if (!existing) {
761
924
  throw new Error("Contradiction not found");
762
925
  }
@@ -814,75 +977,82 @@ var scanAndCreateContradictions = mutation({
814
977
  return { created: 0, updated: 0 };
815
978
  }
816
979
  const now = Date.now();
817
- const beliefs = await ctx.runQuery(
818
- internal.epistemicBeliefs.internalGetByProject,
819
- {
820
- projectId
821
- }
980
+ const beliefs = readRowList(
981
+ await ctx.runQuery(
982
+ internal.epistemicBeliefs.internalGetByProject,
983
+ {
984
+ projectId
985
+ }
986
+ ),
987
+ readBeliefRecord
822
988
  );
823
989
  let created = 0;
824
990
  let updated = 0;
825
991
  for (const belief of beliefs) {
826
- const evidenceLinks = await ctx.db.query("beliefEvidenceLinks").withIndex(
827
- "by_beliefId",
828
- (q) => q.eq("beliefId", belief._id)
829
- ).collect();
830
- const supportingIds = evidenceLinks.filter((l) => l.relation === "supports").map((l) => l.insightId);
831
- const contradictingIds = evidenceLinks.filter((l) => l.relation === "contradicts").map((l) => l.insightId);
832
- if (supportingIds.length > 0 && contradictingIds.length > 0) {
833
- const existingRows = await ctx.db.query("contradictions").withIndex(
992
+ const evidenceLinks = readRowList(
993
+ await ctx.db.query("beliefEvidenceLinks").withIndex(
834
994
  "by_beliefId",
835
995
  (q) => q.eq("beliefId", belief._id)
836
- ).collect();
837
- const existing = existingRows.find(
838
- (candidate) => contradictionSourceOf(candidate) === DEFAULT_CONTRADICTION_SOURCE
839
- );
840
- let severity = "significant";
841
- if (belief.criticality === "blocking") {
842
- severity = "critical";
843
- } else if (belief.criticality === "supporting") {
844
- severity = "minor";
845
- }
846
- if (existing) {
847
- const newSupporting = supportingIds.filter(
848
- (id) => !existing.supportingInsightIds.includes(id)
849
- );
850
- const newContradicting = contradictingIds.filter(
851
- (id) => !existing.contradictingInsightIds.includes(id)
852
- );
853
- if (newSupporting.length > 0 || newContradicting.length > 0) {
854
- await ctx.db.patch(existing._id, {
855
- supportingInsightIds: [
856
- ...existing.supportingInsightIds,
857
- ...newSupporting
858
- ],
859
- contradictingInsightIds: [
860
- ...existing.contradictingInsightIds,
861
- ...newContradicting
862
- ],
863
- severity
864
- });
865
- updated++;
866
- }
867
- } else {
868
- await ctx.db.insert("contradictions", {
869
- projectId,
870
- topicId: String(scope.topicId ?? projectId),
871
- beliefId: belief._id,
872
- supportingInsightIds: supportingIds,
873
- contradictingInsightIds: contradictingIds,
874
- source: DEFAULT_CONTRADICTION_SOURCE,
875
- resolutionStatus: "unresolved",
876
- // Lucern: required field
877
- status: "unresolved",
878
- // Legacy: kept for backward compat
879
- severity,
880
- detectedAt: now,
881
- createdBy: args.createdBy
882
- });
883
- created++;
884
- }
996
+ ).collect(),
997
+ readEvidenceLink
998
+ );
999
+ const { supportingInsightIds, contradictingInsightIds } = extractContradictionEvidence(evidenceLinks);
1000
+ if (supportingInsightIds.length === 0 || contradictingInsightIds.length === 0) {
1001
+ continue;
885
1002
  }
1003
+ const existingRows = readRowList(
1004
+ await ctx.db.query("contradictions").withIndex(
1005
+ "by_beliefId",
1006
+ (q) => q.eq("beliefId", belief._id)
1007
+ ).collect(),
1008
+ readContradictionRow
1009
+ );
1010
+ const existing = existingRows.find(
1011
+ (candidate) => contradictionSourceOf(candidate) === DEFAULT_CONTRADICTION_SOURCE
1012
+ );
1013
+ const severity = getContradictionSeverity(belief.criticality);
1014
+ if (!existing) {
1015
+ await ctx.db.insert("contradictions", {
1016
+ projectId,
1017
+ topicId: String(scope.topicId ?? projectId),
1018
+ beliefId: belief._id,
1019
+ supportingInsightIds,
1020
+ contradictingInsightIds,
1021
+ source: DEFAULT_CONTRADICTION_SOURCE,
1022
+ resolutionStatus: "unresolved",
1023
+ // Lucern: required field
1024
+ status: "unresolved",
1025
+ // Legacy: kept for backward compat
1026
+ severity,
1027
+ detectedAt: now,
1028
+ createdBy: args.createdBy
1029
+ });
1030
+ created++;
1031
+ continue;
1032
+ }
1033
+ const newSupporting = getNewEvidenceIds(
1034
+ existing.supportingInsightIds,
1035
+ supportingInsightIds
1036
+ );
1037
+ const newContradicting = getNewEvidenceIds(
1038
+ existing.contradictingInsightIds,
1039
+ contradictingInsightIds
1040
+ );
1041
+ if (newSupporting.length === 0 && newContradicting.length === 0) {
1042
+ continue;
1043
+ }
1044
+ await ctx.db.patch(existing._id, {
1045
+ supportingInsightIds: [
1046
+ ...existing.supportingInsightIds,
1047
+ ...newSupporting
1048
+ ],
1049
+ contradictingInsightIds: [
1050
+ ...existing.contradictingInsightIds,
1051
+ ...newContradicting
1052
+ ],
1053
+ severity
1054
+ });
1055
+ updated++;
886
1056
  }
887
1057
  return { created, updated };
888
1058
  }