@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,13 +1,34 @@
1
- import { v, ConvexError } from 'convex/values';
2
- import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, readOpinionFromRecord, deriveContractModulationPlan, deriveContractStatus, parseEvidentialEvaluatorConfig, compareMetricValue, buildEvidentialRationale, parseMetricCheckerConfig, getEvaluatorInputRecord, pickFiniteNumber, resolveComparisonResult, buildComparisonRationale, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, parseMarketIndexComparatorConfig } from '@lucern/confidence';
3
- import { checkProjectAccess } from '@lucern/access-control/access';
1
+ import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
2
+ import { componentsGeneric, internalMutationGeneric } from 'convex/server';
4
3
  import '@lucern/access-control/audience';
5
4
  import '@lucern/access-control/auth';
6
- import { componentsGeneric, internalMutationGeneric, anyApi } from 'convex/server';
5
+ import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
6
+ import { normalizeTupleContradictionPolicy, mkOpinion, conditionalDeduction, project, dampedDependencyCascade, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, confidenceFromSL, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, hasProjectedOpinionChanged, deriveContractModulationPlan, deriveContractStatus, parseEvidentialEvaluatorConfig, compareMetricValue, resolveComparisonResult, buildEvidentialRationale, parseMetricCheckerConfig, getEvaluatorInputRecord, pickFiniteNumber, buildComparisonRationale, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, parseMarketIndexComparatorConfig } from '@lucern/confidence';
7
+ import { v } from 'convex/values';
7
8
  import '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
9
+ import { requireScopeWriteAccess } from '@lucern/access-control/access';
8
10
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
9
11
 
10
- // src/epistemicBeliefs.helpers.ts
12
+ // src/convex.ts
13
+ var unsafeApi = unsafeConvexAnyApi(
14
+ "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
15
+ );
16
+ var api = unsafeApi;
17
+ componentsGeneric();
18
+ var internal = unsafeApi;
19
+ var internalMutation = internalMutationGeneric;
20
+
21
+ // src/debug.ts
22
+ function isGraphPrimitiveDebugEnabled() {
23
+ const env = globalThis.process?.env;
24
+ return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
25
+ }
26
+ function debugGraphPrimitiveFallback(message, context) {
27
+ if (!isGraphPrimitiveDebugEnabled()) {
28
+ return;
29
+ }
30
+ console.debug(message, context ?? {});
31
+ }
11
32
 
12
33
  // src/beliefLifecycle.ts
13
34
  var BELIEF_STATUS_VALUES = [
@@ -129,22 +150,6 @@ function promoteBeliefStatusAfterScoring(status, opts) {
129
150
  }
130
151
  return status;
131
152
  }
132
- var api = anyApi;
133
- componentsGeneric();
134
- var internal = anyApi;
135
- var internalMutation = internalMutationGeneric;
136
-
137
- // src/debug.ts
138
- function isGraphPrimitiveDebugEnabled() {
139
- const env = globalThis.process?.env;
140
- return env?.LUCERN_COMPAT_FALLBACK_DEBUG === "1" || env?.LUCERN_GRAPH_DEBUG === "1";
141
- }
142
- function debugGraphPrimitiveFallback(message, context) {
143
- if (!isGraphPrimitiveDebugEnabled()) {
144
- return;
145
- }
146
- console.debug(message, context ?? {});
147
- }
148
153
  var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
149
154
  async function resolveTopicNodeScopeOrNull(ctx, ref) {
150
155
  if (!ctx?.db || typeof ctx.db.query !== "function") {
@@ -179,13 +184,15 @@ function asMappedProjectId(topic) {
179
184
  if (!topic) {
180
185
  return;
181
186
  }
182
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD]);
187
+ const directLegacyProjectId = normalizeScopeValue(
188
+ topic[LEGACY_SCOPE_FIELD]
189
+ );
183
190
  if (directLegacyProjectId) {
184
191
  return directLegacyProjectId;
185
192
  }
186
193
  const metadata = topic.metadata || {};
187
194
  const candidate = metadata[LEGACY_SCOPE_FIELD] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
188
- return candidate ? candidate : void 0;
195
+ return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
189
196
  }
190
197
  function normalizeScopeValue(value) {
191
198
  if (typeof value !== "string") {
@@ -210,8 +217,9 @@ function pickPrimaryTopic(candidates) {
210
217
  })[0];
211
218
  }
212
219
  async function findTopicsByScopeAlias(ctx, scopeId) {
220
+ const query = ctx.db.query("topics");
213
221
  try {
214
- return await ctx.db.query("topics").withIndex(
222
+ return await query.withIndex(
215
223
  "by_graph_scope_project",
216
224
  (q) => q.eq(LEGACY_SCOPE_FIELD, scopeId)
217
225
  ).collect();
@@ -223,7 +231,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
223
231
  scopeId
224
232
  }
225
233
  );
226
- const topics = await ctx.db.query("topics").collect();
234
+ const topics = await query.collect();
227
235
  return topics.filter((topic) => {
228
236
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
229
237
  const mappedProjectId = asMappedProjectId(topic);
@@ -279,137 +287,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
279
287
  let current = topic;
280
288
  for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
281
289
  current = await ctx.db.get(current.parentTopicId);
282
- if (!current) break;
290
+ if (!current) {
291
+ break;
292
+ }
283
293
  if (!tenantId) {
284
294
  tenantId = normalizeScopeValue(current.tenantId);
285
295
  }
286
296
  if (!workspaceId) {
287
297
  workspaceId = normalizeScopeValue(current.workspaceId);
288
298
  }
289
- if (tenantId && workspaceId) break;
299
+ if (tenantId && workspaceId) {
300
+ break;
301
+ }
290
302
  }
291
303
  return { tenantId, workspaceId };
292
304
  }
293
305
  async function resolveTopicProjectScope(ctx, args) {
294
306
  if (args.topicId) {
295
- let topic = null;
296
- try {
297
- topic = await ctx.db.get(
298
- args.topicId
299
- );
300
- } catch (error) {
301
- debugGraphPrimitiveFallback(
302
- "[topicScope] Failed to load topic by direct id",
303
- {
304
- error,
305
- topicId: args.topicId
306
- }
307
- );
308
- }
309
- if (!topic) {
310
- topic = await tryResolveHostTopicById(ctx, String(args.topicId));
311
- }
312
- if (!topic) {
313
- topic = pickPrimaryTopic(
314
- await findTopicsByScopeAlias(ctx, String(args.topicId))
315
- ) ?? null;
316
- }
317
- if (!topic) {
318
- const nodeScope = await resolveTopicNodeScopeOrNull(
319
- ctx,
320
- String(args.topicId)
321
- );
322
- if (nodeScope) {
323
- return nodeScope;
324
- }
325
- throw new Error(`Topic not found: ${String(args.topicId)}`);
326
- }
327
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
328
- const mapped = asMappedProjectId(topic);
329
- if (mapped) {
330
- return {
331
- topicId: topic._id,
332
- projectId: mapped,
333
- tenantId: inherited.tenantId,
334
- workspaceId: inherited.workspaceId,
335
- source: "topic"
336
- };
337
- }
338
- return {
339
- topicId: topic._id,
340
- tenantId: inherited.tenantId,
341
- workspaceId: inherited.workspaceId,
342
- source: "topic"
343
- };
307
+ return await resolveScopeFromTopicId(ctx, args.topicId);
344
308
  }
345
309
  if (args.projectId) {
346
- let directTopic = null;
347
- try {
348
- directTopic = await ctx.db.get(
349
- args.projectId
350
- );
351
- } catch (error) {
352
- debugGraphPrimitiveFallback(
353
- "[topicScope] Failed to load direct project topic",
354
- {
355
- error,
356
- projectId: args.projectId
357
- }
358
- );
359
- }
360
- if (directTopic) {
361
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
362
- const mapped = asMappedProjectId(directTopic);
363
- return {
364
- topicId: directTopic._id,
365
- projectId: mapped ?? args.projectId,
366
- tenantId: inherited.tenantId,
367
- workspaceId: inherited.workspaceId,
368
- source: "topic_inferred"
369
- };
370
- }
371
- directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
372
- if (directTopic) {
373
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
374
- const mapped = asMappedProjectId(directTopic);
375
- return {
376
- topicId: directTopic._id,
377
- projectId: mapped ?? args.projectId,
378
- tenantId: inherited.tenantId,
379
- workspaceId: inherited.workspaceId,
380
- source: "topic_inferred"
381
- };
382
- }
383
- const topics = await findTopicsByScopeAlias(ctx, args.projectId);
384
- const primary = pickPrimaryTopic(topics);
385
- if (primary) {
386
- const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
387
- return {
388
- topicId: primary._id,
389
- projectId: args.projectId,
390
- tenantId: inherited.tenantId,
391
- workspaceId: inherited.workspaceId,
392
- source: "project_mapped_topic"
393
- };
394
- }
395
- const nodeScope = await resolveTopicNodeScopeOrNull(
396
- ctx,
397
- String(args.projectId)
398
- );
399
- if (nodeScope) {
400
- return {
401
- ...nodeScope,
402
- projectId: nodeScope.projectId ?? String(args.projectId)
403
- };
404
- }
405
- throw new Error(
406
- `Legacy project scope ${String(args.projectId)} has no mapped topic.`
407
- );
310
+ return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
408
311
  }
409
312
  throw new Error(
410
313
  "Missing scope: provide topicId (preferred) or legacy projectId alias."
411
314
  );
412
315
  }
316
+ async function resolveScopeFromTopicId(ctx, topicId) {
317
+ const topic = await resolveTopicDocFromTopicId(ctx, topicId);
318
+ if (topic) {
319
+ return await buildTopicScope(ctx, topic, "topic");
320
+ }
321
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
322
+ if (nodeScope) {
323
+ return nodeScope;
324
+ }
325
+ throw new Error(`Topic not found: ${String(topicId)}`);
326
+ }
327
+ async function resolveTopicDocFromTopicId(ctx, topicId) {
328
+ const direct = await tryReadTopicDoc(ctx, topicId, {
329
+ failureLog: "[topicScope] Failed to load topic by direct id",
330
+ idLogKey: "topicId"
331
+ });
332
+ if (direct) {
333
+ return direct;
334
+ }
335
+ const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
336
+ if (hostTopic) {
337
+ return hostTopic;
338
+ }
339
+ return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
340
+ }
341
+ async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
342
+ const directTopic = await resolveDirectLegacyProjectTopic(
343
+ ctx,
344
+ legacyProjectId
345
+ );
346
+ if (directTopic) {
347
+ return await buildTopicScope(ctx, directTopic, "topic_inferred", {
348
+ fallbackProjectId: legacyProjectId
349
+ });
350
+ }
351
+ const primary = pickPrimaryTopic(
352
+ await findTopicsByScopeAlias(ctx, legacyProjectId)
353
+ );
354
+ if (primary) {
355
+ return await buildTopicScope(ctx, primary, "project_mapped_topic", {
356
+ fallbackProjectId: legacyProjectId
357
+ });
358
+ }
359
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
360
+ if (nodeScope) {
361
+ return {
362
+ ...nodeScope,
363
+ projectId: nodeScope.projectId ?? legacyProjectId
364
+ };
365
+ }
366
+ throw new Error(
367
+ `Legacy project scope ${legacyProjectId} has no mapped topic.`
368
+ );
369
+ }
370
+ async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
371
+ const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
372
+ failureLog: "[topicScope] Failed to load direct project topic",
373
+ idLogKey: "projectId"
374
+ });
375
+ return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
376
+ }
377
+ async function tryReadTopicDoc(ctx, id, log) {
378
+ try {
379
+ return await ctx.db.get(id);
380
+ } catch (error) {
381
+ debugGraphPrimitiveFallback(log.failureLog, {
382
+ error,
383
+ [log.idLogKey]: id
384
+ });
385
+ return null;
386
+ }
387
+ }
388
+ async function buildTopicScope(ctx, topic, source, options = {}) {
389
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
390
+ const mapped = asMappedProjectId(topic);
391
+ return {
392
+ topicId: topic._id,
393
+ ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
394
+ tenantId: inherited.tenantId,
395
+ workspaceId: inherited.workspaceId,
396
+ source
397
+ };
398
+ }
413
399
  ({
414
400
  projectId: v.optional(v.string()),
415
401
  topicId: v.optional(v.string())
@@ -477,9 +463,10 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
477
463
  if (resolved.tenantId || resolved.workspaceId) {
478
464
  return resolved;
479
465
  }
480
- if (node.topicId) {
466
+ const topicId = normalizeScopeValue2(node.topicId);
467
+ if (topicId) {
481
468
  const topicScope = await resolveTopicProjectScope(ctx, {
482
- topicId: node.topicId
469
+ topicId
483
470
  });
484
471
  return {
485
472
  ...resolved,
@@ -499,33 +486,11 @@ async function resolveNodeScopeForWorkspaceIsolation(ctx, node) {
499
486
  }
500
487
  return resolved;
501
488
  }
502
-
503
- // src/epistemicBeliefs.helpers.ts
504
489
  v.id("epistemicNodes");
505
490
  var DEFAULT_CONFIDENCE_POLICY = {
506
491
  scoringMode: "after_worktree",
507
492
  tupleContradiction: normalizeTupleContradictionPolicy()
508
493
  };
509
- function throwStructuredMutationError(args) {
510
- const data = {
511
- structuredMutationError: true,
512
- message: args.message,
513
- status: args.status,
514
- code: args.code,
515
- invariantCode: args.invariantCode,
516
- suggestion: args.suggestion,
517
- details: args.details
518
- };
519
- const error = new ConvexError(
520
- data
521
- );
522
- error.status = args.status;
523
- error.code = args.code;
524
- error.invariantCode = args.invariantCode;
525
- error.suggestion = args.suggestion;
526
- error.details = args.details;
527
- throw error;
528
- }
529
494
  function buildBeliefConfidenceRow(args) {
530
495
  return {
531
496
  beliefId: args.beliefId,
@@ -600,7 +565,10 @@ function resolveBeliefStatus(node, metadata) {
600
565
  });
601
566
  }
602
567
  async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
603
- const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex("by_belief", (q) => q.eq("beliefId", beliefNodeId)).collect();
568
+ const clusterMembership = await ctx.db.query("worktreeBeliefCluster").withIndex(
569
+ "by_belief",
570
+ (q) => q.eq("beliefId", beliefNodeId)
571
+ ).collect();
604
572
  for (const membership of clusterMembership) {
605
573
  const worktree = await ctx.db.get(membership.worktreeId);
606
574
  if (worktree?.status === "completed" || worktree?.status === "merged") {
@@ -611,7 +579,10 @@ async function hasCompletedWorktreeForBelief(ctx, beliefNodeId) {
611
579
  }
612
580
  async function getActiveConfidencePolicy(ctx) {
613
581
  try {
614
- const activeConfig = await ctx.db.query("logicSprintScoring").withIndex("by_active", (q) => q.eq("isActive", true)).first();
582
+ const activeConfig = await ctx.db.query("logicSprintScoring").withIndex(
583
+ "by_active",
584
+ (q) => q.eq("isActive", true)
585
+ ).first();
615
586
  return {
616
587
  scoringMode: activeConfig?.confidencePolicy === "always" ? "always" : DEFAULT_CONFIDENCE_POLICY.scoringMode,
617
588
  tupleContradiction: normalizeTupleContradictionPolicy(
@@ -628,23 +599,6 @@ async function getActiveConfidencePolicy(ctx) {
628
599
  return DEFAULT_CONFIDENCE_POLICY;
629
600
  }
630
601
  }
631
- async function requireProjectWriteAccess(ctx, projectId, userId) {
632
- const hasAccess = await checkProjectAccess(
633
- ctx,
634
- projectId,
635
- userId
636
- );
637
- if (!hasAccess) {
638
- throwStructuredMutationError({
639
- message: `Project write access denied for topic ${projectId}.`,
640
- status: 403,
641
- code: "PROJECT_ACCESS_DENIED",
642
- invariantCode: "policy.scope_required",
643
- 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.",
644
- details: { topicId: projectId, principalId: userId }
645
- });
646
- }
647
- }
648
602
 
649
603
  // src/edges/contains.ts
650
604
  var containsPropagationSpec = {
@@ -781,7 +735,7 @@ var dependsOnPropagationSpec = {
781
735
  description: "Structural gating. Textbook conditional deduction when edge conditionals exist, otherwise damped dependency cascade through downstream chains."
782
736
  };
783
737
 
784
- // src/edges/derivedFrom.ts
738
+ // src/edges/derived-from.ts
785
739
  var derivedFromPropagationSpec = {
786
740
  edgeType: "derived_from",
787
741
  direction: "incoming",
@@ -834,7 +788,7 @@ var informsPropagationSpec = {
834
788
  description: "Evidence-bearing influence. Informs can chain through the graph with light per-hop damping."
835
789
  };
836
790
 
837
- // src/edges/propagationTypes.ts
791
+ // src/edges/propagation-types.ts
838
792
  function isPropagationTraversalDirection(direction) {
839
793
  return direction === "outgoing" || direction === "incoming";
840
794
  }
@@ -907,6 +861,9 @@ var testsPropagationSpec = {
907
861
  };
908
862
 
909
863
  // src/edges/index.ts
864
+ var canContinueTransitively2 = canContinueTransitively;
865
+ var canTraverseHop2 = canTraverseHop;
866
+ var isPropagationTraversalDirection2 = isPropagationTraversalDirection;
910
867
  var EDGE_PROPAGATION_SPECS = [
911
868
  supportsPropagationSpec,
912
869
  informsPropagationSpec,
@@ -923,16 +880,15 @@ function getEdgePropagationSpecs() {
923
880
  return EDGE_PROPAGATION_SPECS;
924
881
  }
925
882
  function getTraversalDirections(direction) {
926
- if (isPropagationTraversalDirection(direction)) {
883
+ if (isPropagationTraversalDirection2(direction)) {
927
884
  return [direction];
928
885
  }
929
886
  return ["outgoing", "incoming"];
930
887
  }
931
888
 
932
889
  // src/confidencePropagationDispatch.ts
933
- function resolveTraversalTargetNodeId(edge, direction) {
934
- const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
935
- return targetNodeId ?? void 0;
890
+ function nodeIdToCacheKey(nodeId) {
891
+ return String(nodeId);
936
892
  }
937
893
  function readNodeOpinion(node) {
938
894
  const metadata = node.metadata ?? {};
@@ -948,118 +904,354 @@ function readNodeOpinion(node) {
948
904
  return mkOpinion(0, 0, 1, 0.5);
949
905
  }
950
906
  }
907
+ function resolveTraversalTargetNodeId(edge, direction) {
908
+ const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
909
+ return targetNodeId ?? void 0;
910
+ }
911
+ function buildInitialState(sourceNodeId, sourceOpinion) {
912
+ return {
913
+ nodeId: sourceNodeId,
914
+ opinion: sourceOpinion,
915
+ hop: 0,
916
+ visitedNodeIds: /* @__PURE__ */ new Set([nodeIdToCacheKey(sourceNodeId)])
917
+ };
918
+ }
919
+ function extendVisited(currentVisited, targetNodeId) {
920
+ return /* @__PURE__ */ new Set([...currentVisited, nodeIdToCacheKey(targetNodeId)]);
921
+ }
922
+ function makeTransitiveState(current, targetNodeId, projectedOpinion, nextHop) {
923
+ return {
924
+ nodeId: targetNodeId,
925
+ opinion: projectedOpinion,
926
+ hop: nextHop,
927
+ visitedNodeIds: extendVisited(current.visitedNodeIds, targetNodeId)
928
+ };
929
+ }
930
+ function makeDispatchRecord(targetNodeId, spec, direction, edge, projectedOpinion, nextHop, result, existingDispatch) {
931
+ return {
932
+ targetNodeId,
933
+ edgeType: spec.edgeType,
934
+ traversedDirection: direction,
935
+ weight: edge.weight ?? 1,
936
+ opinion: projectedOpinion,
937
+ operator: result.operator,
938
+ rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
939
+ hop: nextHop
940
+ };
941
+ }
942
+ async function loadCachedNode(scope, nodeId) {
943
+ const cacheKey = nodeIdToCacheKey(nodeId);
944
+ if (!scope.nodeCache.has(cacheKey)) {
945
+ scope.nodeCache.set(cacheKey, await scope.args.getNode(nodeId));
946
+ }
947
+ return scope.nodeCache.get(cacheKey) ?? null;
948
+ }
949
+ async function collectTargetDispatch(state, nextHop, spec, direction, edge, queue, scope) {
950
+ const sourceScope = scope.args.sourceScope;
951
+ if (sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, sourceScope)) {
952
+ return;
953
+ }
954
+ const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
955
+ if (!targetNodeId) {
956
+ return;
957
+ }
958
+ const targetNodeIdKey = nodeIdToCacheKey(targetNodeId);
959
+ if (state.visitedNodeIds.has(targetNodeIdKey)) {
960
+ return;
961
+ }
962
+ const targetNode = await loadCachedNode(scope, targetNodeId);
963
+ if (targetNode?.nodeType !== "belief") {
964
+ return;
965
+ }
966
+ if (sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, sourceScope)) {
967
+ return;
968
+ }
969
+ const targetOpinion = scope.opinionCache.get(targetNodeIdKey) ?? readNodeOpinion(targetNode);
970
+ const result = spec.operator(state.opinion, targetOpinion, edge, {
971
+ hop: nextHop,
972
+ sourceNodeId: state.nodeId,
973
+ targetNodeId,
974
+ traversedDirection: direction,
975
+ spec
976
+ });
977
+ if (!(result && hasProjectedOpinionChanged(targetOpinion, result.opinion))) {
978
+ return;
979
+ }
980
+ const projectedOpinion = mkOpinion(
981
+ result.opinion.b,
982
+ result.opinion.d,
983
+ result.opinion.u,
984
+ result.opinion.a
985
+ );
986
+ scope.opinionCache.set(targetNodeIdKey, projectedOpinion);
987
+ const existingDispatch = scope.dispatchesByTargetId.get(targetNodeIdKey);
988
+ scope.dispatchesByTargetId.set(
989
+ targetNodeIdKey,
990
+ makeDispatchRecord(
991
+ targetNodeId,
992
+ spec,
993
+ direction,
994
+ edge,
995
+ projectedOpinion,
996
+ nextHop,
997
+ result,
998
+ existingDispatch
999
+ )
1000
+ );
1001
+ if (canContinueTransitively2(spec, nextHop)) {
1002
+ queue.push(
1003
+ makeTransitiveState(state, targetNodeId, projectedOpinion, nextHop)
1004
+ );
1005
+ }
1006
+ }
1007
+ async function processTraversalSpec(state, nextHop, spec, queue, scope) {
1008
+ const sourceNodeId = state.nodeId;
1009
+ for (const direction of getTraversalDirections(spec.direction)) {
1010
+ const edges = await scope.args.queryEdges({
1011
+ nodeId: sourceNodeId,
1012
+ spec,
1013
+ direction,
1014
+ hop: nextHop
1015
+ });
1016
+ for (const edge of edges) {
1017
+ await collectTargetDispatch(
1018
+ state,
1019
+ nextHop,
1020
+ spec,
1021
+ direction,
1022
+ edge,
1023
+ queue,
1024
+ scope
1025
+ );
1026
+ }
1027
+ }
1028
+ }
1029
+ async function processQueuedState(state, queue, scope) {
1030
+ const nextHop = state.hop + 1;
1031
+ for (const spec of scope.traversalSpecs) {
1032
+ if (!canTraverseHop2(spec, nextHop)) {
1033
+ continue;
1034
+ }
1035
+ await processTraversalSpec(state, nextHop, spec, queue, scope);
1036
+ }
1037
+ }
1038
+ function sortDispatches(dispatches) {
1039
+ return Array.from(dispatches).sort((left, right) => {
1040
+ if (left.hop !== right.hop) {
1041
+ return left.hop - right.hop;
1042
+ }
1043
+ return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
1044
+ });
1045
+ }
951
1046
  async function collectConfidencePropagationDispatches(args) {
952
1047
  const dispatchesByTargetId = /* @__PURE__ */ new Map();
953
1048
  const opinionCache = /* @__PURE__ */ new Map();
954
1049
  const nodeCache = /* @__PURE__ */ new Map();
955
1050
  const traversalSpecs = args.traversalSpecs ?? getEdgePropagationSpecs();
1051
+ const scope = {
1052
+ args,
1053
+ dispatchesByTargetId,
1054
+ opinionCache,
1055
+ nodeCache,
1056
+ traversalSpecs
1057
+ };
956
1058
  const queue = [
957
- {
958
- nodeId: args.sourceNodeId,
959
- opinion: args.sourceOpinion,
960
- hop: 0,
961
- visitedNodeIds: /* @__PURE__ */ new Set([String(args.sourceNodeId)])
962
- }
1059
+ buildInitialState(args.sourceNodeId, args.sourceOpinion)
963
1060
  ];
964
- const loadNode = async (nodeId) => {
965
- const cacheKey = String(nodeId);
966
- if (!nodeCache.has(cacheKey)) {
967
- nodeCache.set(cacheKey, await args.getNode(nodeId));
968
- }
969
- return nodeCache.get(cacheKey) ?? null;
970
- };
971
1061
  while (queue.length > 0) {
972
1062
  const state = queue.shift();
973
1063
  if (!state) {
974
1064
  continue;
975
1065
  }
976
- for (const spec of traversalSpecs) {
977
- const nextHop = state.hop + 1;
978
- if (!canTraverseHop(spec, nextHop)) {
979
- continue;
980
- }
981
- for (const direction of getTraversalDirections(spec.direction)) {
982
- const edges = await args.queryEdges({
983
- nodeId: state.nodeId,
984
- spec,
985
- direction,
986
- hop: nextHop
987
- });
988
- for (const edge of edges) {
989
- if (args.sourceScope && !edgeMatchesWorkspaceReasoningScope(edge, args.sourceScope)) {
990
- continue;
991
- }
992
- const targetNodeId = resolveTraversalTargetNodeId(edge, direction);
993
- if (!targetNodeId) {
994
- continue;
995
- }
996
- if (state.visitedNodeIds.has(String(targetNodeId))) {
997
- continue;
998
- }
999
- const targetNode = await loadNode(targetNodeId);
1000
- if (!targetNode || targetNode.nodeType !== "belief") {
1001
- continue;
1002
- }
1003
- if (args.sourceScope && !nodeMatchesWorkspaceReasoningScope(targetNode, args.sourceScope)) {
1004
- continue;
1005
- }
1006
- const cacheKey = String(targetNodeId);
1007
- const targetOpinion = opinionCache.get(cacheKey) ?? readNodeOpinion(targetNode);
1008
- const result = spec.operator(state.opinion, targetOpinion, edge, {
1009
- hop: nextHop,
1010
- sourceNodeId: state.nodeId,
1011
- targetNodeId,
1012
- traversedDirection: direction,
1013
- spec
1014
- });
1015
- if (!result || !hasProjectedOpinionChanged(targetOpinion, result.opinion)) {
1016
- continue;
1017
- }
1018
- const projectedOpinion = mkOpinion(
1019
- result.opinion.b,
1020
- result.opinion.d,
1021
- result.opinion.u,
1022
- result.opinion.a
1023
- );
1024
- opinionCache.set(cacheKey, projectedOpinion);
1025
- const existingDispatch = dispatchesByTargetId.get(cacheKey);
1026
- dispatchesByTargetId.set(cacheKey, {
1027
- targetNodeId,
1028
- edgeType: spec.edgeType,
1029
- traversedDirection: direction,
1030
- weight: edge.weight ?? 1,
1031
- opinion: projectedOpinion,
1032
- operator: result.operator,
1033
- rationale: existingDispatch ? `${existingDispatch.rationale}; ${result.rationale}` : result.rationale,
1034
- hop: nextHop
1035
- });
1036
- if (canContinueTransitively(spec, nextHop)) {
1037
- queue.push({
1038
- nodeId: targetNodeId,
1039
- opinion: projectedOpinion,
1040
- hop: nextHop,
1041
- visitedNodeIds: /* @__PURE__ */ new Set([
1042
- ...state.visitedNodeIds,
1043
- String(targetNodeId)
1044
- ])
1045
- });
1046
- }
1047
- }
1048
- }
1049
- }
1066
+ await processQueuedState(state, queue, scope);
1050
1067
  }
1051
- return Array.from(dispatchesByTargetId.values()).sort((left, right) => {
1052
- if (left.hop !== right.hop) {
1053
- return left.hop - right.hop;
1054
- }
1055
- return String(left.targetNodeId).localeCompare(String(right.targetNodeId));
1056
- });
1068
+ return sortDispatches(dispatchesByTargetId.values());
1057
1069
  }
1058
1070
 
1059
1071
  // src/epistemicBeliefs.confidence.ts
1072
+ function isRecord(value) {
1073
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1074
+ }
1075
+ function readConvexId(value) {
1076
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1077
+ }
1078
+ function readOptionalBoolean(value) {
1079
+ return typeof value === "boolean" ? value : void 0;
1080
+ }
1081
+ function readOptionalNumber(value) {
1082
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1083
+ }
1084
+ function readOptionalString(value) {
1085
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1086
+ }
1087
+ function readRecord(value) {
1088
+ return isRecord(value) ? value : void 0;
1089
+ }
1090
+ function readConfidenceBeliefNode(value) {
1091
+ if (!isRecord(value)) {
1092
+ return null;
1093
+ }
1094
+ const id = readConvexId(value._id);
1095
+ const nodeType = readOptionalString(value.nodeType);
1096
+ const projectId = readOptionalString(value.projectId);
1097
+ if (!(id && nodeType === "belief" && projectId)) {
1098
+ return null;
1099
+ }
1100
+ const node = {
1101
+ _id: id,
1102
+ nodeType,
1103
+ projectId
1104
+ };
1105
+ const confidence = readOptionalNumber(value.confidence);
1106
+ const epistemicLayer = readOptionalString(value.epistemicLayer);
1107
+ const globalId = readOptionalString(value.globalId);
1108
+ const metadata = readRecord(value.metadata);
1109
+ const opinionA = readOptionalNumber(value.opinion_a);
1110
+ const opinionB = readOptionalNumber(value.opinion_b);
1111
+ const opinionD = readOptionalNumber(value.opinion_d);
1112
+ const opinionU = readOptionalNumber(value.opinion_u);
1113
+ const predictionMeta = readRecord(value.predictionMeta);
1114
+ const publicationStatus = readOptionalString(value.publicationStatus);
1115
+ const status = readOptionalString(value.status);
1116
+ const tenantId = readOptionalString(value.tenantId);
1117
+ const topicId = readOptionalString(value.topicId);
1118
+ const tupleContradicted = readOptionalBoolean(value.tupleContradicted);
1119
+ const workspaceId = readOptionalString(value.workspaceId);
1120
+ if (confidence !== void 0) {
1121
+ node.confidence = confidence;
1122
+ }
1123
+ if (epistemicLayer !== void 0) {
1124
+ node.epistemicLayer = epistemicLayer;
1125
+ }
1126
+ if (globalId !== void 0) {
1127
+ node.globalId = globalId;
1128
+ }
1129
+ if (metadata !== void 0) {
1130
+ node.metadata = metadata;
1131
+ }
1132
+ if (opinionA !== void 0) {
1133
+ node.opinion_a = opinionA;
1134
+ }
1135
+ if (opinionB !== void 0) {
1136
+ node.opinion_b = opinionB;
1137
+ }
1138
+ if (opinionD !== void 0) {
1139
+ node.opinion_d = opinionD;
1140
+ }
1141
+ if (opinionU !== void 0) {
1142
+ node.opinion_u = opinionU;
1143
+ }
1144
+ if (predictionMeta !== void 0) {
1145
+ node.predictionMeta = predictionMeta;
1146
+ }
1147
+ if (publicationStatus !== void 0) {
1148
+ node.publicationStatus = publicationStatus;
1149
+ }
1150
+ if (status !== void 0) {
1151
+ node.status = status;
1152
+ }
1153
+ if (tenantId !== void 0) {
1154
+ node.tenantId = tenantId;
1155
+ }
1156
+ if (topicId !== void 0) {
1157
+ node.topicId = topicId;
1158
+ }
1159
+ if (tupleContradicted !== void 0) {
1160
+ node.tupleContradicted = tupleContradicted;
1161
+ }
1162
+ if (workspaceId !== void 0) {
1163
+ node.workspaceId = workspaceId;
1164
+ }
1165
+ return node;
1166
+ }
1167
+ function readPropagationEdge(value) {
1168
+ if (!isRecord(value)) {
1169
+ return null;
1170
+ }
1171
+ const edgeType = readOptionalString(value.edgeType);
1172
+ if (!edgeType) {
1173
+ return null;
1174
+ }
1175
+ const edge = { edgeType };
1176
+ const fromNodeId = readConvexId(value.fromNodeId);
1177
+ const tenantId = readOptionalString(value.tenantId);
1178
+ const toNodeId = readConvexId(value.toNodeId);
1179
+ const weight = readOptionalNumber(value.weight);
1180
+ const workspaceId = readOptionalString(value.workspaceId);
1181
+ if (fromNodeId !== void 0) {
1182
+ edge.fromNodeId = fromNodeId;
1183
+ }
1184
+ if (tenantId !== void 0) {
1185
+ edge.tenantId = tenantId;
1186
+ }
1187
+ if (toNodeId !== void 0) {
1188
+ edge.toNodeId = toNodeId;
1189
+ }
1190
+ if (weight !== void 0) {
1191
+ edge.weight = weight;
1192
+ }
1193
+ if (workspaceId !== void 0) {
1194
+ edge.workspaceId = workspaceId;
1195
+ }
1196
+ return edge;
1197
+ }
1198
+ function readRowList(values, reader) {
1199
+ return values.flatMap((value) => {
1200
+ const row = reader(value);
1201
+ return row ? [row] : [];
1202
+ });
1203
+ }
1060
1204
  async function applyBeliefConfidenceChange(ctx, args) {
1061
1205
  const now = Date.now();
1062
- const node = await ctx.db.get(args.nodeId);
1206
+ const node = await requireConfidenceBeliefNode(ctx, args);
1207
+ const state = await buildConfidenceChangeState(ctx, node, args);
1208
+ await assertConfidenceScoringPolicySatisfied(ctx, args, state);
1209
+ const tupleContradictionId = await createTupleContradictionIfNeeded(
1210
+ ctx,
1211
+ args,
1212
+ node,
1213
+ state
1214
+ );
1215
+ await patchBeliefConfidenceState(ctx, args, state);
1216
+ await scheduleFirstScoringThemeEdges(ctx, args, node, state);
1217
+ const beliefConfidenceId = await insertBeliefConfidenceRecord(
1218
+ ctx,
1219
+ args,
1220
+ state,
1221
+ tupleContradictionId,
1222
+ now
1223
+ );
1224
+ await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
1225
+ nodeId: args.nodeId,
1226
+ operation: "upsert"
1227
+ });
1228
+ await insertConfidenceAudit(
1229
+ ctx,
1230
+ args,
1231
+ node,
1232
+ state,
1233
+ tupleContradictionId,
1234
+ now
1235
+ );
1236
+ await insertTupleTransitionAuditIfNeeded(
1237
+ ctx,
1238
+ args,
1239
+ node,
1240
+ state,
1241
+ tupleContradictionId,
1242
+ now
1243
+ );
1244
+ await scheduleConfidenceFollowups(ctx, args, node, state);
1245
+ return {
1246
+ nodeId: args.nodeId,
1247
+ previousConfidence: state.previousConfidence,
1248
+ newConfidence: state.derivedConfidence,
1249
+ opinion: state.nextOpinion,
1250
+ beliefConfidenceId
1251
+ };
1252
+ }
1253
+ async function requireConfidenceBeliefNode(ctx, args) {
1254
+ const node = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
1063
1255
  if (!node) {
1064
1256
  throwStructuredMutationError({
1065
1257
  message: "Node not found.",
@@ -1070,59 +1262,28 @@ async function applyBeliefConfidenceChange(ctx, args) {
1070
1262
  details: { nodeId: args.nodeId }
1071
1263
  });
1072
1264
  }
1073
- if (node.nodeType !== "belief") {
1074
- throwStructuredMutationError({
1075
- 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.`,
1076
- status: 400,
1077
- code: "INVALID_ARGUMENT",
1078
- invariantCode: "entity.no_confidence",
1079
- suggestion: "Use entityLifecycle.updateEntityAttributes for entity mutations. appendSlScoring is for belief nodes only.",
1080
- details: { nodeId: args.nodeId, nodeType: node.nodeType }
1081
- });
1082
- }
1083
- if (!node.projectId) {
1084
- throwStructuredMutationError({
1085
- message: "Belief has no project scope.",
1086
- status: 400,
1087
- code: "MISSING_SCOPE",
1088
- invariantCode: "belief.project_required",
1089
- suggestion: "Belief must have a projectId before SL scoring can be appended.",
1090
- details: { nodeId: args.nodeId }
1091
- });
1092
- }
1093
- await requireProjectWriteAccess(
1094
- ctx,
1095
- node.projectId,
1096
- args.authenticatedUserId
1097
- );
1098
- const existingMetadata = node.metadata || {};
1265
+ await requireScopeWriteAccess(ctx, node.projectId, args.authenticatedUserId);
1266
+ return node;
1267
+ }
1268
+ async function buildConfidenceChangeState(ctx, node, args) {
1269
+ const existingMetadata = readNodeMetadata(node);
1099
1270
  const currentBeliefStatus = resolveBeliefStatus(node, existingMetadata);
1100
1271
  const confidencePolicy = await getActiveConfidencePolicy(ctx);
1101
- if (confidencePolicy.scoringMode === "after_worktree" && isPreValidationBeliefStatus(currentBeliefStatus)) {
1102
- const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
1103
- ctx,
1104
- args.nodeId
1105
- );
1106
- if (!hasCompletedWorktree) {
1107
- throwStructuredMutationError({
1108
- message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
1109
- status: 409,
1110
- code: "CONFLICT",
1111
- invariantCode: "belief.confidence_append_only",
1112
- suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
1113
- details: { nodeId: args.nodeId }
1114
- });
1115
- }
1116
- }
1117
1272
  const previousConfidence = node.confidence || 0.5;
1118
1273
  const predictionMeta = node.predictionMeta || existingMetadata.predictionMeta;
1119
1274
  const previousOpinion = readBeliefOpinionSnapshot(node, existingMetadata);
1120
- const slB = args.belief;
1121
- const slD = args.disbelief;
1122
- const slU = args.uncertainty;
1123
- const slA = args.baseRate ?? 0.5;
1124
- const nextOpinion = { b: slB, d: slD, u: slU, a: slA };
1125
- const derivedConfidence = confidenceFromSL(slB, slD, slU, slA);
1275
+ const nextOpinion = {
1276
+ b: args.belief,
1277
+ d: args.disbelief,
1278
+ u: args.uncertainty,
1279
+ a: args.baseRate ?? 0.5
1280
+ };
1281
+ const derivedConfidence = confidenceFromSL(
1282
+ nextOpinion.b,
1283
+ nextOpinion.d,
1284
+ nextOpinion.u,
1285
+ nextOpinion.a
1286
+ );
1126
1287
  const isFirstScoring = typeof node.confidence !== "number" || !Number.isFinite(node.confidence);
1127
1288
  const previousTupleContradicted = readTupleContradictedFlag(node.tupleContradicted) ?? readTupleContradictedFlag(existingMetadata.tupleContradicted) ?? detectTupleContradiction(
1128
1289
  previousOpinion,
@@ -1143,79 +1304,121 @@ async function applyBeliefConfidenceChange(ctx, args) {
1143
1304
  predictionMeta,
1144
1305
  metadata: existingMetadata
1145
1306
  });
1146
- let tupleContradictionId;
1147
- if (tupleTransition.crossedIntoTupleContradiction) {
1148
- tupleContradictionId = await ctx.runMutation(
1149
- "contradictions:create",
1150
- {
1151
- projectId: node.projectId,
1152
- topicId: node.topicId,
1153
- beliefId: args.nodeId,
1154
- beliefBId: args.nodeId,
1155
- supportingInsightIds: [],
1156
- contradictingInsightIds: [],
1157
- severity: deriveTupleContradictionSeverity(node),
1158
- source: "tuple_space",
1159
- detectionMethod: "agent",
1160
- description: tupleContradictionDescription,
1161
- createdBy: args.authenticatedUserId
1162
- }
1163
- );
1307
+ const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
1308
+ return {
1309
+ confidencePolicy,
1310
+ currentBeliefStatus,
1311
+ derivedConfidence,
1312
+ existingMetadata,
1313
+ isFirstScoring,
1314
+ newBeliefStatus,
1315
+ nextOpinion,
1316
+ previousConfidence,
1317
+ previousTupleContradicted,
1318
+ storedRationale,
1319
+ tupleContradictionDescription,
1320
+ tupleTransition
1321
+ };
1322
+ }
1323
+ function readNodeMetadata(node) {
1324
+ return node.metadata ?? {};
1325
+ }
1326
+ async function assertConfidenceScoringPolicySatisfied(ctx, args, state) {
1327
+ if (state.confidencePolicy.scoringMode !== "after_worktree" || !isPreValidationBeliefStatus(state.currentBeliefStatus)) {
1328
+ return;
1164
1329
  }
1330
+ const hasCompletedWorktree = await hasCompletedWorktreeForBelief(
1331
+ ctx,
1332
+ args.nodeId
1333
+ );
1334
+ if (hasCompletedWorktree) {
1335
+ return;
1336
+ }
1337
+ throwStructuredMutationError({
1338
+ message: "Cannot score belief before worktree completion. Complete a worktree that tests this belief first.",
1339
+ status: 409,
1340
+ code: "CONFLICT",
1341
+ invariantCode: "belief.confidence_append_only",
1342
+ suggestion: "Complete a worktree linked to this belief before recording SL scoring.",
1343
+ details: { nodeId: args.nodeId }
1344
+ });
1345
+ }
1346
+ async function createTupleContradictionIfNeeded(ctx, args, node, state) {
1347
+ if (!state.tupleTransition.crossedIntoTupleContradiction) {
1348
+ return;
1349
+ }
1350
+ return await ctx.runMutation("contradictions:create", {
1351
+ projectId: node.projectId,
1352
+ topicId: node.topicId,
1353
+ beliefId: args.nodeId,
1354
+ beliefBId: args.nodeId,
1355
+ supportingInsightIds: [],
1356
+ contradictingInsightIds: [],
1357
+ severity: deriveTupleContradictionSeverity(node),
1358
+ source: "tuple_space",
1359
+ detectionMethod: "agent",
1360
+ description: state.tupleContradictionDescription,
1361
+ createdBy: args.authenticatedUserId
1362
+ });
1363
+ }
1364
+ async function patchBeliefConfidenceState(ctx, args, state) {
1165
1365
  await ctx.db.patch(args.nodeId, {
1166
- confidence: derivedConfidence,
1167
- beliefStatus: newBeliefStatus,
1168
- tupleContradicted: tupleTransition.tupleContradicted,
1169
- updatedAt: now,
1170
- // Store SL opinion fields at node level for fast access
1171
- opinion_b: slB,
1172
- opinion_d: slD,
1173
- opinion_u: slU,
1174
- opinion_a: slA,
1366
+ confidence: state.derivedConfidence,
1367
+ beliefStatus: state.newBeliefStatus,
1368
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1369
+ updatedAt: Date.now(),
1370
+ opinion_b: state.nextOpinion.b,
1371
+ opinion_d: state.nextOpinion.d,
1372
+ opinion_u: state.nextOpinion.u,
1373
+ opinion_a: state.nextOpinion.a,
1175
1374
  metadata: {
1176
- ...existingMetadata,
1177
- beliefStatus: newBeliefStatus,
1178
- slBelief: slB,
1179
- slDisbelief: slD,
1180
- slUncertainty: slU,
1181
- slBaseRate: slA,
1182
- tupleContradicted: tupleTransition.tupleContradicted
1375
+ ...state.existingMetadata,
1376
+ beliefStatus: state.newBeliefStatus,
1377
+ slBelief: state.nextOpinion.b,
1378
+ slDisbelief: state.nextOpinion.d,
1379
+ slUncertainty: state.nextOpinion.u,
1380
+ slBaseRate: state.nextOpinion.a,
1381
+ tupleContradicted: state.tupleTransition.tupleContradicted
1183
1382
  }
1184
1383
  });
1185
- if (isFirstScoring) {
1186
- const nodeTopicId = node.topicId;
1187
- const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
1188
- "by_topic",
1189
- (q) => q.eq("topicId", nodeTopicId || node.projectId)
1190
- ).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
1191
- for (const theme of themeNodes) {
1192
- if (theme.globalId && node.globalId) {
1193
- await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
1194
- globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
1195
- fromGlobalId: node.globalId,
1196
- toGlobalId: theme.globalId,
1197
- edgeType: "relates_to_thesis",
1198
- weight: derivedConfidence,
1199
- createdBy: args.authenticatedUserId,
1200
- topicId: String(node.projectId),
1201
- fromNodeType: "belief",
1202
- toNodeType: "theme",
1203
- fromLayer: "L3",
1204
- toLayer: "L3"
1205
- });
1206
- }
1384
+ }
1385
+ async function scheduleFirstScoringThemeEdges(ctx, args, node, state) {
1386
+ if (!state.isFirstScoring) {
1387
+ return;
1388
+ }
1389
+ const themeNodes = await ctx.db.query("epistemicNodes").withIndex(
1390
+ "by_topic",
1391
+ (q) => q.eq("topicId", node.topicId || node.projectId)
1392
+ ).filter((q) => q.eq(q.field("nodeType"), "theme")).collect();
1393
+ for (const theme of themeNodes) {
1394
+ if (!(theme.globalId && node.globalId)) {
1395
+ continue;
1207
1396
  }
1397
+ await ctx.scheduler.runAfter(0, internal.neo4jEdgeAPI.createEdge, {
1398
+ globalId: `edge-${node.globalId}-relates_to_thesis-${theme.globalId}`,
1399
+ fromGlobalId: node.globalId,
1400
+ toGlobalId: theme.globalId,
1401
+ edgeType: "relates_to_thesis",
1402
+ weight: state.derivedConfidence,
1403
+ createdBy: args.authenticatedUserId,
1404
+ topicId: String(node.projectId),
1405
+ fromNodeType: "belief",
1406
+ toNodeType: "theme",
1407
+ fromLayer: "L3",
1408
+ toLayer: "L3"
1409
+ });
1208
1410
  }
1209
- const storedRationale = args.rationale ?? `Confidence changed from ${previousConfidence.toFixed(2)} (nodeId: ${args.nodeId})`;
1210
- const beliefConfidenceId = await ctx.db.insert("beliefConfidence", {
1411
+ }
1412
+ async function insertBeliefConfidenceRecord(ctx, args, state, tupleContradictionId, now) {
1413
+ return await ctx.db.insert("beliefConfidence", {
1211
1414
  ...buildBeliefConfidenceRow({
1212
1415
  beliefId: args.nodeId,
1213
- belief: slB,
1214
- disbelief: slD,
1215
- uncertainty: slU,
1216
- baseRate: slA,
1416
+ belief: state.nextOpinion.b,
1417
+ disbelief: state.nextOpinion.d,
1418
+ uncertainty: state.nextOpinion.u,
1419
+ baseRate: state.nextOpinion.a,
1217
1420
  trigger: args.trigger,
1218
- rationale: storedRationale,
1421
+ rationale: state.storedRationale,
1219
1422
  assessedBy: args.authenticatedUserId,
1220
1423
  assessedAt: now,
1221
1424
  slOperator: args.slOperator,
@@ -1224,25 +1427,23 @@ async function applyBeliefConfidenceChange(ctx, args) {
1224
1427
  triggeringWorktreeId: args.triggeringWorktreeId
1225
1428
  })
1226
1429
  });
1227
- await ctx.scheduler.runAfter(0, internal.neo4jSync.syncNodeToNeo4j, {
1228
- nodeId: args.nodeId,
1229
- operation: "upsert"
1230
- });
1430
+ }
1431
+ async function insertConfidenceAudit(ctx, args, node, state, tupleContradictionId, now) {
1231
1432
  await ctx.db.insert("epistemicAudit", {
1232
1433
  entityType: "belief",
1233
1434
  entityId: args.nodeId,
1234
1435
  changeType: "confidence_changed",
1235
1436
  previousState: {
1236
- confidence: previousConfidence,
1237
- tupleContradicted: previousTupleContradicted
1437
+ confidence: state.previousConfidence,
1438
+ tupleContradicted: state.previousTupleContradicted
1238
1439
  },
1239
1440
  newState: {
1240
- opinion: nextOpinion,
1241
- confidence: derivedConfidence,
1441
+ opinion: state.nextOpinion,
1442
+ confidence: state.derivedConfidence,
1242
1443
  trigger: args.trigger,
1243
- rationale: storedRationale,
1244
- tupleContradicted: tupleTransition.tupleContradicted,
1245
- tupleContradictionPolicy: tupleTransition.policy,
1444
+ rationale: state.storedRationale,
1445
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1446
+ tupleContradictionPolicy: state.tupleTransition.policy,
1246
1447
  ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1247
1448
  },
1248
1449
  changedBy: args.authenticatedUserId,
@@ -1251,28 +1452,39 @@ async function applyBeliefConfidenceChange(ctx, args) {
1251
1452
  projectId: node.projectId,
1252
1453
  topicId: node.topicId
1253
1454
  });
1254
- if (tupleTransition.crossedIntoTupleContradiction || tupleTransition.crossedOutOfTupleContradiction) {
1255
- await ctx.db.insert("epistemicAudit", {
1256
- entityType: "belief",
1257
- entityId: args.nodeId,
1258
- changeType: "updated",
1259
- previousState: { tupleContradicted: previousTupleContradicted },
1260
- newState: {
1261
- tupleContradicted: tupleTransition.tupleContradicted,
1262
- action: tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
1263
- opinion: nextOpinion,
1264
- tupleContradictionPolicy: tupleTransition.policy,
1265
- ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1266
- },
1267
- 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.`,
1268
- changedBy: args.authenticatedUserId,
1269
- isAgent: false,
1270
- changedAt: now,
1271
- projectId: node.projectId,
1272
- topicId: node.topicId
1273
- });
1455
+ }
1456
+ async function insertTupleTransitionAuditIfNeeded(ctx, args, node, state, tupleContradictionId, now) {
1457
+ if (!(state.tupleTransition.crossedIntoTupleContradiction || state.tupleTransition.crossedOutOfTupleContradiction)) {
1458
+ return;
1459
+ }
1460
+ await ctx.db.insert("epistemicAudit", {
1461
+ entityType: "belief",
1462
+ entityId: args.nodeId,
1463
+ changeType: "updated",
1464
+ previousState: { tupleContradicted: state.previousTupleContradicted },
1465
+ newState: {
1466
+ tupleContradicted: state.tupleTransition.tupleContradicted,
1467
+ action: state.tupleTransition.crossedIntoTupleContradiction ? "tuple_contradiction_detected" : "tuple_contradiction_cleared",
1468
+ opinion: state.nextOpinion,
1469
+ tupleContradictionPolicy: state.tupleTransition.policy,
1470
+ ...tupleContradictionId ? { tupleContradictionId: String(tupleContradictionId) } : {}
1471
+ },
1472
+ rationale: tupleAuditRationale(state),
1473
+ changedBy: args.authenticatedUserId,
1474
+ isAgent: false,
1475
+ changedAt: now,
1476
+ projectId: node.projectId,
1477
+ topicId: node.topicId
1478
+ });
1479
+ }
1480
+ function tupleAuditRationale(state) {
1481
+ if (state.tupleTransition.crossedIntoTupleContradiction) {
1482
+ return state.tupleContradictionDescription;
1274
1483
  }
1275
- if (Math.abs(derivedConfidence - previousConfidence) >= 0.15) {
1484
+ return `Tuple-space contradiction cleared: b=${state.nextOpinion.b.toFixed(2)}, d=${state.nextOpinion.d.toFixed(2)} no longer exceed the configured policy thresholds.`;
1485
+ }
1486
+ async function scheduleConfidenceFollowups(ctx, args, node, state) {
1487
+ if (Math.abs(state.derivedConfidence - state.previousConfidence) >= 0.15) {
1276
1488
  await ctx.scheduler.runAfter(
1277
1489
  5e3,
1278
1490
  internal.bi.contradictionSemanticDetector.scanAffectedBeliefs,
@@ -1289,13 +1501,6 @@ async function applyBeliefConfidenceChange(ctx, args) {
1289
1501
  { nodeId: args.nodeId }
1290
1502
  );
1291
1503
  }
1292
- return {
1293
- nodeId: args.nodeId,
1294
- previousConfidence,
1295
- newConfidence: derivedConfidence,
1296
- opinion: { b: slB, d: slD, u: slU, a: slA },
1297
- beliefConfidenceId
1298
- };
1299
1504
  }
1300
1505
  function propagationPressureLabel(edgeType, weight) {
1301
1506
  if (edgeType === "contradicts" || edgeType === "refutes") {
@@ -1323,7 +1528,7 @@ internalMutation({
1323
1528
  args.opinion_u,
1324
1529
  args.opinion_a
1325
1530
  );
1326
- const sourceNode = await ctx.db.get(args.nodeId);
1531
+ const sourceNode = readConfidenceBeliefNode(await ctx.db.get(args.nodeId));
1327
1532
  const sourceScope = await resolveNodeScopeForWorkspaceIsolation(
1328
1533
  ctx,
1329
1534
  sourceNode
@@ -1332,16 +1537,20 @@ internalMutation({
1332
1537
  sourceNodeId: args.nodeId,
1333
1538
  sourceOpinion,
1334
1539
  sourceScope,
1335
- queryEdges: async ({ nodeId, spec, direction }) => {
1336
- return await ctx.db.query("epistemicEdges").withIndex(
1540
+ queryEdges: async ({ nodeId, spec, direction }) => readRowList(
1541
+ await ctx.db.query("epistemicEdges").withIndex(
1337
1542
  direction === "outgoing" ? "by_from_type" : "by_to_type",
1338
1543
  (q) => direction === "outgoing" ? q.eq("fromNodeId", nodeId).eq("edgeType", spec.edgeType) : q.eq("toNodeId", nodeId).eq("edgeType", spec.edgeType)
1339
- ).collect();
1340
- },
1341
- getNode: async (nodeId) => await ctx.db.get(nodeId)
1544
+ ).collect(),
1545
+ readPropagationEdge
1546
+ ),
1547
+ getNode: async (nodeId) => readConfidenceBeliefNode(await ctx.db.get(nodeId))
1342
1548
  });
1343
1549
  for (const dispatch of dispatches) {
1344
- const pressureLabel = propagationPressureLabel(dispatch.edgeType, dispatch.weight);
1550
+ const pressureLabel = propagationPressureLabel(
1551
+ dispatch.edgeType,
1552
+ dispatch.weight
1553
+ );
1345
1554
  await applyBeliefConfidenceChange(ctx, {
1346
1555
  nodeId: dispatch.targetNodeId,
1347
1556
  belief: dispatch.opinion.b,
@@ -1371,9 +1580,7 @@ var ACTIVE_CONTRADICTION_STATUSES = /* @__PURE__ */ new Set([
1371
1580
  "investigating",
1372
1581
  "accepted_as_permanent"
1373
1582
  ]);
1374
- var DEPENDENT_EDGE_TYPES = /* @__PURE__ */ new Set([
1375
- "depends_on"
1376
- ]);
1583
+ var DEPENDENT_EDGE_TYPES = /* @__PURE__ */ new Set(["depends_on"]);
1377
1584
  function classifyContradictionStatus(status) {
1378
1585
  if (typeof status !== "string") {
1379
1586
  return "active";
@@ -1386,6 +1593,99 @@ function classifyContradictionStatus(status) {
1386
1593
  }
1387
1594
  return "resolved";
1388
1595
  }
1596
+ function isRecord2(value) {
1597
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1598
+ }
1599
+ function readOptionalNumber2(value) {
1600
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1601
+ }
1602
+ function readOptionalString2(value) {
1603
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1604
+ }
1605
+ function readConvexId2(value) {
1606
+ const normalized = readOptionalString2(value);
1607
+ return normalized;
1608
+ }
1609
+ function readMetricNodeDoc(value) {
1610
+ if (!isRecord2(value)) {
1611
+ return null;
1612
+ }
1613
+ const id = readConvexId2(value._id);
1614
+ const nodeType = readOptionalString2(value.nodeType);
1615
+ if (!(id && nodeType)) {
1616
+ return null;
1617
+ }
1618
+ const node = { _id: id, nodeType };
1619
+ const globalId = readOptionalString2(value.globalId);
1620
+ if (globalId !== void 0) {
1621
+ node.globalId = globalId;
1622
+ }
1623
+ if ("metadata" in value) {
1624
+ node.metadata = value.metadata;
1625
+ }
1626
+ const status = readOptionalString2(value.status);
1627
+ if (status !== void 0) {
1628
+ node.status = status;
1629
+ }
1630
+ return node;
1631
+ }
1632
+ function readIncomingEdgeRow(value) {
1633
+ if (!isRecord2(value)) {
1634
+ return null;
1635
+ }
1636
+ const fromNodeId = readOptionalString2(value.fromNodeId);
1637
+ if (!fromNodeId) {
1638
+ return null;
1639
+ }
1640
+ const edge = { fromNodeId };
1641
+ const id = readConvexId2(value._id);
1642
+ if (id !== void 0) {
1643
+ edge._id = id;
1644
+ }
1645
+ const edgeType = readOptionalString2(value.edgeType);
1646
+ if (edgeType !== void 0) {
1647
+ edge.edgeType = edgeType;
1648
+ }
1649
+ const fromGlobalId = readOptionalString2(value.fromGlobalId);
1650
+ if (fromGlobalId !== void 0) {
1651
+ edge.fromGlobalId = fromGlobalId;
1652
+ }
1653
+ const fromUuid = readOptionalString2(value.fromUuid);
1654
+ if (fromUuid !== void 0) {
1655
+ edge.fromUuid = fromUuid;
1656
+ }
1657
+ const sourceGlobalId = readOptionalString2(value.sourceGlobalId);
1658
+ if (sourceGlobalId !== void 0) {
1659
+ edge.sourceGlobalId = sourceGlobalId;
1660
+ }
1661
+ const targetGlobalId = readOptionalString2(value.targetGlobalId);
1662
+ if (targetGlobalId !== void 0) {
1663
+ edge.targetGlobalId = targetGlobalId;
1664
+ }
1665
+ const toGlobalId = readOptionalString2(value.toGlobalId);
1666
+ if (toGlobalId !== void 0) {
1667
+ edge.toGlobalId = toGlobalId;
1668
+ }
1669
+ const toNodeId = readOptionalString2(value.toNodeId);
1670
+ if (toNodeId !== void 0) {
1671
+ edge.toNodeId = toNodeId;
1672
+ }
1673
+ const toUuid = readOptionalString2(value.toUuid);
1674
+ if (toUuid !== void 0) {
1675
+ edge.toUuid = toUuid;
1676
+ }
1677
+ const weight = readOptionalNumber2(value.weight);
1678
+ if (weight !== void 0) {
1679
+ edge.weight = weight;
1680
+ }
1681
+ for (const timestampField of ["_creationTime", "createdAt", "updatedAt"]) {
1682
+ const timestamp = readOptionalNumber2(value[timestampField]);
1683
+ if (timestamp !== void 0) {
1684
+ edge[timestampField] = timestamp;
1685
+ }
1686
+ }
1687
+ return edge;
1688
+ }
1389
1689
  function getEdgeTimestamp(edge) {
1390
1690
  if (typeof edge.updatedAt === "number") {
1391
1691
  return edge.updatedAt;
@@ -1398,22 +1698,86 @@ function getEdgeTimestamp(edge) {
1398
1698
  }
1399
1699
  return null;
1400
1700
  }
1701
+ async function collectNodeEndpointRefs(ctx, nodeId) {
1702
+ const refs = /* @__PURE__ */ new Set([String(nodeId)]);
1703
+ const node = readMetricNodeDoc(await ctx.db.get(nodeId));
1704
+ if (node?.globalId) {
1705
+ refs.add(node.globalId);
1706
+ }
1707
+ return [...refs];
1708
+ }
1709
+ async function collectIncomingEdgeRows(ctx, nodeId, edgeType) {
1710
+ const refs = await collectNodeEndpointRefs(ctx, nodeId);
1711
+ const seen = /* @__PURE__ */ new Set();
1712
+ const edges = [];
1713
+ for (const ref of refs) {
1714
+ const rows = edgeType === void 0 ? await ctx.db.query("epistemicEdges").withIndex("by_to", (q) => q.eq("toNodeId", ref)).collect() : await ctx.db.query("epistemicEdges").withIndex(
1715
+ "by_to_type",
1716
+ (q) => q.eq("toNodeId", ref).eq("edgeType", edgeType)
1717
+ ).collect();
1718
+ for (const row of rows) {
1719
+ const edge = readIncomingEdgeRow(row);
1720
+ if (!edge) {
1721
+ continue;
1722
+ }
1723
+ if (edgeType !== void 0 && edge.edgeType !== edgeType) {
1724
+ continue;
1725
+ }
1726
+ const key = edge._id === void 0 ? `${edge.fromNodeId}->${edge.toNodeId ?? ref}:${edge.edgeType ?? ""}` : String(edge._id);
1727
+ if (seen.has(key)) {
1728
+ continue;
1729
+ }
1730
+ seen.add(key);
1731
+ edges.push(edge);
1732
+ }
1733
+ }
1734
+ return edges;
1735
+ }
1736
+ function sourceEndpointRefs(edge) {
1737
+ return [
1738
+ edge.fromNodeId,
1739
+ edge.sourceGlobalId,
1740
+ edge.fromGlobalId,
1741
+ edge.fromUuid
1742
+ ].filter((value) => value !== void 0);
1743
+ }
1744
+ async function resolveEndpointNode(ctx, refs) {
1745
+ const candidates = refs.map((value) => value.trim()).filter(
1746
+ (value, index, values) => value.length > 0 && values.indexOf(value) === index
1747
+ );
1748
+ for (const candidate of candidates) {
1749
+ try {
1750
+ const direct = readMetricNodeDoc(
1751
+ await ctx.db.get(candidate)
1752
+ );
1753
+ if (direct) {
1754
+ return direct;
1755
+ }
1756
+ } catch {
1757
+ }
1758
+ const byGlobalId = readMetricNodeDoc(
1759
+ await ctx.db.query("epistemicNodes").withIndex("by_globalId", (q) => q.eq("globalId", candidate)).first()
1760
+ );
1761
+ if (byGlobalId) {
1762
+ return byGlobalId;
1763
+ }
1764
+ }
1765
+ return null;
1766
+ }
1401
1767
  async function getEvidenceLinks(ctx, beliefNodeId) {
1402
- const edges = await ctx.db.query("epistemicEdges").withIndex(
1403
- "by_to_type",
1404
- (q) => q.eq("toNodeId", beliefNodeId).eq("edgeType", "informs")
1405
- ).collect();
1768
+ const edges = await collectIncomingEdgeRows(ctx, beliefNodeId, "informs");
1406
1769
  if (edges.length === 0) {
1407
1770
  return [];
1408
1771
  }
1409
- const nodes = await Promise.all(edges.map((edge) => ctx.db.get(edge.fromNodeId)));
1410
- return edges.flatMap((edge, index) => {
1411
- const node = nodes[index];
1412
- if (!node || node.nodeType !== "evidence" || node.status === "archived") {
1413
- return [];
1772
+ const links = [];
1773
+ for (const edge of edges) {
1774
+ const node = await resolveEndpointNode(ctx, sourceEndpointRefs(edge));
1775
+ if (node?.nodeType !== "evidence" || node.status === "archived") {
1776
+ continue;
1414
1777
  }
1415
- return [{ edge, node }];
1416
- });
1778
+ links.push({ edge, node });
1779
+ }
1780
+ return links;
1417
1781
  }
1418
1782
  function getEvidenceTags(node) {
1419
1783
  const metadata = node.metadata && typeof node.metadata === "object" ? node.metadata : null;
@@ -1439,7 +1803,8 @@ async function computeTaggedEvidenceCount(args) {
1439
1803
  };
1440
1804
  }
1441
1805
  async function computeContradictionCounts(ctx, beliefNodeId) {
1442
- const contradictions = await ctx.db.query("contradictions").withIndex("by_beliefId", (q) => q.eq("beliefId", beliefNodeId)).collect();
1806
+ const contradictionDb = ctx.db;
1807
+ const contradictions = await contradictionDb.query("contradictions").withIndex("by_beliefId", (q) => q.eq("beliefId", beliefNodeId)).collect();
1443
1808
  return contradictions.reduce(
1444
1809
  (counts, contradiction) => {
1445
1810
  const status = contradiction.resolutionStatus ?? contradiction.status ?? "unresolved";
@@ -1475,18 +1840,16 @@ async function computeEvidenceFreshness(ctx, beliefNodeId, now = Date.now()) {
1475
1840
  };
1476
1841
  }
1477
1842
  async function computeDependentBeliefCount(ctx, beliefNodeId) {
1478
- const incomingEdges = await ctx.db.query("epistemicEdges").withIndex("by_to", (q) => q.eq("toNodeId", beliefNodeId)).collect();
1843
+ const incomingEdges = await collectIncomingEdgeRows(ctx, beliefNodeId);
1479
1844
  const dependencyEdges = incomingEdges.filter(
1480
- (edge) => DEPENDENT_EDGE_TYPES.has(edge.edgeType)
1845
+ (edge) => edge.edgeType ? DEPENDENT_EDGE_TYPES.has(edge.edgeType) : false
1481
1846
  );
1482
1847
  if (dependencyEdges.length === 0) {
1483
1848
  return 0;
1484
1849
  }
1485
- const dependentBeliefs = await Promise.all(
1486
- dependencyEdges.map((edge) => ctx.db.get(edge.fromNodeId))
1487
- );
1488
1850
  const uniqueBeliefIds = /* @__PURE__ */ new Set();
1489
- for (const node of dependentBeliefs) {
1851
+ for (const edge of dependencyEdges) {
1852
+ const node = await resolveEndpointNode(ctx, sourceEndpointRefs(edge));
1490
1853
  if (node && node.nodeType === "belief" && node.status !== "archived" && node.status !== "deleted") {
1491
1854
  uniqueBeliefIds.add(String(node._id));
1492
1855
  }
@@ -1496,7 +1859,10 @@ async function computeDependentBeliefCount(ctx, beliefNodeId) {
1496
1859
  async function snapshotEvidentialMetric(args) {
1497
1860
  switch (args.metric) {
1498
1861
  case "evidence_count": {
1499
- const count = await computeEvidenceCountMetric(args.ctx, args.beliefNodeId);
1862
+ const count = await computeEvidenceCountMetric(
1863
+ args.ctx,
1864
+ args.beliefNodeId
1865
+ );
1500
1866
  return {
1501
1867
  metric: args.metric,
1502
1868
  value: count,
@@ -1504,7 +1870,10 @@ async function snapshotEvidentialMetric(args) {
1504
1870
  };
1505
1871
  }
1506
1872
  case "contradiction_status": {
1507
- const counts = await computeContradictionCounts(args.ctx, args.beliefNodeId);
1873
+ const counts = await computeContradictionCounts(
1874
+ args.ctx,
1875
+ args.beliefNodeId
1876
+ );
1508
1877
  return {
1509
1878
  metric: args.metric,
1510
1879
  value: counts.activeCount,
@@ -1524,7 +1893,10 @@ async function snapshotEvidentialMetric(args) {
1524
1893
  };
1525
1894
  }
1526
1895
  case "dependent_count": {
1527
- const count = await computeDependentBeliefCount(args.ctx, args.beliefNodeId);
1896
+ const count = await computeDependentBeliefCount(
1897
+ args.ctx,
1898
+ args.beliefNodeId
1899
+ );
1528
1900
  return {
1529
1901
  metric: args.metric,
1530
1902
  value: count,
@@ -1540,7 +1912,9 @@ async function snapshotEvidentialMetric(args) {
1540
1912
  }
1541
1913
  }
1542
1914
  async function evaluateBuiltInEvidentialContract(args) {
1543
- const config = parseEvidentialEvaluatorConfig(args.contract.condition.evaluatorConfig);
1915
+ const config = parseEvidentialEvaluatorConfig(
1916
+ args.contract.condition.evaluatorConfig
1917
+ );
1544
1918
  const snapshot = await snapshotEvidentialMetric({
1545
1919
  ctx: args.ctx,
1546
1920
  beliefNodeId: args.belief._id,
@@ -1548,7 +1922,10 @@ async function evaluateBuiltInEvidentialContract(args) {
1548
1922
  now: args.now
1549
1923
  });
1550
1924
  const comparisonSatisfied = snapshot.value !== null && compareMetricValue(config.operator, snapshot.value, config.threshold);
1551
- const result = args.contract.direction === "falsifies" ? comparisonSatisfied ? "disconfirmed" : "confirmed" : comparisonSatisfied ? "confirmed" : "disconfirmed";
1925
+ const result = resolveComparisonResult(
1926
+ args.contract.direction,
1927
+ comparisonSatisfied
1928
+ );
1552
1929
  return {
1553
1930
  result,
1554
1931
  rationale: buildEvidentialRationale({
@@ -1568,57 +1945,66 @@ async function evaluateBuiltInEvidentialContract(args) {
1568
1945
  }
1569
1946
  };
1570
1947
  }
1571
- async function evaluateMetricCheckerContract(args) {
1572
- const config = parseMetricCheckerConfig(args.contract.condition.evaluatorConfig);
1573
- const input = getEvaluatorInputRecord(args.inputData, "metricData");
1574
- const metric = typeof input.metric === "string" && input.metric.length > 0 ? input.metric : config.metric;
1575
- const observedValue = pickFiniteNumber(input, [
1576
- "observedValue",
1577
- "currentValue",
1578
- "metricValue",
1579
- "value"
1580
- ]) ?? config.observedValue ?? config.currentValue ?? config.metricValue ?? null;
1581
- if (observedValue === null) {
1948
+ function evaluateMetricCheckerContract(args) {
1949
+ return Promise.resolve().then(() => {
1950
+ const config = parseMetricCheckerConfig(
1951
+ args.contract.condition.evaluatorConfig
1952
+ );
1953
+ const input = getEvaluatorInputRecord(args.inputData, "metricData");
1954
+ const metric = typeof input.metric === "string" && input.metric.length > 0 ? input.metric : config.metric;
1955
+ const observedValue = pickFiniteNumber(input, [
1956
+ "observedValue",
1957
+ "currentValue",
1958
+ "metricValue",
1959
+ "value"
1960
+ ]) ?? config.observedValue ?? config.currentValue ?? config.metricValue ?? null;
1961
+ if (observedValue === null) {
1962
+ return {
1963
+ result: "inconclusive",
1964
+ rationale: `metric_checker is awaiting data for ${metric ?? args.contract.condition.expression}.`,
1965
+ data: {
1966
+ metric,
1967
+ observedValue: null,
1968
+ operator: config.operator,
1969
+ threshold: config.threshold,
1970
+ unit: config.unit
1971
+ }
1972
+ };
1973
+ }
1974
+ const comparisonSatisfied = compareMetricValue(
1975
+ config.operator,
1976
+ observedValue,
1977
+ config.threshold
1978
+ );
1979
+ const result = resolveComparisonResult(
1980
+ args.contract.direction,
1981
+ comparisonSatisfied
1982
+ );
1582
1983
  return {
1583
- result: "inconclusive",
1584
- rationale: `metric_checker is awaiting data for ${metric ?? args.contract.condition.expression}.`,
1984
+ result,
1985
+ rationale: buildComparisonRationale({
1986
+ label: metric ?? "metric",
1987
+ observedValue,
1988
+ operator: config.operator,
1989
+ threshold: config.threshold,
1990
+ comparisonSatisfied,
1991
+ result,
1992
+ unit: config.unit
1993
+ }),
1585
1994
  data: {
1586
1995
  metric,
1587
- observedValue: null,
1996
+ observedValue,
1588
1997
  operator: config.operator,
1589
1998
  threshold: config.threshold,
1590
1999
  unit: config.unit
1591
2000
  }
1592
2001
  };
1593
- }
1594
- const comparisonSatisfied = compareMetricValue(
1595
- config.operator,
1596
- observedValue,
1597
- config.threshold
1598
- );
1599
- const result = resolveComparisonResult(args.contract.direction, comparisonSatisfied);
1600
- return {
1601
- result,
1602
- rationale: buildComparisonRationale({
1603
- label: metric ?? "metric",
1604
- observedValue,
1605
- operator: config.operator,
1606
- threshold: config.threshold,
1607
- comparisonSatisfied,
1608
- result,
1609
- unit: config.unit
1610
- }),
1611
- data: {
1612
- metric,
1613
- observedValue,
1614
- operator: config.operator,
1615
- threshold: config.threshold,
1616
- unit: config.unit
1617
- }
1618
- };
2002
+ });
1619
2003
  }
1620
2004
  async function evaluateReferenceCheckCounterContract(args) {
1621
- const config = parseReferenceCheckCounterConfig(args.contract.condition.evaluatorConfig);
2005
+ const config = parseReferenceCheckCounterConfig(
2006
+ args.contract.condition.evaluatorConfig
2007
+ );
1622
2008
  const input = getEvaluatorInputRecord(args.inputData, "referenceCheckData");
1623
2009
  const tag = typeof input.tag === "string" && input.tag.trim().length > 0 ? input.tag.trim() : config.tag;
1624
2010
  const snapshot = await computeTaggedEvidenceCount({
@@ -1632,7 +2018,10 @@ async function evaluateReferenceCheckCounterContract(args) {
1632
2018
  snapshot.count,
1633
2019
  config.threshold
1634
2020
  );
1635
- const result = resolveComparisonResult(args.contract.direction, comparisonSatisfied);
2021
+ const result = resolveComparisonResult(
2022
+ args.contract.direction,
2023
+ comparisonSatisfied
2024
+ );
1636
2025
  return {
1637
2026
  result,
1638
2027
  rationale: buildComparisonRationale({
@@ -1654,130 +2043,167 @@ async function evaluateReferenceCheckCounterContract(args) {
1654
2043
  }
1655
2044
  };
1656
2045
  }
1657
- async function evaluateTemporalDeadlineContract(args) {
1658
- if (typeof args.contract.deadline !== "number" || !Number.isFinite(args.contract.deadline)) {
1659
- throw new Error(
1660
- "temporal_deadline requires contract.deadline to be set to a finite timestamp."
1661
- );
1662
- }
1663
- const config = parseTemporalDeadlineConfig(args.contract.condition.evaluatorConfig);
1664
- const input = getEvaluatorInputRecord(args.inputData, "temporalData");
1665
- const label = (typeof input.label === "string" && input.label.length > 0 ? input.label : config.label) ?? args.contract.title ?? args.contract.condition.expression;
1666
- const completedAt = pickFiniteNumber(input, [
1667
- "completedAt",
1668
- "observedAt",
1669
- "satisfiedAt",
1670
- "achievedAt"
1671
- ]) ?? config.completedAt ?? config.observedAt ?? config.satisfiedAt ?? config.achievedAt;
1672
- const completed = input.completed === true || config.completed === true || completedAt !== void 0;
1673
- if (completed) {
1674
- if (completedAt !== void 0 && completedAt > args.contract.deadline) {
1675
- return {
1676
- result: "expired",
1677
- rationale: `${label} completed at ${completedAt}, after deadline ${args.contract.deadline}.`,
1678
- data: {
1679
- label,
1680
- deadline: args.contract.deadline,
1681
- completed: true,
1682
- completedAt,
1683
- missedDeadline: true,
1684
- overdueByMs: completedAt - args.contract.deadline
1685
- }
1686
- };
1687
- }
1688
- const result = args.contract.direction === "falsifies" ? "disconfirmed" : "confirmed";
2046
+ function resolveCompletedTemporalDeadlineResult(args) {
2047
+ const { completedAt, context, deadline, label } = args;
2048
+ if (completedAt !== void 0 && completedAt > deadline) {
1689
2049
  return {
1690
- result,
1691
- rationale: `${label} completed before deadline ${args.contract.deadline}.`,
2050
+ result: "expired",
2051
+ rationale: `${label} completed at ${completedAt}, after deadline ${deadline}.`,
1692
2052
  data: {
1693
2053
  label,
1694
- deadline: args.contract.deadline,
2054
+ deadline,
1695
2055
  completed: true,
1696
- completedAt: completedAt ?? null,
1697
- missedDeadline: false
2056
+ completedAt,
2057
+ missedDeadline: true,
2058
+ overdueByMs: completedAt - deadline
1698
2059
  }
1699
2060
  };
1700
2061
  }
1701
- if (args.now > args.contract.deadline) {
2062
+ const result = context.contract.direction === "falsifies" ? "disconfirmed" : "confirmed";
2063
+ return {
2064
+ result,
2065
+ rationale: `${label} completed before deadline ${deadline}.`,
2066
+ data: {
2067
+ label,
2068
+ deadline,
2069
+ completed: true,
2070
+ completedAt: completedAt ?? null,
2071
+ missedDeadline: false
2072
+ }
2073
+ };
2074
+ }
2075
+ function resolveOpenTemporalDeadlineResult(args) {
2076
+ const { context, deadline, label } = args;
2077
+ if (context.now > deadline) {
1702
2078
  return {
1703
2079
  result: "expired",
1704
- rationale: `${label} missed deadline ${args.contract.deadline}; temporal contract expired.`,
2080
+ rationale: `${label} missed deadline ${deadline}; temporal contract expired.`,
1705
2081
  data: {
1706
2082
  label,
1707
- deadline: args.contract.deadline,
2083
+ deadline,
1708
2084
  completed: false,
1709
- overdueByMs: args.now - args.contract.deadline
2085
+ overdueByMs: context.now - deadline
1710
2086
  }
1711
2087
  };
1712
2088
  }
1713
2089
  return {
1714
2090
  result: "inconclusive",
1715
- rationale: `${label} is still before deadline ${args.contract.deadline}; awaiting outcome.`,
2091
+ rationale: `${label} is still before deadline ${deadline}; awaiting outcome.`,
1716
2092
  data: {
1717
2093
  label,
1718
- deadline: args.contract.deadline,
2094
+ deadline,
1719
2095
  completed: false,
1720
- timeRemainingMs: args.contract.deadline - args.now
2096
+ timeRemainingMs: deadline - context.now
1721
2097
  }
1722
2098
  };
1723
2099
  }
1724
- async function evaluateMarketIndexComparatorContract(args) {
1725
- const config = parseMarketIndexComparatorConfig(args.contract.condition.evaluatorConfig);
1726
- const input = getEvaluatorInputRecord(args.inputData, "marketIndexData");
1727
- const subject = typeof input.subject === "string" && input.subject.length > 0 ? input.subject : config.subject;
1728
- const benchmark = typeof input.benchmark === "string" && input.benchmark.length > 0 ? input.benchmark : config.benchmark;
1729
- const subjectValue = pickFiniteNumber(input, ["subjectValue", "primaryValue", "leftValue"]) ?? config.subjectValue ?? config.primaryValue ?? null;
1730
- const benchmarkValue = pickFiniteNumber(input, ["benchmarkValue", "comparisonValue", "rightValue"]) ?? config.benchmarkValue ?? config.comparisonValue ?? null;
1731
- if (subjectValue === null || benchmarkValue === null) {
2100
+ function evaluateTemporalDeadlineContract(args) {
2101
+ return Promise.resolve().then(() => {
2102
+ if (typeof args.contract.deadline !== "number" || !Number.isFinite(args.contract.deadline)) {
2103
+ throw new Error(
2104
+ "temporal_deadline requires contract.deadline to be set to a finite timestamp."
2105
+ );
2106
+ }
2107
+ const deadline = args.contract.deadline;
2108
+ const config = parseTemporalDeadlineConfig(
2109
+ args.contract.condition.evaluatorConfig
2110
+ );
2111
+ const input = getEvaluatorInputRecord(args.inputData, "temporalData");
2112
+ const label = (typeof input.label === "string" && input.label.length > 0 ? input.label : config.label) ?? args.contract.title ?? args.contract.condition.expression;
2113
+ const completedAt = pickFiniteNumber(input, [
2114
+ "completedAt",
2115
+ "observedAt",
2116
+ "satisfiedAt",
2117
+ "achievedAt"
2118
+ ]) ?? config.completedAt ?? config.observedAt ?? config.satisfiedAt ?? config.achievedAt;
2119
+ const completed = input.completed === true || config.completed === true || completedAt !== void 0;
2120
+ if (completed) {
2121
+ return resolveCompletedTemporalDeadlineResult({
2122
+ completedAt,
2123
+ context: args,
2124
+ deadline,
2125
+ label
2126
+ });
2127
+ }
2128
+ return resolveOpenTemporalDeadlineResult({
2129
+ context: args,
2130
+ deadline,
2131
+ label
2132
+ });
2133
+ });
2134
+ }
2135
+ function evaluateMarketIndexComparatorContract(args) {
2136
+ return Promise.resolve().then(() => {
2137
+ const config = parseMarketIndexComparatorConfig(
2138
+ args.contract.condition.evaluatorConfig
2139
+ );
2140
+ const input = getEvaluatorInputRecord(args.inputData, "marketIndexData");
2141
+ const subject = typeof input.subject === "string" && input.subject.length > 0 ? input.subject : config.subject;
2142
+ const benchmark = typeof input.benchmark === "string" && input.benchmark.length > 0 ? input.benchmark : config.benchmark;
2143
+ const subjectValue = pickFiniteNumber(input, ["subjectValue", "primaryValue", "leftValue"]) ?? config.subjectValue ?? config.primaryValue ?? null;
2144
+ const benchmarkValue = pickFiniteNumber(input, [
2145
+ "benchmarkValue",
2146
+ "comparisonValue",
2147
+ "rightValue"
2148
+ ]) ?? config.benchmarkValue ?? config.comparisonValue ?? null;
2149
+ if (subjectValue === null || benchmarkValue === null) {
2150
+ return {
2151
+ result: "inconclusive",
2152
+ rationale: "market_index_comparator is awaiting both subject and benchmark values.",
2153
+ data: {
2154
+ subject,
2155
+ subjectValue,
2156
+ benchmark,
2157
+ benchmarkValue,
2158
+ operator: config.operator,
2159
+ threshold: config.threshold
2160
+ }
2161
+ };
2162
+ }
2163
+ if (benchmarkValue === 0) {
2164
+ throw new Error(
2165
+ "market_index_comparator cannot compare against a zero benchmark value."
2166
+ );
2167
+ }
2168
+ const differentialPercent = (subjectValue - benchmarkValue) / Math.abs(benchmarkValue) * 100;
2169
+ const comparisonSatisfied = compareMetricValue(
2170
+ config.operator,
2171
+ differentialPercent,
2172
+ config.threshold
2173
+ );
2174
+ const result = resolveComparisonResult(
2175
+ args.contract.direction,
2176
+ comparisonSatisfied
2177
+ );
1732
2178
  return {
1733
- result: "inconclusive",
1734
- rationale: "market_index_comparator is awaiting both subject and benchmark values.",
2179
+ result,
2180
+ rationale: buildComparisonRationale({
2181
+ label: `${subject ?? "subject"} vs ${benchmark ?? "benchmark"} differential`,
2182
+ observedValue: differentialPercent,
2183
+ operator: config.operator,
2184
+ threshold: config.threshold,
2185
+ comparisonSatisfied,
2186
+ result,
2187
+ unit: "%"
2188
+ }),
1735
2189
  data: {
1736
2190
  subject,
1737
2191
  subjectValue,
1738
2192
  benchmark,
1739
2193
  benchmarkValue,
2194
+ differentialPercent,
1740
2195
  operator: config.operator,
1741
2196
  threshold: config.threshold
1742
2197
  }
1743
2198
  };
1744
- }
1745
- if (benchmarkValue === 0) {
1746
- throw new Error(
1747
- "market_index_comparator cannot compare against a zero benchmark value."
1748
- );
1749
- }
1750
- const differentialPercent = (subjectValue - benchmarkValue) / Math.abs(benchmarkValue) * 100;
1751
- const comparisonSatisfied = compareMetricValue(
1752
- config.operator,
1753
- differentialPercent,
1754
- config.threshold
1755
- );
1756
- const result = resolveComparisonResult(args.contract.direction, comparisonSatisfied);
1757
- return {
1758
- result,
1759
- rationale: buildComparisonRationale({
1760
- label: `${subject ?? "subject"} vs ${benchmark ?? "benchmark"} differential`,
1761
- observedValue: differentialPercent,
1762
- operator: config.operator,
1763
- threshold: config.threshold,
1764
- comparisonSatisfied,
1765
- result,
1766
- unit: "%"
1767
- }),
1768
- data: {
1769
- subject,
1770
- subjectValue,
1771
- benchmark,
1772
- benchmarkValue,
1773
- differentialPercent,
1774
- operator: config.operator,
1775
- threshold: config.threshold
1776
- }
1777
- };
2199
+ });
1778
2200
  }
1779
2201
  var METRIC_COMPARATOR_EVALUATOR_NAMES = {
1780
- evidentialAliases: /* @__PURE__ */ new Set(["evidential", "built_in_evidential", "builtin_evidential"]),
2202
+ evidentialAliases: /* @__PURE__ */ new Set([
2203
+ "evidential",
2204
+ "built_in_evidential",
2205
+ "builtin_evidential"
2206
+ ]),
1781
2207
  metricChecker: "metric_checker",
1782
2208
  referenceCheckCounter: "reference_check_counter",
1783
2209
  temporalDeadline: "temporal_deadline",
@@ -1785,6 +2211,8 @@ var METRIC_COMPARATOR_EVALUATOR_NAMES = {
1785
2211
  };
1786
2212
 
1787
2213
  // src/evaluators/shared.ts
2214
+ var WINDOWS_PATH_SEPARATORS = /\\/g;
2215
+ var LEADING_DOT_SLASH = /^\.\//;
1788
2216
  function asArray(value) {
1789
2217
  return Array.isArray(value) ? value : [];
1790
2218
  }
@@ -1826,7 +2254,7 @@ function extractTextCandidates(value) {
1826
2254
  return Array.from(new Set(candidates));
1827
2255
  }
1828
2256
  function normalizeFilePath(value) {
1829
- return value.replace(/\\/g, "/").replace(/^\.\//, "");
2257
+ return value.replace(WINDOWS_PATH_SEPARATORS, "/").replace(LEADING_DOT_SLASH, "");
1830
2258
  }
1831
2259
  function normalizeToolResultEnvelope(value) {
1832
2260
  const record = asRecord(value);
@@ -1880,7 +2308,7 @@ function somePatternMatches(filePath, patterns) {
1880
2308
  return patterns.some((pattern) => patternMatchesPath(filePath, pattern));
1881
2309
  }
1882
2310
 
1883
- // src/evaluators/lintCheckerEvaluator.ts
2311
+ // src/evaluators/lint-checker-evaluator.ts
1884
2312
  function parseConfig(condition) {
1885
2313
  const record = asRecord(condition.evaluatorConfig);
1886
2314
  if (!record) {
@@ -1952,7 +2380,10 @@ var lintCheckerEvaluator = {
1952
2380
  }
1953
2381
  const envelope = normalizeToolResultEnvelope(args.resultData);
1954
2382
  const exitCode = asNumber(envelope.exitCode);
1955
- const matchedDiagnostics = getMatchedDiagnostics(args.contract, args.resultData);
2383
+ const matchedDiagnostics = getMatchedDiagnostics(
2384
+ args.contract,
2385
+ args.resultData
2386
+ );
1956
2387
  if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {
1957
2388
  return {
1958
2389
  result: "inconclusive",
@@ -1978,7 +2409,7 @@ var lintCheckerEvaluator = {
1978
2409
  }
1979
2410
  };
1980
2411
 
1981
- // src/evaluators/sentryCheckerEvaluator.ts
2412
+ // src/evaluators/sentry-checker-evaluator.ts
1982
2413
  function parseConfig2(condition) {
1983
2414
  const record = asRecord(condition.evaluatorConfig);
1984
2415
  if (!record) {
@@ -2063,7 +2494,7 @@ var sentryCheckerEvaluator = {
2063
2494
  }
2064
2495
  };
2065
2496
 
2066
- // src/evaluators/testRunnerEvaluator.ts
2497
+ // src/evaluators/test-runner-evaluator.ts
2067
2498
  function parseConfig3(condition) {
2068
2499
  const record = asRecord(condition.evaluatorConfig);
2069
2500
  if (!record) {
@@ -2209,7 +2640,7 @@ var testRunnerEvaluator = {
2209
2640
  }
2210
2641
  };
2211
2642
 
2212
- // src/evaluators/tscCheckerEvaluator.ts
2643
+ // src/evaluators/tsc-checker-evaluator.ts
2213
2644
  function parseConfig4(condition) {
2214
2645
  const record = asRecord(condition.evaluatorConfig);
2215
2646
  if (!record) {
@@ -2294,7 +2725,10 @@ var tscCheckerEvaluator = {
2294
2725
  }
2295
2726
  const envelope = normalizeToolResultEnvelope(args.resultData);
2296
2727
  const exitCode = asNumber(envelope.exitCode);
2297
- const matchedDiagnostics = getMatchedDiagnostics2(args.contract, args.resultData);
2728
+ const matchedDiagnostics = getMatchedDiagnostics2(
2729
+ args.contract,
2730
+ args.resultData
2731
+ );
2298
2732
  if (matchedDiagnostics.length === 0 && exitCode !== 0 && exitCode !== null) {
2299
2733
  return {
2300
2734
  result: "inconclusive",
@@ -2338,6 +2772,18 @@ var BUILT_IN_REFERENCE_CHECK_COUNTER2 = METRIC_COMPARATOR_EVALUATOR_NAMES.refere
2338
2772
  var BUILT_IN_TEMPORAL_DEADLINE2 = METRIC_COMPARATOR_EVALUATOR_NAMES.temporalDeadline;
2339
2773
  var BUILT_IN_MARKET_INDEX_COMPARATOR2 = METRIC_COMPARATOR_EVALUATOR_NAMES.marketIndexComparator;
2340
2774
  var MAX_CONTRACT_EVALUATION_BATCH_SIZE = 50;
2775
+ function confidenceSeed(args) {
2776
+ if (typeof args.currentConfidence === "number") {
2777
+ return args.currentConfidence;
2778
+ }
2779
+ if (typeof args.beliefConfidence === "number") {
2780
+ return args.beliefConfidence;
2781
+ }
2782
+ return 0.5;
2783
+ }
2784
+ function contractDocId(contract) {
2785
+ return contract._id;
2786
+ }
2341
2787
  function clearEpistemicEvaluators() {
2342
2788
  evaluatorRegistry.clear();
2343
2789
  ensureBuiltInEvaluators();
@@ -2430,7 +2876,10 @@ async function executeContractEvaluation(args) {
2430
2876
  rationale: `No epistemic evaluator registered for "${args.contract.condition.evaluator}".`
2431
2877
  };
2432
2878
  }
2433
- const confidenceBefore = typeof args.currentConfidence === "number" ? args.currentConfidence : typeof args.belief.confidence === "number" ? args.belief.confidence : 0.5;
2879
+ const confidenceBefore = confidenceSeed({
2880
+ beliefConfidence: args.belief.confidence,
2881
+ currentConfidence: args.currentConfidence
2882
+ });
2434
2883
  const modulationPlan = deriveContractModulationPlan({
2435
2884
  currentConfidence: confidenceBefore,
2436
2885
  modulation: args.contract.modulation,
@@ -2470,16 +2919,16 @@ async function executeContractEvaluation(args) {
2470
2919
  modulationRationale: evaluation.rationale,
2471
2920
  topicId: args.contract.topicId
2472
2921
  });
2473
- const nextStatus = deriveContractStatus(evaluation.result, args.contract.status);
2474
- await args.ctx.db.patch(
2475
- args.contract._id,
2476
- {
2477
- status: nextStatus,
2478
- lastEvaluatedAt: args.now,
2479
- evaluationCount: (args.contract.evaluationCount ?? 0) + 1,
2480
- updatedAt: args.now
2481
- }
2922
+ const nextStatus = deriveContractStatus(
2923
+ evaluation.result,
2924
+ args.contract.status
2482
2925
  );
2926
+ await args.ctx.db.patch(contractDocId(args.contract), {
2927
+ status: nextStatus,
2928
+ lastEvaluatedAt: args.now,
2929
+ evaluationCount: (args.contract.evaluationCount ?? 0) + 1,
2930
+ updatedAt: args.now
2931
+ });
2483
2932
  return {
2484
2933
  evaluationId,
2485
2934
  result: evaluation.result,
@@ -2564,7 +3013,8 @@ async function evaluateContractsForTriggerBatch(args) {
2564
3013
  };
2565
3014
  }
2566
3015
  async function loadContractsForBelief(args) {
2567
- return await args.ctx.db.query("epistemicContracts").withIndex("by_belief", (q) => q.eq("beliefNodeId", args.beliefNodeId)).collect();
3016
+ const rows = await args.ctx.db.query("epistemicContracts").withIndex("by_belief", (q) => q.eq("beliefNodeId", args.beliefNodeId)).collect();
3017
+ return rows;
2568
3018
  }
2569
3019
  async function loadContractsForTrigger(args) {
2570
3020
  const contracts = await loadContractsForBelief(args);