@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,11 +1,13 @@
1
- import { v, ConvexError } from 'convex/values';
2
- import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, readOpinionFromRecord } from '@lucern/confidence';
1
+ import { requireScopeWriteAccess } from '@lucern/access-control/access';
2
+ import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, hasProjectedOpinionChanged } from '@lucern/confidence';
3
3
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
4
- import { componentsGeneric, internalMutationGeneric, anyApi } from 'convex/server';
4
+ import { v } from 'convex/values';
5
5
  import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
6
- import { checkProjectAccess } from '@lucern/access-control/access';
6
+ import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
7
+ import { componentsGeneric, internalMutationGeneric } from 'convex/server';
7
8
  import '@lucern/access-control/audience';
8
9
  import '@lucern/access-control/auth';
10
+ import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
9
11
 
10
12
  // src/epistemicBeliefs.confidence.ts
11
13
 
@@ -129,10 +131,6 @@ function promoteBeliefStatusAfterScoring(status, opts) {
129
131
  }
130
132
  return status;
131
133
  }
132
- var api = anyApi;
133
- componentsGeneric();
134
- var internal = anyApi;
135
- var internalMutation = internalMutationGeneric;
136
134
 
137
135
  // src/edges/contains.ts
138
136
  var containsPropagationSpec = {
@@ -269,7 +267,7 @@ var dependsOnPropagationSpec = {
269
267
  description: "Structural gating. Textbook conditional deduction when edge conditionals exist, otherwise damped dependency cascade through downstream chains."
270
268
  };
271
269
 
272
- // src/edges/derivedFrom.ts
270
+ // src/edges/derived-from.ts
273
271
  var derivedFromPropagationSpec = {
274
272
  edgeType: "derived_from",
275
273
  direction: "incoming",
@@ -322,7 +320,7 @@ var informsPropagationSpec = {
322
320
  description: "Evidence-bearing influence. Informs can chain through the graph with light per-hop damping."
323
321
  };
324
322
 
325
- // src/edges/propagationTypes.ts
323
+ // src/edges/propagation-types.ts
326
324
  function isPropagationTraversalDirection(direction) {
327
325
  return direction === "outgoing" || direction === "incoming";
328
326
  }
@@ -395,6 +393,9 @@ var testsPropagationSpec = {
395
393
  };
396
394
 
397
395
  // src/edges/index.ts
396
+ var canContinueTransitively2 = canContinueTransitively;
397
+ var canTraverseHop2 = canTraverseHop;
398
+ var isPropagationTraversalDirection2 = isPropagationTraversalDirection;
398
399
  var EDGE_PROPAGATION_SPECS = [
399
400
  supportsPropagationSpec,
400
401
  informsPropagationSpec,
@@ -411,11 +412,18 @@ function getEdgePropagationSpecs() {
411
412
  return EDGE_PROPAGATION_SPECS;
412
413
  }
413
414
  function getTraversalDirections(direction) {
414
- if (isPropagationTraversalDirection(direction)) {
415
+ if (isPropagationTraversalDirection2(direction)) {
415
416
  return [direction];
416
417
  }
417
418
  return ["outgoing", "incoming"];
418
419
  }
420
+ var unsafeApi = unsafeConvexAnyApi(
421
+ "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
422
+ );
423
+ var api = unsafeApi;
424
+ componentsGeneric();
425
+ var internal = unsafeApi;
426
+ var internalMutation = internalMutationGeneric;
419
427
 
420
428
  // src/debug.ts
421
429
  function isGraphPrimitiveDebugEnabled() {
@@ -464,13 +472,15 @@ function asMappedProjectId(topic) {
464
472
  if (!topic) {
465
473
  return;
466
474
  }
467
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
475
+ const directLegacyProjectId = normalizeScopeValue(
476
+ topic[LEGACY_SCOPE_FIELD]
477
+ );
468
478
  if (directLegacyProjectId) {
469
479
  return directLegacyProjectId;
470
480
  }
471
481
  const metadata = topic.metadata || {};
472
482
  const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
473
- return candidate ? candidate : void 0;
483
+ return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
474
484
  }
475
485
  function normalizeScopeValue(value) {
476
486
  if (typeof value !== "string") {
@@ -495,8 +505,9 @@ function pickPrimaryTopic(candidates) {
495
505
  })[0];
496
506
  }
497
507
  async function findTopicsByScopeAlias(ctx, scopeId) {
508
+ const query = ctx.db.query("topics");
498
509
  try {
499
- return await ctx.db.query("topics").withIndex(
510
+ return await query.withIndex(
500
511
  "by_graph_scope_project",
501
512
  (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
502
513
  ).collect();
@@ -508,7 +519,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
508
519
  scopeId
509
520
  }
510
521
  );
511
- const topics = await ctx.db.query("topics").collect();
522
+ const topics = await query.collect();
512
523
  return topics.filter((topic) => {
513
524
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
514
525
  const mappedProjectId = asMappedProjectId(topic);
@@ -564,137 +575,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
564
575
  let current = topic;
565
576
  for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
566
577
  current = await ctx.db.get(current.parentTopicId);
567
- if (!current) break;
578
+ if (!current) {
579
+ break;
580
+ }
568
581
  if (!tenantId) {
569
582
  tenantId = normalizeScopeValue(current.tenantId);
570
583
  }
571
584
  if (!workspaceId) {
572
585
  workspaceId = normalizeScopeValue(current.workspaceId);
573
586
  }
574
- if (tenantId && workspaceId) break;
587
+ if (tenantId && workspaceId) {
588
+ break;
589
+ }
575
590
  }
576
591
  return { tenantId, workspaceId };
577
592
  }
578
593
  async function resolveTopicProjectScope(ctx, args) {
579
594
  if (args.topicId) {
580
- let topic = null;
581
- try {
582
- topic = await ctx.db.get(
583
- args.topicId
584
- );
585
- } catch (error) {
586
- debugGraphPrimitiveFallback(
587
- "[topicScope] Failed to load topic by direct id",
588
- {
589
- error,
590
- topicId: args.topicId
591
- }
592
- );
593
- }
594
- if (!topic) {
595
- topic = await tryResolveHostTopicById(ctx, String(args.topicId));
596
- }
597
- if (!topic) {
598
- topic = pickPrimaryTopic(
599
- await findTopicsByScopeAlias(ctx, String(args.topicId))
600
- ) ?? null;
601
- }
602
- if (!topic) {
603
- const nodeScope = await resolveTopicNodeScopeOrNull(
604
- ctx,
605
- String(args.topicId)
606
- );
607
- if (nodeScope) {
608
- return nodeScope;
609
- }
610
- throw new Error(`Topic not found: ${String(args.topicId)}`);
611
- }
612
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
613
- const mapped = asMappedProjectId(topic);
614
- if (mapped) {
615
- return {
616
- topicId: topic._id,
617
- projectId: mapped,
618
- tenantId: inherited.tenantId,
619
- workspaceId: inherited.workspaceId,
620
- source: "topic"
621
- };
622
- }
623
- return {
624
- topicId: topic._id,
625
- tenantId: inherited.tenantId,
626
- workspaceId: inherited.workspaceId,
627
- source: "topic"
628
- };
595
+ return await resolveScopeFromTopicId(ctx, args.topicId);
629
596
  }
630
597
  if (args.projectId) {
631
- let directTopic = null;
632
- try {
633
- directTopic = await ctx.db.get(
634
- args.projectId
635
- );
636
- } catch (error) {
637
- debugGraphPrimitiveFallback(
638
- "[topicScope] Failed to load direct project topic",
639
- {
640
- error,
641
- projectId: args.projectId
642
- }
643
- );
644
- }
645
- if (directTopic) {
646
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
647
- const mapped = asMappedProjectId(directTopic);
648
- return {
649
- topicId: directTopic._id,
650
- projectId: mapped ?? args.projectId,
651
- tenantId: inherited.tenantId,
652
- workspaceId: inherited.workspaceId,
653
- source: "topic_inferred"
654
- };
655
- }
656
- directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
657
- if (directTopic) {
658
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
659
- const mapped = asMappedProjectId(directTopic);
660
- return {
661
- topicId: directTopic._id,
662
- projectId: mapped ?? args.projectId,
663
- tenantId: inherited.tenantId,
664
- workspaceId: inherited.workspaceId,
665
- source: "topic_inferred"
666
- };
667
- }
668
- const topics = await findTopicsByScopeAlias(ctx, args.projectId);
669
- const primary = pickPrimaryTopic(topics);
670
- if (primary) {
671
- const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
672
- return {
673
- topicId: primary._id,
674
- projectId: args.projectId,
675
- tenantId: inherited.tenantId,
676
- workspaceId: inherited.workspaceId,
677
- source: "project_mapped_topic"
678
- };
679
- }
680
- const nodeScope = await resolveTopicNodeScopeOrNull(
681
- ctx,
682
- String(args.projectId)
683
- );
684
- if (nodeScope) {
685
- return {
686
- ...nodeScope,
687
- projectId: nodeScope.projectId ?? String(args.projectId)
688
- };
689
- }
690
- throw new Error(
691
- `Legacy project scope ${String(args.projectId)} has no mapped topic.`
692
- );
598
+ return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
693
599
  }
694
600
  throw new Error(
695
601
  "Missing scope: provide topicId (preferred) or legacy projectId alias."
696
602
  );
697
603
  }
604
+ async function resolveScopeFromTopicId(ctx, topicId) {
605
+ const topic = await resolveTopicDocFromTopicId(ctx, topicId);
606
+ if (topic) {
607
+ return await buildTopicScope(ctx, topic, "topic");
608
+ }
609
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
610
+ if (nodeScope) {
611
+ return nodeScope;
612
+ }
613
+ throw new Error(`Topic not found: ${String(topicId)}`);
614
+ }
615
+ async function resolveTopicDocFromTopicId(ctx, topicId) {
616
+ const direct = await tryReadTopicDoc(ctx, topicId, {
617
+ failureLog: "[topicScope] Failed to load topic by direct id",
618
+ idLogKey: "topicId"
619
+ });
620
+ if (direct) {
621
+ return direct;
622
+ }
623
+ const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
624
+ if (hostTopic) {
625
+ return hostTopic;
626
+ }
627
+ return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
628
+ }
629
+ async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
630
+ const directTopic = await resolveDirectLegacyProjectTopic(
631
+ ctx,
632
+ legacyProjectId
633
+ );
634
+ if (directTopic) {
635
+ return await buildTopicScope(ctx, directTopic, "topic_inferred", {
636
+ fallbackProjectId: legacyProjectId
637
+ });
638
+ }
639
+ const primary = pickPrimaryTopic(
640
+ await findTopicsByScopeAlias(ctx, legacyProjectId)
641
+ );
642
+ if (primary) {
643
+ return await buildTopicScope(ctx, primary, "project_mapped_topic", {
644
+ fallbackProjectId: legacyProjectId
645
+ });
646
+ }
647
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
648
+ if (nodeScope) {
649
+ return {
650
+ ...nodeScope,
651
+ projectId: nodeScope.projectId ?? legacyProjectId
652
+ };
653
+ }
654
+ throw new Error(
655
+ `Legacy project scope ${legacyProjectId} has no mapped topic.`
656
+ );
657
+ }
658
+ async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
659
+ const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
660
+ failureLog: "[topicScope] Failed to load direct project topic",
661
+ idLogKey: "projectId"
662
+ });
663
+ return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
664
+ }
665
+ async function tryReadTopicDoc(ctx, id, log) {
666
+ try {
667
+ return await ctx.db.get(id);
668
+ } catch (error) {
669
+ debugGraphPrimitiveFallback(log.failureLog, {
670
+ error,
671
+ [log.idLogKey]: id
672
+ });
673
+ return null;
674
+ }
675
+ }
676
+ async function buildTopicScope(ctx, topic, source, options = {}) {
677
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
678
+ const mapped = asMappedProjectId(topic);
679
+ return {
680
+ topicId: topic._id,
681
+ ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
682
+ tenantId: inherited.tenantId,
683
+ workspaceId: inherited.workspaceId,
684
+ source
685
+ };
686
+ }
698
687
  ({
699
688
  projectId: v.optional(v.string()),
700
689
  topicId: v.optional(v.string())
@@ -764,9 +753,10 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
764
753
  if (resolved.tenantId || resolved.workspaceId) {
765
754
  return resolved;
766
755
  }
767
- if (node.topicId) {
756
+ const topicId = normalizeScopeValue2(node.topicId);
757
+ if (topicId) {
768
758
  const topicScope = await resolveTopicProjectScope(ctx, {
769
- topicId: node.topicId
759
+ topicId
770
760
  });
771
761
  return {
772
762
  ...resolved,
@@ -788,9 +778,8 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
788
778
  }
789
779
 
790
780
  // src/confidencePropagationDispatch.ts
791
- function resolveTraversalTargetNodeId(edge, direction) {
792
- const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
793
- return targetNodeId ?? void 0;
781
+ function nodeIdToCacheKey(nodeId) {
782
+ return String(nodeId);
794
783
  }
795
784
  function readNodeOpinion(node) {
796
785
  const metadata = node.metadata ?? {};
@@ -806,138 +795,174 @@ function readNodeOpinion(node) {
806
795
  return mkOpinion(0, 0, 1, 0.5);
807
796
  }
808
797
  }
798
+ function resolveTraversalTargetNodeId(edge, direction) {
799
+ const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
800
+ return targetNodeId ?? void 0;
801
+ }
802
+ function buildInitialState(sourceNodeId, sourceOpinion) {
803
+ return {
804
+ nodeId: sourceNodeId,
805
+ opinion: sourceOpinion,
806
+ hop: 0,
807
+ visitedNodeIds: /* @__PURE__ */ new Set([nodeIdToCacheKey(sourceNodeId)])
808
+ };
809
+ }
810
+ function extendVisited(currentVisited, targetNodeId) {
811
+ return /* @__PURE__ */ new Set([...currentVisited, nodeIdToCacheKey(targetNodeId)]);
812
+ }
813
+ function makeTransitiveState(current, targetNodeId, projectedOpinion, nextHop) {
814
+ return {
815
+ nodeId: targetNodeId,
816
+ opinion: projectedOpinion,
817
+ hop: nextHop,
818
+ visitedNodeIds: extendVisited(current.visitedNodeIds, targetNodeId)
819
+ };
820
+ }
821
+ function makeDispatchRecord(targetNodeId, spec, direction, edge, projectedOpinion, nextHop, result, existingDispatch) {
822
+ return {
823
+ targetNodeId,
824
+ edgeType: spec.edgeType,
825
+ traversedDirection: direction,
826
+ weight: edge.weight ?? 1,
827
+ opinion: projectedOpinion,
828
+ operator: result.operator,
829
+ rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
830
+ hop: nextHop
831
+ };
832
+ }
833
+ async function loadCachedNode(scope, nodeId) {
834
+ const cacheKey = nodeIdToCacheKey(nodeId);
835
+ if (!scope.nodeCache.has(cacheKey)) {
836
+ scope.nodeCache.set(cacheKey, await scope.args.getNode(nodeId));
837
+ }
838
+ return scope.nodeCache.get(cacheKey) ?? null;
839
+ }
840
+ async function collectTargetDispatch(state, nextHop, spec, direction, edge, queue, scope) {
841
+ const sourceScope = scope.args.sourceScope;
842
+ if (sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, sourceScope)) {
843
+ return;
844
+ }
845
+ const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
846
+ if (!targetNodeId) {
847
+ return;
848
+ }
849
+ const targetNodeIdKey = nodeIdToCacheKey(targetNodeId);
850
+ if (state.visitedNodeIds.has(targetNodeIdKey)) {
851
+ return;
852
+ }
853
+ const targetNode = await loadCachedNode(scope, targetNodeId);
854
+ if (targetNode?.nodeType !== "belief") {
855
+ return;
856
+ }
857
+ if (sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, sourceScope)) {
858
+ return;
859
+ }
860
+ const targetOpinion = scope.opinionCache.get(targetNodeIdKey) ?? readNodeOpinion(targetNode);
861
+ const result = spec.operator(state.opinion, targetOpinion, edge, {
862
+ hop: nextHop,
863
+ sourceNodeId: state.nodeId,
864
+ targetNodeId,
865
+ traversedDirection: direction,
866
+ spec
867
+ });
868
+ if (!(result && hasProjectedOpinionChanged(targetOpinion, result.opinion))) {
869
+ return;
870
+ }
871
+ const projectedOpinion = mkOpinion(
872
+ result.opinion.b,
873
+ result.opinion.d,
874
+ result.opinion.u,
875
+ result.opinion.a
876
+ );
877
+ scope.opinionCache.set(targetNodeIdKey, projectedOpinion);
878
+ const existingDispatch = scope.dispatchesByTargetId.get(targetNodeIdKey);
879
+ scope.dispatchesByTargetId.set(
880
+ targetNodeIdKey,
881
+ makeDispatchRecord(
882
+ targetNodeId,
883
+ spec,
884
+ direction,
885
+ edge,
886
+ projectedOpinion,
887
+ nextHop,
888
+ result,
889
+ existingDispatch
890
+ )
891
+ );
892
+ if (canContinueTransitively2(spec, nextHop)) {
893
+ queue.push(
894
+ makeTransitiveState(state, targetNodeId, projectedOpinion, nextHop)
895
+ );
896
+ }
897
+ }
898
+ async function processTraversalSpec(state, nextHop, spec, queue, scope) {
899
+ const sourceNodeId = state.nodeId;
900
+ for (const direction of getTraversalDirections(spec.direction)) {
901
+ const edges = await scope.args.queryEdges({
902
+ nodeId: sourceNodeId,
903
+ spec,
904
+ direction,
905
+ hop: nextHop
906
+ });
907
+ for (const edge of edges) {
908
+ await collectTargetDispatch(
909
+ state,
910
+ nextHop,
911
+ spec,
912
+ direction,
913
+ edge,
914
+ queue,
915
+ scope
916
+ );
917
+ }
918
+ }
919
+ }
920
+ async function processQueuedState(state, queue, scope) {
921
+ const nextHop = state.hop + 1;
922
+ for (const spec of scope.traversalSpecs) {
923
+ if (!canTraverseHop2(spec, nextHop)) {
924
+ continue;
925
+ }
926
+ await processTraversalSpec(state, nextHop, spec, queue, scope);
927
+ }
928
+ }
929
+ function sortDispatches(dispatches) {
930
+ return Array.from(dispatches).sort((left, right) => {
931
+ if (left.hop !== right.hop) {
932
+ return left.hop - right.hop;
933
+ }
934
+ return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
935
+ });
936
+ }
809
937
  async function collectConfidencePropagationDispatches(args) {
810
938
  const dispatchesByTargetId = /* @__PURE__ */ new Map();
811
939
  const opinionCache = /* @__PURE__ */ new Map();
812
940
  const nodeCache = /* @__PURE__ */ new Map();
813
941
  const traversalSpecs = args.traversalSpecs ?? getEdgePropagationSpecs();
942
+ const scope = {
943
+ args,
944
+ dispatchesByTargetId,
945
+ opinionCache,
946
+ nodeCache,
947
+ traversalSpecs
948
+ };
814
949
  const queue = [
815
- {
816
- nodeId: args.sourceNodeId,
817
- opinion: args.sourceOpinion,
818
- hop: 0,
819
- visitedNodeIds: /* @__PURE__ */ new Set([String(args.sourceNodeId)])
820
- }
950
+ buildInitialState(args.sourceNodeId, args.sourceOpinion)
821
951
  ];
822
- const loadNode = async (nodeId) => {
823
- const cacheKey = String(nodeId);
824
- if (!nodeCache.has(cacheKey)) {
825
- nodeCache.set(cacheKey, await args.getNode(nodeId));
826
- }
827
- return nodeCache.get(cacheKey) ?? null;
828
- };
829
952
  while (queue.length > 0) {
830
953
  const state = queue.shift();
831
954
  if (!state) {
832
955
  continue;
833
956
  }
834
- for (const spec of traversalSpecs) {
835
- const nextHop = state.hop + 1;
836
- if (!canTraverseHop(spec, nextHop)) {
837
- continue;
838
- }
839
- for (const direction of getTraversalDirections(spec.direction)) {
840
- const edges = await args.queryEdges({
841
- nodeId: state.nodeId,
842
- spec,
843
- direction,
844
- hop: nextHop
845
- });
846
- for (const edge of edges) {
847
- if (args.sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, args.sourceScope)) {
848
- continue;
849
- }
850
- const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
851
- if (!targetNodeId) {
852
- continue;
853
- }
854
- if (state.visitedNodeIds.has(String(targetNodeId))) {
855
- continue;
856
- }
857
- const targetNode = await loadNode(targetNodeId);
858
- if (!targetNode || targetNode.nodeType !== "belief") {
859
- continue;
860
- }
861
- if (args.sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, args.sourceScope)) {
862
- continue;
863
- }
864
- const cacheKey = String(targetNodeId);
865
- const targetOpinion = opinionCache.get(cacheKey) ?? readNodeOpinion(targetNode);
866
- const result = spec.operator(state.opinion, targetOpinion, edge, {
867
- hop: nextHop,
868
- sourceNodeId: state.nodeId,
869
- targetNodeId,
870
- traversedDirection: direction,
871
- spec
872
- });
873
- if (!result || !hasProjectedOpinionChanged(targetOpinion, result.opinion)) {
874
- continue;
875
- }
876
- const projectedOpinion = mkOpinion(
877
- result.opinion.b,
878
- result.opinion.d,
879
- result.opinion.u,
880
- result.opinion.a
881
- );
882
- opinionCache.set(cacheKey, projectedOpinion);
883
- const existingDispatch = dispatchesByTargetId.get(cacheKey);
884
- dispatchesByTargetId.set(cacheKey, {
885
- targetNodeId,
886
- edgeType: spec.edgeType,
887
- traversedDirection: direction,
888
- weight: edge.weight ?? 1,
889
- opinion: projectedOpinion,
890
- operator: result.operator,
891
- rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
892
- hop: nextHop
893
- });
894
- if (canContinueTransitively(spec, nextHop)) {
895
- queue.push({
896
- nodeId: targetNodeId,
897
- opinion: projectedOpinion,
898
- hop: nextHop,
899
- visitedNodeIds: /* @__PURE__ */ new Set([
900
- ...state.visitedNodeIds,
901
- String(targetNodeId)
902
- ])
903
- });
904
- }
905
- }
906
- }
907
- }
957
+ await processQueuedState(state, queue, scope);
908
958
  }
909
- return Array.from(dispatchesByTargetId.values()).sort((left, right) => {
910
- if (left.hop !== right.hop) {
911
- return left.hop - right.hop;
912
- }
913
- return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
914
- });
959
+ return sortDispatches(dispatchesByTargetId.values());
915
960
  }
916
961
  v.id("epistemicNodes");
917
962
  var DEFAULT_CONFIDENCE_POLICY = {
918
963
  scoringMode: "after_worktree",
919
964
  tupleContradiction: normalizeTupleContradictionPolicy()
920
965
  };
921
- function throwStructuredMutationError(args) {
922
- const data = {
923
- structuredMutationError: true,
924
- message: args.message,
925
- status: args.status,
926
- code: args.code,
927
- invariantCode: args.invariantCode,
928
- suggestion: args.suggestion,
929
- details: args.details
930
- };
931
- const error = new ConvexError(
932
- data
933
- );
934
- error.status = args.status;
935
- error.code = args.code;
936
- error.invariantCode = args.invariantCode;
937
- error.suggestion = args.suggestion;
938
- error.details = args.details;
939
- throw error;
940
- }
941
966
  function buildBeliefConfidenceRow(args) {
942
967
  return {
943
968
  beliefId: args.beliefId,
@@ -1012,7 +1037,10 @@ function resolveBeliefStatus(node, metadata) {
1012
1037
  });
1013
1038
  }
1014
1039
  async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
1015
- const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex("by_belief", (q) => q.eq("beliefId", beliefNodeId)).collect();
1040
+ const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
1041
+ "by_belief",
1042
+ (q) => q.eq("beliefId", beliefNodeId)
1043
+ ).collect();
1016
1044
  for (const membership of clusterMembership) {
1017
1045
  const worktree = await ctx.db.get(membership.worktreeId);
1018
1046
  if (worktree?.status === "completed" || worktree?.status === "merged") {
@@ -1023,7 +1051,10 @@ async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
1023
1051
  }
1024
1052
  async function getActiveConfidencePolicy(ctx) {
1025
1053
  try {
1026
- const activeConfig = await ctx.db.query("logicSprintScoring").withIndex("by_active", (q) => q.eq("isActive", true)).first();
1054
+ const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
1055
+ "by_active",
1056
+ (q) => q.eq("isActive", true)
1057
+ ).first();
1027
1058
  return {
1028
1059
  scoringMode: activeConfig?.confidencePolicy === "always" ? "always" : DEFAULT_CONFIDENCE_POLICY.scoringMode,
1029
1060
  tupleContradiction: normalizeTupleContradictionPolicy(
@@ -1040,28 +1071,191 @@ async function getActiveConfidencePolicy(ctx) {
1040
1071
  return DEFAULT_CONFIDENCE_POLICY;
1041
1072
  }
1042
1073
  }
1043
- async function requireProjectWriteAccess(ctx, projectId, userId) {
1044
- const hasAccess = await checkProjectAccess(
1045
- ctx,
1046
- projectId,
1047
- userId
1048
- );
1049
- if (!hasAccess) {
1050
- throwStructuredMutationError({
1051
- message: `Project write access denied for topic ${projectId}.`,
1052
- status: 403,
1053
- code: "PROJECT_ACCESS_DENIED",
1054
- invariantCode: "policy.scope_required",
1055
- suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
1056
- details: { topicId: projectId, principalId: userId }
1057
- });
1058
- }
1059
- }
1060
1074
 
1061
1075
  // src/epistemicBeliefs.confidence.ts
1076
+ function isRecord(value) {
1077
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1078
+ }
1079
+ function readConvexId(value) {
1080
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1081
+ }
1082
+ function readOptionalBoolean(value) {
1083
+ return typeof value === "boolean" ? value : void 0;
1084
+ }
1085
+ function readOptionalNumber(value) {
1086
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1087
+ }
1088
+ function readOptionalString(value) {
1089
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1090
+ }
1091
+ function readRecord(value) {
1092
+ return isRecord(value) ? value : void 0;
1093
+ }
1094
+ function readConfidenceBeliefNode(value) {
1095
+ if (!isRecord(value)) {
1096
+ return null;
1097
+ }
1098
+ const id = readConvexId(value._id);
1099
+ const nodeType = readOptionalString(value.nodeType);
1100
+ const projectId = readOptionalString(value.projectId);
1101
+ if (!(id && nodeType === "belief" && projectId)) {
1102
+ return null;
1103
+ }
1104
+ const node = {
1105
+ _id: id,
1106
+ nodeType,
1107
+ projectId
1108
+ };
1109
+ const confidence = readOptionalNumber(value.confidence);
1110
+ const epistemicLayer = readOptionalString(value.epistemicLayer);
1111
+ const globalId = readOptionalString(value.globalId);
1112
+ const metadata = readRecord(value.metadata);
1113
+ const opinionA = readOptionalNumber(value.opinion_a);
1114
+ const opinionB = readOptionalNumber(value.opinion_b);
1115
+ const opinionD = readOptionalNumber(value.opinion_d);
1116
+ const opinionU = readOptionalNumber(value.opinion_u);
1117
+ const predictionMeta = readRecord(value.predictionMeta);
1118
+ const publicationStatus = readOptionalString(value.publicationStatus);
1119
+ const status = readOptionalString(value.status);
1120
+ const tenantId = readOptionalString(value.tenantId);
1121
+ const topicId = readOptionalString(value.topicId);
1122
+ const tupleContradicted = readOptionalBoolean(value.tupleContradicted);
1123
+ const workspaceId = readOptionalString(value.workspaceId);
1124
+ if (confidence !== void 0) {
1125
+ node.confidence = confidence;
1126
+ }
1127
+ if (epistemicLayer !== void 0) {
1128
+ node.epistemicLayer = epistemicLayer;
1129
+ }
1130
+ if (globalId !== void 0) {
1131
+ node.globalId = globalId;
1132
+ }
1133
+ if (metadata !== void 0) {
1134
+ node.metadata = metadata;
1135
+ }
1136
+ if (opinionA !== void 0) {
1137
+ node.opinion_a = opinionA;
1138
+ }
1139
+ if (opinionB !== void 0) {
1140
+ node.opinion_b = opinionB;
1141
+ }
1142
+ if (opinionD !== void 0) {
1143
+ node.opinion_d = opinionD;
1144
+ }
1145
+ if (opinionU !== void 0) {
1146
+ node.opinion_u = opinionU;
1147
+ }
1148
+ if (predictionMeta !== void 0) {
1149
+ node.predictionMeta = predictionMeta;
1150
+ }
1151
+ if (publicationStatus !== void 0) {
1152
+ node.publicationStatus = publicationStatus;
1153
+ }
1154
+ if (status !== void 0) {
1155
+ node.status = status;
1156
+ }
1157
+ if (tenantId !== void 0) {
1158
+ node.tenantId = tenantId;
1159
+ }
1160
+ if (topicId !== void 0) {
1161
+ node.topicId = topicId;
1162
+ }
1163
+ if (tupleContradicted !== void 0) {
1164
+ node.tupleContradicted = tupleContradicted;
1165
+ }
1166
+ if (workspaceId !== void 0) {
1167
+ node.workspaceId = workspaceId;
1168
+ }
1169
+ return node;
1170
+ }
1171
+ function readPropagationEdge(value) {
1172
+ if (!isRecord(value)) {
1173
+ return null;
1174
+ }
1175
+ const edgeType = readOptionalString(value.edgeType);
1176
+ if (!edgeType) {
1177
+ return null;
1178
+ }
1179
+ const edge = { edgeType };
1180
+ const fromNodeId = readConvexId(value.fromNodeId);
1181
+ const tenantId = readOptionalString(value.tenantId);
1182
+ const toNodeId = readConvexId(value.toNodeId);
1183
+ const weight = readOptionalNumber(value.weight);
1184
+ const workspaceId = readOptionalString(value.workspaceId);
1185
+ if (fromNodeId !== void 0) {
1186
+ edge.fromNodeId = fromNodeId;
1187
+ }
1188
+ if (tenantId !== void 0) {
1189
+ edge.tenantId = tenantId;
1190
+ }
1191
+ if (toNodeId !== void 0) {
1192
+ edge.toNodeId = toNodeId;
1193
+ }
1194
+ if (weight !== void 0) {
1195
+ edge.weight = weight;
1196
+ }
1197
+ if (workspaceId !== void 0) {
1198
+ edge.workspaceId = workspaceId;
1199
+ }
1200
+ return edge;
1201
+ }
1202
+ function readRowList(values, reader) {
1203
+ return values.flatMap((value) => {
1204
+ const row = reader(value);
1205
+ return row ? [row] : [];
1206
+ });
1207
+ }
1062
1208
  async function applyBeliefConfidenceChange(ctx, args) {
1063
1209
  const now = Date.now();
1064
- const node = await ctx.db.get(args.nodeId);
1210
+ const node = await requireConfidenceBeliefNode(ctx, args);
1211
+ const state = await buildConfidenceChangeState(ctx, node, args);
1212
+ await assertConfidenceScoringPolicySatisfied(ctx, args, state);
1213
+ const tupleContradictionId = await createTupleContradictionIfNeeded(
1214
+ ctx,
1215
+ args,
1216
+ node,
1217
+ state
1218
+ );
1219
+ await patchBeliefConfidenceState(ctx, args, state);
1220
+ await scheduleFirstScoringThemeEdges(ctx, args, node, state);
1221
+ const beliefConfidenceId = await insertBeliefConfidenceRecord(
1222
+ ctx,
1223
+ args,
1224
+ state,
1225
+ tupleContradictionId,
1226
+ now
1227
+ );
1228
+ await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
1229
+ nodeId: args.nodeId,
1230
+ operation: "upsert"
1231
+ });
1232
+ await insertConfidenceAudit(
1233
+ ctx,
1234
+ args,
1235
+ node,
1236
+ state,
1237
+ tupleContradictionId,
1238
+ now
1239
+ );
1240
+ await insertTupleTransitionAuditIfNeeded(
1241
+ ctx,
1242
+ args,
1243
+ node,
1244
+ state,
1245
+ tupleContradictionId,
1246
+ now
1247
+ );
1248
+ await scheduleConfidenceFollowups(ctx, args, node, state);
1249
+ return {
1250
+ nodeId: args.nodeId,
1251
+ previousConfidence: state.previousConfidence,
1252
+ newConfidence: state.derivedConfidence,
1253
+ opinion: state.nextOpinion,
1254
+ beliefConfidenceId
1255
+ };
1256
+ }
1257
+ async function requireConfidenceBeliefNode(ctx, args) {
1258
+ const node = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
1065
1259
  if (!node) {
1066
1260
  throwStructuredMutationError({
1067
1261
  message: "Node not found.",
@@ -1072,59 +1266,28 @@ async function applyBeliefConfidenceChange(ctx, args) {
1072
1266
  details: { nodeId: args.nodeId }
1073
1267
  });
1074
1268
  }
1075
- if (node.nodeType !== "belief") {
1076
- throwStructuredMutationError({
1077
- message: `appendSlScoring only applies to belief nodes. Received nodeType "${node.nodeType}". Entity nodes (company, person, investor, etc.) do not have confidence \u2014 use entityLifecycle.updateEntityAttributes for mutable entity data.`,
1078
- status: 400,
1079
- code: "INVALID_ARGUMENT",
1080
- invariantCode: "entity.no_confidence",
1081
- suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
1082
- details: { nodeId: args.nodeId, nodeType: node.nodeType }
1083
- });
1084
- }
1085
- if (!node.projectId) {
1086
- throwStructuredMutationError({
1087
- message: "Belief has no project scope.",
1088
- status: 400,
1089
- code: "MISSING_SCOPE",
1090
- invariantCode: "belief.project_required",
1091
- suggestion: "Belief must have a projectId before SL scoring can be appended.",
1092
- details: { nodeId: args.nodeId }
1093
- });
1094
- }
1095
- await requireProjectWriteAccess(
1096
- ctx,
1097
- node.projectId,
1098
- args.authenticatedUserId
1099
- );
1100
- const existingMetadata = node.metadata || {};
1269
+ await requireScopeWriteAccess(ctx, node.projectId, args.authenticatedUserId);
1270
+ return node;
1271
+ }
1272
+ async function buildConfidenceChangeState(ctx, node, args) {
1273
+ const existingMetadata = readNodeMetadata(node);
1101
1274
  const currentBeliefStatus = resolveBeliefStatus(node, existingMetadata);
1102
1275
  const confidencePolicy = await getActiveConfidencePolicy(ctx);
1103
- if (confidencePolicy.scoringMode === "after_worktree" && isPreValidationBeliefStatus(currentBeliefStatus)) {
1104
- const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
1105
- ctx,
1106
- args.nodeId
1107
- );
1108
- if (!hasCompletedWorktree) {
1109
- throwStructuredMutationError({
1110
- message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
1111
- status: 409,
1112
- code: "CONFLICT",
1113
- invariantCode: "belief.confidence_append_only",
1114
- suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
1115
- details: { nodeId: args.nodeId }
1116
- });
1117
- }
1118
- }
1119
1276
  const previousConfidence = node.confidence || 0.5;
1120
1277
  const predictionMeta = node.predictionMeta || existingMetadata.predictionMeta;
1121
1278
  const previousOpinion = readBeliefOpinionSnapshot(node, existingMetadata);
1122
- const slB = args.belief;
1123
- const slD = args.disbelief;
1124
- const slU = args.uncertainty;
1125
- const slA = args.baseRate ?? 0.5;
1126
- const nextOpinion = { b: slB, d: slD, u: slU, a: slA };
1127
- const derivedConfidence = confidenceFromSL(slB, slD, slU, slA);
1279
+ const nextOpinion = {
1280
+ b: args.belief,
1281
+ d: args.disbelief,
1282
+ u: args.uncertainty,
1283
+ a: args.baseRate ?? 0.5
1284
+ };
1285
+ const derivedConfidence = confidenceFromSL(
1286
+ nextOpinion.b,
1287
+ nextOpinion.d,
1288
+ nextOpinion.u,
1289
+ nextOpinion.a
1290
+ );
1128
1291
  const isFirstScoring = typeof node.confidence !== "number" || !Number.isFinite(node.confidence);
1129
1292
  const previousTupleContradicted = readTupleContradictedFlag(node.tupleContradicted) ?? readTupleContradictedFlag(existingMetadata.tupleContradicted) ?? detectTupleContradiction(
1130
1293
  previousOpinion,
@@ -1145,79 +1308,121 @@ async function applyBeliefConfidenceChange(ctx, args) {
1145
1308
  predictionMeta,
1146
1309
  metadata: existingMetadata
1147
1310
  });
1148
- let tupleContradictionId;
1149
- if (tupleTransition.crossedIntoTupleContradiction) {
1150
- tupleContradictionId = await ctx.runMutation(
1151
- "contradictions:create",
1152
- {
1153
- projectId: node.projectId,
1154
- topicId: node.topicId,
1155
- beliefId: args.nodeId,
1156
- beliefBId: args.nodeId,
1157
- supportingInsightIds: [],
1158
- contradictingInsightIds: [],
1159
- severity: deriveTupleContradictionSeverity(node),
1160
- source: "tuple_space",
1161
- detectionMethod: "agent",
1162
- description: tupleContradictionDescription,
1163
- createdBy: args.authenticatedUserId
1164
- }
1165
- );
1311
+ const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
1312
+ return {
1313
+ confidencePolicy,
1314
+ currentBeliefStatus,
1315
+ derivedConfidence,
1316
+ existingMetadata,
1317
+ isFirstScoring,
1318
+ newBeliefStatus,
1319
+ nextOpinion,
1320
+ previousConfidence,
1321
+ previousTupleContradicted,
1322
+ storedRationale,
1323
+ tupleContradictionDescription,
1324
+ tupleTransition
1325
+ };
1326
+ }
1327
+ function readNodeMetadata(node) {
1328
+ return node.metadata ?? {};
1329
+ }
1330
+ async function assertConfidenceScoringPolicySatisfied(ctx, args, state) {
1331
+ if (state.confidencePolicy.scoringMode !== "after_worktree" || !isPreValidationBeliefStatus(state.currentBeliefStatus)) {
1332
+ return;
1333
+ }
1334
+ const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
1335
+ ctx,
1336
+ args.nodeId
1337
+ );
1338
+ if (hasCompletedWorktree) {
1339
+ return;
1340
+ }
1341
+ throwStructuredMutationError({
1342
+ message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
1343
+ status: 409,
1344
+ code: "CONFLICT",
1345
+ invariantCode: "belief.confidence_append_only",
1346
+ suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
1347
+ details: { nodeId: args.nodeId }
1348
+ });
1349
+ }
1350
+ async function createTupleContradictionIfNeeded(ctx, args, node, state) {
1351
+ if (!state.tupleTransition.crossedIntoTupleContradiction) {
1352
+ return;
1166
1353
  }
1354
+ return await ctx.runMutation("contradictions:create", {
1355
+ projectId: node.projectId,
1356
+ topicId: node.topicId,
1357
+ beliefId: args.nodeId,
1358
+ beliefBId: args.nodeId,
1359
+ supportingInsightIds: [],
1360
+ contradictingInsightIds: [],
1361
+ severity: deriveTupleContradictionSeverity(node),
1362
+ source: "tuple_space",
1363
+ detectionMethod: "agent",
1364
+ description: state.tupleContradictionDescription,
1365
+ createdBy: args.authenticatedUserId
1366
+ });
1367
+ }
1368
+ async function patchBeliefConfidenceState(ctx, args, state) {
1167
1369
  await ctx.db.patch(args.nodeId, {
1168
- confidence: derivedConfidence,
1169
- beliefStatus: newBeliefStatus,
1170
- tupleContradicted: tupleTransition.tupleContradicted,
1171
- updatedAt: now,
1172
- // Store SL opinion fields at node level for fast access
1173
- opinion_b: slB,
1174
- opinion_d: slD,
1175
- opinion_u: slU,
1176
- opinion_a: slA,
1370
+ confidence: state.derivedConfidence,
1371
+ beliefStatus: state.newBeliefStatus,
1372
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1373
+ updatedAt: Date.now(),
1374
+ opinion_b: state.nextOpinion.b,
1375
+ opinion_d: state.nextOpinion.d,
1376
+ opinion_u: state.nextOpinion.u,
1377
+ opinion_a: state.nextOpinion.a,
1177
1378
  metadata: {
1178
- ...existingMetadata,
1179
- beliefStatus: newBeliefStatus,
1180
- slBelief: slB,
1181
- slDisbelief: slD,
1182
- slUncertainty: slU,
1183
- slBaseRate: slA,
1184
- tupleContradicted: tupleTransition.tupleContradicted
1379
+ ...state.existingMetadata,
1380
+ beliefStatus: state.newBeliefStatus,
1381
+ slBelief: state.nextOpinion.b,
1382
+ slDisbelief: state.nextOpinion.d,
1383
+ slUncertainty: state.nextOpinion.u,
1384
+ slBaseRate: state.nextOpinion.a,
1385
+ tupleContradicted: state.tupleTransition.tupleContradicted
1185
1386
  }
1186
1387
  });
1187
- if (isFirstScoring) {
1188
- const nodeTopicId = node.topicId;
1189
- const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
1190
- "by_topic",
1191
- (q) => q.eq("topicId", nodeTopicId || node.projectId)
1192
- ).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
1193
- for (const theme of themeNodes) {
1194
- if (theme.globalId && node.globalId) {
1195
- await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
1196
- globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
1197
- fromGlobalId: node.globalId,
1198
- toGlobalId: theme.globalId,
1199
- edgeType: "relates_to_thesis",
1200
- weight: derivedConfidence,
1201
- createdBy: args.authenticatedUserId,
1202
- topicId: String(node.projectId),
1203
- fromNodeType: "belief",
1204
- toNodeType: "theme",
1205
- fromLayer: "L3",
1206
- toLayer: "L3"
1207
- });
1208
- }
1388
+ }
1389
+ async function scheduleFirstScoringThemeEdges(ctx, args, node, state) {
1390
+ if (!state.isFirstScoring) {
1391
+ return;
1392
+ }
1393
+ const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
1394
+ "by_topic",
1395
+ (q) => q.eq("topicId", node.topicId || node.projectId)
1396
+ ).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
1397
+ for (const theme of themeNodes) {
1398
+ if (!(theme.globalId && node.globalId)) {
1399
+ continue;
1209
1400
  }
1401
+ await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
1402
+ globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
1403
+ fromGlobalId: node.globalId,
1404
+ toGlobalId: theme.globalId,
1405
+ edgeType: "relates_to_thesis",
1406
+ weight: state.derivedConfidence,
1407
+ createdBy: args.authenticatedUserId,
1408
+ topicId: String(node.projectId),
1409
+ fromNodeType: "belief",
1410
+ toNodeType: "theme",
1411
+ fromLayer: "L3",
1412
+ toLayer: "L3"
1413
+ });
1210
1414
  }
1211
- const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
1212
- const beliefConfidenceId = await ctx.db.insert("beliefConfidence", {
1415
+ }
1416
+ async function insertBeliefConfidenceRecord(ctx, args, state, tupleContradictionId, now) {
1417
+ return await ctx.db.insert("beliefConfidence", {
1213
1418
  ...buildBeliefConfidenceRow({
1214
1419
  beliefId: args.nodeId,
1215
- belief: slB,
1216
- disbelief: slD,
1217
- uncertainty: slU,
1218
- baseRate: slA,
1420
+ belief: state.nextOpinion.b,
1421
+ disbelief: state.nextOpinion.d,
1422
+ uncertainty: state.nextOpinion.u,
1423
+ baseRate: state.nextOpinion.a,
1219
1424
  trigger: args.trigger,
1220
- rationale: storedRationale,
1425
+ rationale: state.storedRationale,
1221
1426
  assessedBy: args.authenticatedUserId,
1222
1427
  assessedAt: now,
1223
1428
  slOperator: args.slOperator,
@@ -1226,25 +1431,23 @@ async function applyBeliefConfidenceChange(ctx, args) {
1226
1431
  triggeringWorktreeId: args.triggeringWorktreeId
1227
1432
  })
1228
1433
  });
1229
- await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
1230
- nodeId: args.nodeId,
1231
- operation: "upsert"
1232
- });
1434
+ }
1435
+ async function insertConfidenceAudit(ctx, args, node, state, tupleContradictionId, now) {
1233
1436
  await ctx.db.insert("epistemicAudit", {
1234
1437
  entityType: "belief",
1235
1438
  entityId: args.nodeId,
1236
1439
  changeType: "confidence_changed",
1237
1440
  previousState: {
1238
- confidence: previousConfidence,
1239
- tupleContradicted: previousTupleContradicted
1441
+ confidence: state.previousConfidence,
1442
+ tupleContradicted: state.previousTupleContradicted
1240
1443
  },
1241
1444
  newState: {
1242
- opinion: nextOpinion,
1243
- confidence: derivedConfidence,
1445
+ opinion: state.nextOpinion,
1446
+ confidence: state.derivedConfidence,
1244
1447
  trigger: args.trigger,
1245
- rationale: storedRationale,
1246
- tupleContradicted: tupleTransition.tupleContradicted,
1247
- tupleContradictionPolicy: tupleTransition.policy,
1448
+ rationale: state.storedRationale,
1449
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1450
+ tupleContradictionPolicy: state.tupleTransition.policy,
1248
1451
  ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1249
1452
  },
1250
1453
  changedBy: args.authenticatedUserId,
@@ -1253,28 +1456,39 @@ async function applyBeliefConfidenceChange(ctx, args) {
1253
1456
  projectId: node.projectId,
1254
1457
  topicId: node.topicId
1255
1458
  });
1256
- if (tupleTransition.crossedIntoTupleContradiction || tupleTransition.crossedOutOfTupleContradiction) {
1257
- await ctx.db.insert("epistemicAudit", {
1258
- entityType: "belief",
1259
- entityId: args.nodeId,
1260
- changeType: "updated",
1261
- previousState: { tupleContradicted: previousTupleContradicted },
1262
- newState: {
1263
- tupleContradicted: tupleTransition.tupleContradicted,
1264
- action: tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
1265
- opinion: nextOpinion,
1266
- tupleContradictionPolicy: tupleTransition.policy,
1267
- ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1268
- },
1269
- rationale: tupleTransition.crossedIntoTupleContradiction ? tupleContradictionDescription : `Tuple-space contradiction cleared: b=${nextOpinion.b.toFixed(2)}, d=${nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`,
1270
- changedBy: args.authenticatedUserId,
1271
- isAgent: false,
1272
- changedAt: now,
1273
- projectId: node.projectId,
1274
- topicId: node.topicId
1275
- });
1459
+ }
1460
+ async function insertTupleTransitionAuditIfNeeded(ctx, args, node, state, tupleContradictionId, now) {
1461
+ if (!(state.tupleTransition.crossedIntoTupleContradiction || state.tupleTransition.crossedOutOfTupleContradiction)) {
1462
+ return;
1276
1463
  }
1277
- if (Math.abs(derivedConfidence - previousConfidence) >= 0.15) {
1464
+ await ctx.db.insert("epistemicAudit", {
1465
+ entityType: "belief",
1466
+ entityId: args.nodeId,
1467
+ changeType: "updated",
1468
+ previousState: { tupleContradicted: state.previousTupleContradicted },
1469
+ newState: {
1470
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1471
+ action: state.tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
1472
+ opinion: state.nextOpinion,
1473
+ tupleContradictionPolicy: state.tupleTransition.policy,
1474
+ ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1475
+ },
1476
+ rationale: tupleAuditRationale(state),
1477
+ changedBy: args.authenticatedUserId,
1478
+ isAgent: false,
1479
+ changedAt: now,
1480
+ projectId: node.projectId,
1481
+ topicId: node.topicId
1482
+ });
1483
+ }
1484
+ function tupleAuditRationale(state) {
1485
+ if (state.tupleTransition.crossedIntoTupleContradiction) {
1486
+ return state.tupleContradictionDescription;
1487
+ }
1488
+ return `Tuple-space contradiction cleared: b=${state.nextOpinion.b.toFixed(2)}, d=${state.nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`;
1489
+ }
1490
+ async function scheduleConfidenceFollowups(ctx, args, node, state) {
1491
+ if (Math.abs(state.derivedConfidence - state.previousConfidence) >= 0.15) {
1278
1492
  await ctx.scheduler.runAfter(
1279
1493
  5e3,
1280
1494
  internal.bi.contradictionSemanticDetector.scanAffectedBeliefs,
@@ -1291,13 +1505,6 @@ async function applyBeliefConfidenceChange(ctx, args) {
1291
1505
  { nodeId: args.nodeId }
1292
1506
  );
1293
1507
  }
1294
- return {
1295
- nodeId: args.nodeId,
1296
- previousConfidence,
1297
- newConfidence: derivedConfidence,
1298
- opinion: { b: slB, d: slD, u: slU, a: slA },
1299
- beliefConfidenceId
1300
- };
1301
1508
  }
1302
1509
  function propagationPressureLabel(edgeType, weight) {
1303
1510
  if (edgeType === "contradicts" || edgeType === "refutes") {
@@ -1325,7 +1532,7 @@ var propagateConfidenceChange = internalMutation({
1325
1532
  args.opinion_u,
1326
1533
  args.opinion_a
1327
1534
  );
1328
- const sourceNode = await ctx.db.get(args.nodeId);
1535
+ const sourceNode = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
1329
1536
  const sourceScope = await resolveNodeScopeForWorkspaceIsolation(
1330
1537
  ctx,
1331
1538
  sourceNode
@@ -1334,16 +1541,20 @@ var propagateConfidenceChange = internalMutation({
1334
1541
  sourceNodeId: args.nodeId,
1335
1542
  sourceOpinion,
1336
1543
  sourceScope,
1337
- queryEdges: async ({ nodeId, spec, direction }) => {
1338
- return await ctx.db.query("epistemicEdges").withIndex(
1544
+ queryEdges: async ({ nodeId, spec, direction }) => readRowList(
1545
+ await ctx.db.query("epistemicEdges").withIndex(
1339
1546
  direction === "outgoing" ? "by_from_type" : "by_to_type",
1340
1547
  (q) => direction === "outgoing" ? q.eq("fromNodeId", nodeId).eq("edgeType", spec.edgeType) : q.eq("toNodeId", nodeId).eq("edgeType", spec.edgeType)
1341
- ).collect();
1342
- },
1343
- getNode: async (nodeId) => await ctx.db.get(nodeId)
1548
+ ).collect(),
1549
+ readPropagationEdge
1550
+ ),
1551
+ getNode: async (nodeId) => readConfidenceBeliefNode(await ctx.db.get(nodeId))
1344
1552
  });
1345
1553
  for (const dispatch of dispatches) {
1346
- const pressureLabel = propagationPressureLabel(dispatch.edgeType, dispatch.weight);
1554
+ const pressureLabel = propagationPressureLabel(
1555
+ dispatch.edgeType,
1556
+ dispatch.weight
1557
+ );
1347
1558
  await applyBeliefConfidenceChange(ctx, {
1348
1559
  nodeId: dispatch.targetNodeId,
1349
1560
  belief: dispatch.opinion.b,