@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,14 +1,17 @@
1
- export { BeliefConfidenceTrigger, flattenBeliefNode, resolveBeliefWorktreeId } from './epistemicBeliefs.helpers.js';
1
+ export { batchUpdateCriticality, deleteRelationship, getByCriticality, getByPillar, getByProjectSystem, getUnanalyzed, getWorktreeCluster, updateCriticality } from './epistemicBeliefs.admin.js';
2
+ export { backfillBeliefSprintIds, backfillMandatoryPriors, backfillScoredBeliefEdges, backfillSyntheticOpinionHistory, backfillTwoAxisConfidence, getBeliefClusterPositions, getRecentConfidenceChanges, reassignBeliefsTopic } from './epistemicBeliefs.backfills.js';
2
3
  export { applyBeliefConfidenceChange, propagateConfidenceChange } from './epistemicBeliefs.confidence.js';
3
4
  export { create, forkBelief, getById, getByProject, getByTopic, refineBelief } from './epistemicBeliefs.core.js';
5
+ export { BeliefConfidenceTrigger, flattenBeliefNode, resolveBeliefWorktreeId } from './epistemicBeliefs.helpers.js';
6
+ export { internalCreate, internalGetActive, internalGetById, internalGetByProject, internalGetByTopic } from './epistemicBeliefs.internal.js';
4
7
  export { appendSlScoring, archive, updateRationale, updateStatus, updateStatusInternal } from './epistemicBeliefs.lifecycle.js';
5
- export { getByIds, getByWorktree, getConfidenceHistory, getLineage } from './epistemicBeliefs.queries.js';
6
8
  export { getCountByStatus, getRelationships, getWithEvidence, linkBeliefs, linkEvidence, unlinkEvidence, updatePillar } from './epistemicBeliefs.links.js';
7
- export { batchUpdateCriticality, deleteRelationship, getByCriticality, getByPillar, getByProjectSystem, getUnanalyzed, getWorktreeCluster, updateCriticality } from './epistemicBeliefs.admin.js';
8
- export { internalCreate, internalGetActive, internalGetById, internalGetByProject, internalGetByTopic } from './epistemicBeliefs.internal.js';
9
- export { backfillBeliefSprintIds, backfillMandatoryPriors, backfillScoredBeliefEdges, backfillSyntheticOpinionHistory, backfillTwoAxisConfidence, getBeliefClusterPositions, getRecentConfidenceChanges, reassignBeliefsTopic } from './epistemicBeliefs.backfills.js';
10
- import './topicScope-7zhyeGl7.js';
11
- import 'convex/values';
12
- import './convex.js';
9
+ export { getByIds, getByWorktree, getConfidenceHistory, getLineage } from './epistemicBeliefs.queries.js';
13
10
  import '@lucern/confidence';
11
+ import './convex.js';
12
+ import '@lucern/access-control/convex';
13
+ import '@lucern/contracts/convex/unsafeAnyApi';
14
+ import 'convex/values';
15
+ import './topicScope-DJVa0mLa.js';
14
16
  import './beliefLifecycle-CXwdDw5e.js';
17
+ import '@lucern/access-control/structuredMutationError';
@@ -1,4 +1,6 @@
1
1
  import { MutationCtx, Id, Doc } from './convex.js';
2
+ import '@lucern/access-control/convex';
3
+ import '@lucern/contracts/convex/unsafeAnyApi';
2
4
  import 'convex/values';
3
5
 
4
6
  /** Evidence-gated fork precondition helpers. */
@@ -1,34 +1,14 @@
1
- import { v, ConvexError } from 'convex/values';
2
- import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
3
- import '@lucern/access-control/access';
4
1
  import '@lucern/access-control/audience';
5
2
  import '@lucern/access-control/auth';
3
+ import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
4
+ import { normalizeTupleContradictionPolicy } from '@lucern/confidence';
5
+ import { v } from 'convex/values';
6
6
 
7
7
  // src/epistemicBeliefs.helpers.ts
8
8
  v.id("epistemicNodes");
9
9
  ({
10
10
  tupleContradiction: normalizeTupleContradictionPolicy()
11
11
  });
12
- function throwStructuredMutationError(args) {
13
- const data = {
14
- structuredMutationError: true,
15
- message: args.message,
16
- status: args.status,
17
- code: args.code,
18
- invariantCode: args.invariantCode,
19
- suggestion: args.suggestion,
20
- details: args.details
21
- };
22
- const error = new ConvexError(
23
- data
24
- );
25
- error.status = args.status;
26
- error.code = args.code;
27
- error.invariantCode = args.invariantCode;
28
- error.suggestion = args.suggestion;
29
- error.details = args.details;
30
- throw error;
31
- }
32
12
 
33
13
  // src/epistemicBeliefs.forkEvidence.ts
34
14
  function normalizeForkTriggerRelation(value) {
@@ -42,7 +22,7 @@ function normalizeForkTriggerRelation(value) {
42
22
  }
43
23
  async function resolveForkTriggerEvidence(ctx, args) {
44
24
  const evidence = await ctx.db.get(args.triggeringEvidenceId);
45
- if (!evidence || evidence.nodeType !== "evidence") {
25
+ if (evidence?.nodeType !== "evidence") {
46
26
  throwStructuredMutationError({
47
27
  message: "Fork requires an existing evidence node.",
48
28
  status: 400,
@@ -81,16 +61,16 @@ async function resolveForkTriggerEvidence(ctx, args) {
81
61
  ].filter(Boolean)
82
62
  );
83
63
  let relation = null;
84
- const linkedBeliefNodeId = String(
85
- evidenceMetadata.linkedBeliefNodeId ?? ""
86
- );
64
+ const linkedBeliefNodeId = String(evidenceMetadata.linkedBeliefNodeId ?? "");
87
65
  if (linkedBeliefNodeId && parentRefs.has(linkedBeliefNodeId)) {
88
66
  relation = normalizeForkTriggerRelation(evidenceMetadata.evidenceRelation);
89
67
  }
90
68
  if (!relation) {
91
69
  for (const parentRef of parentRefs) {
92
70
  const links = await ctx.db.query("beliefEvidenceLinks").withIndex("by_beliefId", (q) => q.eq("beliefId", parentRef)).collect();
93
- const matched = links.find((link) => evidenceRefs.has(String(link.insightId)));
71
+ const matched = links.find(
72
+ (link) => evidenceRefs.has(String(link.insightId))
73
+ );
94
74
  if (matched) {
95
75
  relation = normalizeForkTriggerRelation(matched.relation);
96
76
  break;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/epistemicBeliefs.helpers.ts","../src/epistemicBeliefs.forkEvidence.ts"],"names":[],"mappings":"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","file":"epistemicBeliefs.forkEvidence.js","sourcesContent":["/**\n * Epistemic Beliefs API\n *\n * Clean API for managing beliefs in the epistemic spine (epistemicNodes).\n * This is the NEW API that replaces beliefs.ts.\n *\n * Key differences from beliefs.ts:\n * - Writes ONLY to epistemicNodes (no dual-write)\n * - Uses epistemicNodes IDs directly (no runtime ID translation fallback)\n * - Syncs to Neo4j after mutations\n * - Follows Lucern invariants strictly\n *\n * @see /docs/epistemic-invariants/00-epistemic-invariants.md\n */\n\nimport { v } from \"convex/values\";\nimport { ConvexError } from \"convex/values\";\nimport {\n detectTupleContradiction,\n evaluateTupleContradictionTransition,\n confidenceFromSL,\n mkOpinion,\n normalizeTupleContradictionPolicy,\n readOpinionFromRecord,\n type ConfidencePolicyConfig,\n type Opinion,\n type SLOpinion,\n type SLOperator,\n} from \"@lucern/confidence\";\nimport {\n checkProjectAccess,\n checkScopeAccess,\n} from \"@lucern/access-control/access\";\nimport {\n canAudienceClassAccess,\n classFromAudienceKey,\n normalizeAudienceKey,\n} from \"@lucern/access-control/audience\";\nimport { listAudienceRegistryRows } from \"@lucern/access-control/audienceRegistry\";\nimport { getCurrentUserId } from \"@lucern/access-control/auth\";\nimport { assertSchemaEnumValue } from \"@lucern/contracts/schema-helpers/enumValidation\";\nimport { permissiveReturn } from \"@lucern/contracts/schema-helpers/validators\";\nimport {\n type BeliefLifecycleStatus,\n isPreValidationBeliefStatus,\n promoteBeliefStatusAfterScoring,\n resolveBeliefLifecycleStatus,\n} from \"./beliefLifecycle\";\nimport type { Doc, Id, MutationCtx, QueryCtx } from \"./convex\";\nimport {\n internal,\n internalMutation,\n internalQuery,\n mutation,\n query,\n} from \"./convex\";\nimport { collectConfidencePropagationDispatches } from \"./confidencePropagationDispatch\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\nimport {\n createInheritedContractRecord,\n type VerificationConfidenceTrigger,\n} from \"./epistemicContractHelpers\";\nimport { scheduleEmbeddingGeneration } from \"./embeddingTrigger\";\nimport { generateGlobalId } from \"./globalId\";\nimport { computeLogicalRole } from \"./logicalRoleInference\";\nimport { resolveGraphPrimitivesAppResolvers } from \"./resolvers\";\nimport { optionalScopeArgs, resolveTopicProjectScope } from \"./topicScope\";\nimport {\n assertTenantPackWorkspaceMutationAllowed,\n assertWorkspaceScopedEpistemicNodeScope,\n nodeMatchesWorkspaceReasoningScope,\n resolveNodeScopeForWorkspaceIsolation,\n resolveRuntimePackMutationContext,\n} from \"./workspaceIsolation\";\n\n// All IDs now use epistemicNodes exclusively\nexport const insightIdUnion = v.id(\"epistemicNodes\");\nconst DEFAULT_PROJECT_BELIEF_LIMIT = 250;\nexport const MAX_PROJECT_BELIEF_LIMIT = 1000;\nexport const optionalBeliefScopeArgs = optionalScopeArgs;\n\ntype StructuredMutationError = Error & {\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\n/**\n * Boundary-safe payload carried inside a {@link ConvexError}. Mirrors the kernel\n * copy in packages/reasoning-kernel/src/adapters/beliefs.shared.ts so structured\n * refusals from the graph-primitives module survive the Convex client boundary\n * (only `ConvexError.data` is preserved across serialization).\n */\nexport type StructuredMutationErrorData = {\n structuredMutationError: true;\n message: string;\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n};\n\ntype BeliefScopeArgs = {\n projectId?: string | null;\n topicId?: string | null;\n};\n\ntype EpistemicNodeOpinionDoc = Doc<\"epistemicNodes\"> & {\n opinion_a?: number;\n opinion_b?: number;\n opinion_d?: number;\n opinion_u?: number;\n tupleContradicted?: boolean;\n userId?: string;\n metadata?: Record<string, unknown> | null;\n};\n\ntype EpistemicIndexQuery = {\n eq(field: string, value: unknown): EpistemicIndexQuery;\n gt(field: string, value: unknown): EpistemicIndexQuery;\n lt(field: string, value: unknown): EpistemicIndexQuery;\n field(field: string): string;\n};\n\ntype EpistemicQueryChain<T> = {\n withIndex(\n _name: string,\n callback: (q: EpistemicIndexQuery) => EpistemicIndexQuery,\n ): EpistemicQueryChain<T>;\n order(direction: \"asc\" | \"desc\"): EpistemicQueryChain<T>;\n filter(\n callback: (q: EpistemicIndexQuery) => EpistemicIndexQuery,\n ): EpistemicQueryChain<T>;\n first(): Promise<T | null>;\n collect(): Promise<T[]>;\n take(limit: number): Promise<T[]>;\n};\n\ntype EpistemicBeliefCtx = QueryCtx & {\n db: {\n query<T = unknown>(_table: string): EpistemicQueryChain<T>;\n get<T = unknown>(id: Id<string>): Promise<T | null>;\n };\n scheduler: {\n runAfter(\n _delayMs: number,\n _handler: unknown,\n _args: unknown,\n ): Promise<unknown>;\n };\n};\n\ntype AudienceClass = \"internal\" | \"restricted_external\" | \"public\";\n\nconst DEFAULT_CONFIDENCE_POLICY: ConfidencePolicyConfig = {\n scoringMode: \"after_worktree\",\n tupleContradiction: normalizeTupleContradictionPolicy(),\n};\n\nexport type BeliefConfidenceTrigger =\n | \"initial\"\n | \"evidence_added\"\n | \"evidence_removed\"\n | \"contradiction_detected\"\n | \"contradiction_resolved\"\n | \"propagation\"\n | \"agent_assessment\"\n | \"worktree_outcome\"\n | \"worktree_completed\"\n // SL-specific triggers\n | \"fusion\"\n | \"discount\"\n | \"deduction\"\n | \"backfill_synthetic\"\n | VerificationConfidenceTrigger;\n\nexport function throwStructuredMutationError(args: {\n message: string;\n status: number;\n code: string;\n invariantCode?: string;\n suggestion?: string;\n details?: unknown;\n}): never {\n // FR.7 (parity with kernel beliefs.shared.ts): throw a ConvexError carrying\n // the structured payload in `.data` so the gateway can reconstruct the real\n // HTTP status/code instead of collapsing the refusal into a retryable 500.\n // The legacy `.status`/`.code` props are retained for in-process tests.\n const data: StructuredMutationErrorData = {\n structuredMutationError: true,\n message: args.message,\n status: args.status,\n code: args.code,\n invariantCode: args.invariantCode,\n suggestion: args.suggestion,\n details: args.details,\n };\n const error = new ConvexError(\n data as unknown as string,\n ) as unknown as ConvexError<string> & Partial<StructuredMutationError>;\n error.status = args.status;\n error.code = args.code;\n error.invariantCode = args.invariantCode;\n error.suggestion = args.suggestion;\n error.details = args.details;\n throw error;\n}\n\nexport function readFiniteNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function assertBaseRateInRange(baseRate: number, field = \"baseRate\"): number {\n if (baseRate < 0 || baseRate > 1) {\n throwStructuredMutationError({\n message: `${field} must be within [0, 1].`,\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"request.valid_shape\",\n suggestion: `Clamp ${field} into the inclusive [0, 1] interval.`,\n details: { field, baseRate },\n });\n }\n return baseRate;\n}\n\nexport function buildBeliefConfidenceRow(args: {\n beliefId: Id<\"epistemicNodes\">;\n belief: number;\n disbelief: number;\n uncertainty: number;\n baseRate: number;\n trigger: BeliefConfidenceTrigger;\n rationale?: string;\n assessedBy: string;\n assessedAt: number;\n slOperator?: SLOperator;\n triggeringEvidenceId?: Id<\"epistemicNodes\">;\n triggeringContradictionId?: Id<\"contradictions\">;\n triggeringWorktreeId?: string;\n}) {\n return {\n beliefId: args.beliefId,\n confidence: confidenceFromSL(\n args.belief,\n args.disbelief,\n args.uncertainty,\n args.baseRate,\n ),\n belief: args.belief,\n disbelief: args.disbelief,\n uncertainty: args.uncertainty,\n baseRate: args.baseRate,\n slOperator: args.slOperator ?? (\"prior_seed\" as const),\n trigger: args.trigger,\n ...(args.rationale ? { rationale: args.rationale } : {}),\n assessedBy: args.assessedBy,\n assessedAt: args.assessedAt,\n ...(args.triggeringEvidenceId\n ? {\n triggeringEvidenceId: args.triggeringEvidenceId,\n triggeringEvidenceIds: [String(args.triggeringEvidenceId)],\n }\n : {}),\n ...(args.triggeringContradictionId\n ? {\n triggeringContradictionId: args.triggeringContradictionId,\n }\n : {}),\n ...(args.triggeringWorktreeId\n ? { triggeringWorktreeId: args.triggeringWorktreeId }\n : {}),\n };\n}\n\ntype BeliefStatusResult =\n | { success: true }\n | { success: false; message: \"Evidence node not found\" };\n\nexport function buildBeliefStatusSuccessResult(): BeliefStatusResult {\n return { success: true };\n}\n\nexport function buildBeliefEvidenceNotFoundResult(): BeliefStatusResult {\n const result = {} as Extract<BeliefStatusResult, { success: false }>;\n result.success = false;\n result.message = \"Evidence node not found\";\n return result;\n}\n\nexport function deriveSyntheticBackfillOpinion(\n source: Record<string, unknown>,\n): SLOpinion {\n const belief =\n readFiniteNumber(source.opinion_b) ?? readFiniteNumber(source.belief);\n const disbelief =\n readFiniteNumber(source.opinion_d) ?? readFiniteNumber(source.disbelief);\n const uncertainty =\n readFiniteNumber(source.opinion_u) ?? readFiniteNumber(source.uncertainty);\n const baseRate =\n readFiniteNumber(source.opinion_a) ?? readFiniteNumber(source.baseRate);\n\n if (\n belief !== undefined ||\n disbelief !== undefined ||\n uncertainty !== undefined ||\n baseRate !== undefined\n ) {\n try {\n return readOpinionFromRecord(source);\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to decode legacy belief opinion\",\n {\n error,\n },\n );\n return mkOpinion(0, 0, 1, 0.5);\n }\n }\n\n const confidence = clamp01(readFiniteNumber(source.confidence) ?? 0);\n return mkOpinion(confidence, 1 - confidence, 0, 0.5);\n}\n\nexport function clampBeliefLimit(\n limit: number | undefined,\n fallback = DEFAULT_PROJECT_BELIEF_LIMIT,\n): number {\n if (!Number.isFinite(limit)) {\n return fallback;\n }\n return Math.max(\n 1,\n Math.min(Math.floor(limit as number), MAX_PROJECT_BELIEF_LIMIT),\n );\n}\n\nexport function readTupleContradictedFlag(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nexport function readBeliefOpinionSnapshot(\n node: Doc<\"epistemicNodes\">,\n metadata: Record<string, unknown>,\n): SLOpinion {\n try {\n return readOpinionFromRecord({\n ...metadata,\n opinion_b: (node as any).opinion_b,\n opinion_d: (node as any).opinion_d,\n opinion_u: (node as any).opinion_u,\n opinion_a: (node as any).opinion_a,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to read belief opinion snapshot\",\n {\n error,\n beliefId: node._id,\n },\n );\n return mkOpinion(0, 0, 1, 0.5);\n }\n}\n\nexport function deriveTupleContradictionSeverity(\n node: Doc<\"epistemicNodes\">,\n): \"critical\" | \"significant\" | \"minor\" {\n const metadata = (node.metadata || {}) as Record<string, unknown>;\n const criticality =\n typeof metadata.criticality === \"string\" ? metadata.criticality : undefined;\n\n if (criticality === \"blocking\") {\n return \"critical\";\n }\n if (criticality === \"supporting\") {\n return \"minor\";\n }\n return \"significant\";\n}\n\nexport function formatTupleContradictionDescription(args: {\n opinion: Opinion;\n policy: ConfidencePolicyConfig[\"tupleContradiction\"];\n}): string {\n return `Tuple-space contradiction detected: b=${args.opinion.b.toFixed(2)} > ${args.policy.beliefThreshold.toFixed(2)} and d=${args.opinion.d.toFixed(2)} > ${args.policy.disbeliefThreshold.toFixed(2)}.`;\n}\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\nexport function generateContentHash(text: string): string {\n const content = `belief:${text.trim().toLowerCase().replace(/\\s+/g, \" \")}`;\n let hash = 5381;\n for (let i = 0; i < content.length; i++) {\n hash = (hash << 5) + hash + content.charCodeAt(i);\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nexport function resolveBeliefWorktreeId(\n metadata: Record<string, unknown> | undefined,\n): string | undefined {\n const worktreeId = metadata?.worktreeId;\n if (typeof worktreeId === \"string\" && worktreeId.trim().length > 0) {\n return worktreeId;\n }\n\n const sprintId = metadata?.sprintId;\n return typeof sprintId === \"string\" && sprintId.trim().length > 0\n ? sprintId\n : undefined;\n}\n\n// Map pillar names to valid pillar literals\ntype ValidPillar =\n | \"market\"\n | \"competition\"\n | \"product\"\n | \"team\"\n | \"financials\"\n | \"regulatory\"\n | \"timing\"\n | \"customer\"\n | \"technology\"\n | \"distribution\"\n | \"deal\"\n | \"risks\"\n | \"other\";\n\nexport function normalizePillar(pillar?: string): ValidPillar {\n if (!pillar) {\n return \"other\";\n }\n const lower = pillar.toLowerCase();\n const validPillars: ValidPillar[] = [\n \"market\",\n \"competition\",\n \"product\",\n \"team\",\n \"financials\",\n \"regulatory\",\n \"timing\",\n \"customer\",\n \"technology\",\n \"distribution\",\n \"deal\",\n \"risks\",\n ];\n return (validPillars.find((p) => lower.includes(p)) ||\n \"other\") as ValidPillar;\n}\n\nexport async function markBeliefGraphDirty(\n ctx: EpistemicBeliefCtx,\n scope: { projectId?: string | null; topicId?: string | null },\n): Promise<void> {\n const projectId =\n typeof scope.projectId === \"string\" && scope.projectId.trim().length > 0\n ? scope.projectId\n : undefined;\n const topicId =\n typeof scope.topicId === \"string\" && scope.topicId.trim().length > 0\n ? scope.topicId\n : undefined;\n\n if (!projectId && !topicId) {\n return;\n }\n\n if (projectId) {\n await ctx.scheduler.runAfter(\n 0,\n internal.graphAnalysisCache.markCacheStaleInternal,\n { projectId },\n );\n }\n if (topicId) {\n await ctx.scheduler.runAfter(\n 0,\n internal.graphAnalysisCache.markCacheStaleByTopic,\n { topicId },\n );\n }\n\n await resolveGraphPrimitivesAppResolvers(ctx).patchProject(\n ctx,\n topicId ?? projectId!,\n {\n lastActivityAt: Date.now(),\n },\n );\n}\n\nexport async function resolveBeliefScopeOrNull(\n ctx: QueryCtx,\n args: BeliefScopeArgs,\n) {\n if (!args.projectId && !args.topicId) {\n return null;\n }\n\n try {\n return await resolveTopicProjectScope(ctx, {\n projectId: args.projectId ?? undefined,\n topicId: args.topicId ?? undefined,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to resolve belief scope\",\n {\n error,\n projectId: args.projectId,\n topicId: args.topicId,\n },\n );\n return null;\n }\n}\n\nexport async function getBeliefNodesForScope(\n ctx: EpistemicBeliefCtx,\n scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>,\n args?: { scanLimit?: number; status?: string },\n) {\n const baseQuery = ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: any) =>\n q.eq(\"topicId\", scope.topicId).eq(\"nodeType\", \"belief\"),\n );\n const nodes: EpistemicNodeOpinionDoc[] =\n typeof args?.scanLimit === \"number\"\n ? (await baseQuery.order(\"desc\").take(args.scanLimit)) as EpistemicNodeOpinionDoc[]\n : (await baseQuery.collect()) as EpistemicNodeOpinionDoc[];\n const scopedNodes = nodes.filter((node: Doc<\"epistemicNodes\">) =>\n nodeMatchesWorkspaceReasoningScope(node, scope),\n );\n\n if (!args?.status) {\n return scopedNodes;\n }\n\n return scopedNodes.filter((node: EpistemicNodeOpinionDoc) => node.status === args.status);\n}\n\nexport function createBeliefAudienceResolver(\n registryRows: Array<{\n audienceKey?: string | null;\n audienceClass: AudienceClass;\n }>,\n) {\n const audienceClassByKey = new Map<string, AudienceClass>(\n registryRows.map((row) => [\n normalizeAudienceKey(row.audienceKey),\n row.audienceClass,\n ]),\n );\n\n return (\n audienceKey: string | undefined | null,\n fallback: AudienceClass,\n ): AudienceClass => {\n const key = normalizeAudienceKey(audienceKey);\n if (!key) {\n return fallback;\n }\n return (\n audienceClassByKey.get(key) ??\n (classFromAudienceKey(key, fallback) as AudienceClass)\n );\n };\n}\n\nexport function flattenBeliefNode(node: Doc<\"epistemicNodes\">) {\n const meta = (node.metadata || {}) as Record<string, unknown>;\n const worktreeId = resolveBeliefWorktreeId(meta);\n const tupleContradicted =\n readTupleContradictedFlag(\n (node as EpistemicNodeOpinionDoc).tupleContradicted,\n ) ??\n readTupleContradictedFlag(meta.tupleContradicted) ??\n false;\n\n return {\n _id: node._id,\n _epistemicNodeId: node._id,\n _creationTime: node._creationTime,\n belief: node.canonicalText,\n formulation: node.canonicalText,\n projectId: node.projectId,\n topicId: node.topicId,\n userId: (node as EpistemicNodeOpinionDoc).userId || node.createdBy || \"\",\n confidence: (meta.confidence as \"high\" | \"medium\" | \"low\") || \"untested\",\n status: node.status,\n beliefStatus: resolveBeliefStatus(node, meta),\n topic: (meta.topic as string) || (meta.pillar as string) || \"other\",\n pillar: (meta.pillar as string) || (meta.topic as string) || \"\",\n category: (meta.category as string) || \"\",\n subcategory: (meta.subcategory as string) || \"\",\n categoryIcon: (meta.categoryIcon as string) || \"\",\n supportingEvidence: (meta.supportingEvidenceIds as string[]) || [],\n contradictingEvidence: (meta.contradictingEvidenceIds as string[]) || [],\n testingQuestions: (meta.testingQuestionIds as string[]) || [],\n linkedInsights: (meta.linkedInsightIds as string[]) || [],\n createdAt: node.createdAt,\n updatedAt: node.updatedAt || node.createdAt,\n tupleContradicted,\n sprintId: (meta.sprintId as string) || undefined,\n worktreeId,\n sourceBeliefIds: (meta.sourceBeliefIds as string[]) || undefined,\n criticality:\n (meta.criticality as\n | \"critical\"\n | \"supporting\"\n | \"nice_to_have\"\n | \"unanalyzed\"\n | \"blocking\"\n | \"important\") || \"unanalyzed\",\n rationale: (meta.rationale as string) || \"\",\n audienceLabel: node.audienceLabel,\n policyTags: node.policyTags,\n sensitivityTier: node.sensitivityTier,\n exportClass: node.exportClass,\n anonymizationClass: node.anonymizationClass,\n };\n}\n\nexport function resolveBeliefStatus(\n node: {\n beliefStatus?: unknown;\n confidence?: unknown;\n predictionMeta?: unknown;\n },\n metadata: Record<string, unknown>,\n): BeliefLifecycleStatus {\n return resolveBeliefLifecycleStatus({\n beliefStatus: node.beliefStatus,\n confidence: node.confidence,\n predictionMeta: node.predictionMeta,\n metadata,\n });\n}\n\nexport async function hasCompletedWorktreeForBelief(\n ctx: EpistemicBeliefCtx,\n beliefNodeId: Id<\"epistemicNodes\">,\n): Promise<boolean> {\n // Check if the belief is linked to a completed worktree via worktreeBeliefCluster\n const clusterMembership = await ctx.db\n .query(\"worktreeBeliefCluster\")\n .withIndex(\"by_belief\", (q: any) => q.eq(\"beliefId\", beliefNodeId))\n .collect();\n for (const membership of clusterMembership) {\n const worktree = await ctx.db.get(membership.worktreeId);\n if (worktree?.status === \"completed\" || worktree?.status === \"merged\") {\n return true;\n }\n }\n return false;\n}\n\nexport async function getActiveConfidencePolicy(\n ctx: EpistemicBeliefCtx,\n): Promise<ConfidencePolicyConfig> {\n try {\n const activeConfig = await ctx.db\n .query(\"logicSprintScoring\")\n .withIndex(\"by_active\", (q: any) => q.eq(\"isActive\", true))\n .first();\n\n return {\n scoringMode:\n activeConfig?.confidencePolicy === \"always\"\n ? \"always\"\n : DEFAULT_CONFIDENCE_POLICY.scoringMode,\n tupleContradiction: normalizeTupleContradictionPolicy(\n activeConfig?.tupleContradictionPolicy as\n | Partial<ConfidencePolicyConfig[\"tupleContradiction\"]>\n | undefined,\n ),\n };\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to load active confidence policy\",\n {\n error,\n },\n );\n // K-tier/component environments do not carry logicSprintScoring.\n return DEFAULT_CONFIDENCE_POLICY;\n }\n}\n\nexport async function requireAuthenticatedUserId(ctx: {\n auth: { getUserIdentity: () => Promise<unknown> };\n}): Promise<string> {\n const userId = await getCurrentUserId(\n ctx as Parameters<typeof getCurrentUserId>[0],\n );\n if (!userId) {\n throwStructuredMutationError({\n message: \"Authentication required.\",\n status: 401,\n code: \"AUTHENTICATION_REQUIRED\",\n invariantCode: \"auth.required\",\n suggestion:\n \"Provide a valid bearer token before invoking belief mutations.\",\n });\n }\n return userId;\n}\n\nexport async function requireProjectWriteAccess(\n ctx: { db: unknown },\n projectId: string,\n userId: string,\n): Promise<void> {\n const hasAccess = await checkProjectAccess(\n ctx as Parameters<typeof checkProjectAccess>[0],\n projectId,\n userId,\n );\n if (!hasAccess) {\n // FR.7: structured, non-retryable 403 naming ONLY the targeted topic and\n // the caller's own principal (no cross-tenant leakage; security condition e).\n throwStructuredMutationError({\n message: `Project write access denied for topic ${projectId}.`,\n status: 403,\n code: \"PROJECT_ACCESS_DENIED\",\n invariantCode: \"policy.scope_required\",\n suggestion:\n \"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.\",\n details: { topicId: projectId, principalId: userId },\n });\n }\n}\n","/** Evidence-gated fork precondition helpers. */\n\nimport type { Doc, Id, MutationCtx } from \"./convex\";\nimport { throwStructuredMutationError } from \"./epistemicBeliefs.helpers\";\n\nexport type ForkMode = \"supersede\" | \"branch\";\nexport type ForkTriggerRelation = \"supports\" | \"contradicts\";\n\nfunction normalizeForkTriggerRelation(\n value: unknown,\n): ForkTriggerRelation | null {\n if (value === \"supports\" || value === \"supporting\") {\n return \"supports\";\n }\n if (value === \"contradicts\" || value === \"contradicting\") {\n return \"contradicts\";\n }\n return null;\n}\n\nexport async function resolveForkTriggerEvidence(\n ctx: MutationCtx,\n args: {\n parentNodeId: Id<\"epistemicNodes\">;\n parent: Doc<\"epistemicNodes\">;\n triggeringEvidenceId: Id<\"epistemicNodes\">;\n forkMode: ForkMode;\n },\n): Promise<{ evidenceNodeId: Id<\"epistemicNodes\">; relation: ForkTriggerRelation }> {\n const evidence = await ctx.db.get(args.triggeringEvidenceId);\n if (!evidence || evidence.nodeType !== \"evidence\") {\n throwStructuredMutationError({\n message: \"Fork requires an existing evidence node.\",\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"belief.fork_requires_evidence\",\n suggestion:\n \"Create or link evidence first, then fork with triggeringEvidenceId.\",\n details: { triggeringEvidenceId: args.triggeringEvidenceId },\n });\n }\n if (evidence.topicId && evidence.topicId !== args.parent.topicId) {\n throwStructuredMutationError({\n message: \"Fork evidence belongs to a different topic scope.\",\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"belief.fork_evidence_scope\",\n suggestion: \"Use evidence from the same topic/workspace scope as the parent belief.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n },\n });\n }\n\n const evidenceMetadata =\n evidence.metadata && typeof evidence.metadata === \"object\"\n ? (evidence.metadata as Record<string, unknown>)\n : {};\n const parentRefs = new Set(\n [\n String(args.parentNodeId),\n String(args.parent.globalId ?? \"\"),\n String(args.parent._id),\n ].filter(Boolean),\n );\n const evidenceRefs = new Set(\n [\n String(args.triggeringEvidenceId),\n String(evidence.globalId ?? \"\"),\n String(evidence._id),\n ].filter(Boolean),\n );\n\n let relation: ForkTriggerRelation | null = null;\n const linkedBeliefNodeId = String(\n evidenceMetadata.linkedBeliefNodeId ?? \"\",\n );\n if (linkedBeliefNodeId && parentRefs.has(linkedBeliefNodeId)) {\n relation = normalizeForkTriggerRelation(evidenceMetadata.evidenceRelation);\n }\n\n if (!relation) {\n for (const parentRef of parentRefs) {\n const links = await ctx.db\n .query(\"beliefEvidenceLinks\")\n .withIndex(\"by_beliefId\", (q) => q.eq(\"beliefId\", parentRef))\n .collect();\n const matched = links.find((link) => evidenceRefs.has(String(link.insightId)));\n if (matched) {\n relation = normalizeForkTriggerRelation(matched.relation);\n break;\n }\n }\n }\n\n if (!relation) {\n throwStructuredMutationError({\n message:\n \"Fork evidence must already be attached to the parent belief through an SL evidence relation.\",\n status: 409,\n code: \"CONFLICT\",\n invariantCode: \"belief.fork_requires_attached_evidence\",\n suggestion:\n \"Attach the evidence to the parent belief as supports or contradicts before forking.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n },\n });\n }\n if (args.forkMode === \"supersede\" && relation !== \"contradicts\") {\n throwStructuredMutationError({\n message:\n \"Superseding fork requires contradicting evidence against the parent belief.\",\n status: 409,\n code: \"CONFLICT\",\n invariantCode: \"belief.supersede_requires_contradiction\",\n suggestion:\n \"Use forkMode='branch' for a non-replacing fork, or attach contradicting evidence before superseding.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n relation,\n },\n });\n }\n\n return { evidenceNodeId: args.triggeringEvidenceId, relation };\n}\n"]}
1
+ {"version":3,"sources":["../src/epistemicBeliefs.helpers.ts","../src/epistemicBeliefs.forkEvidence.ts"],"names":["throwStructuredMutationError"],"mappings":"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","file":"epistemicBeliefs.forkEvidence.js","sourcesContent":["// biome-ignore-all lint/style/useFilenamingConvention: Public graph-primitives wildcard-export path; rename requires an export-map migration.\n/**\n * Epistemic Beliefs API\n *\n * Clean API for managing beliefs in the epistemic spine (epistemicNodes).\n * This is the NEW API that replaces beliefs.ts.\n *\n * Key differences from beliefs.ts:\n * - Writes ONLY to epistemicNodes (no dual-write)\n * - Uses epistemicNodes IDs directly (no runtime ID translation fallback)\n * - Syncs to Neo4j after mutations\n * - Follows Lucern invariants strictly\n *\n * @see /docs/epistemic-invariants/00-epistemic-invariants.md\n */\n\nimport {\n classFromAudienceKey,\n normalizeAudienceKey,\n} from \"@lucern/access-control/audience\";\nimport { getCurrentUserId } from \"@lucern/access-control/auth\";\nimport { throwStructuredMutationError } from \"@lucern/access-control/structuredMutationError\";\nimport {\n type ConfidencePolicyConfig,\n confidenceFromSL,\n mkOpinion,\n normalizeTupleContradictionPolicy,\n type Opinion,\n readOpinionFromRecord,\n type SLOperator,\n type SLOpinion,\n} from \"@lucern/confidence\";\nimport { v } from \"convex/values\";\nimport {\n type BeliefLifecycleStatus,\n resolveBeliefLifecycleStatus,\n} from \"./beliefLifecycle\";\nimport type { Id, QueryCtx } from \"./convex\";\nimport { internal } from \"./convex\";\nimport { debugGraphPrimitiveFallback } from \"./debug\";\nimport type { VerificationConfidenceTrigger } from \"./epistemicContractHelpers\";\nimport { resolveGraphPrimitivesAppResolvers } from \"./resolvers\";\nimport { optionalScopeArgs, resolveTopicProjectScope } from \"./topicScope\";\nimport { nodeMatchesWorkspaceReasoningScope } from \"./workspaceIsolation\";\n\n// All IDs now use epistemicNodes exclusively\nexport const insightIdUnion = v.id(\"epistemicNodes\");\nconst DEFAULT_PROJECT_BELIEF_LIMIT = 250;\nexport const MAX_PROJECT_BELIEF_LIMIT = 1000;\nexport const optionalBeliefScopeArgs = optionalScopeArgs;\n\n// CQ.11: the structured-refusal primitive is the single shared copy in\n// `@lucern/access-control/structuredMutationError` (the same home the shared\n// access gate throws from). Re-exported here so the graph-primitives modules\n// that imported it from this helper keep their import path unchanged.\nexport type { StructuredMutationErrorData } from \"@lucern/access-control/structuredMutationError\";\n// biome-ignore lint/performance/noBarrelFile: Public helper compatibility re-export retained for existing graph-primitives consumers.\nexport { throwStructuredMutationError } from \"@lucern/access-control/structuredMutationError\";\n\ninterface BeliefScopeArgs {\n projectId?: string | null;\n topicId?: string | null;\n}\n\ninterface EpistemicNodeOpinionSource {\n _id?: unknown;\n metadata?: Record<string, unknown> | null;\n opinion_a?: number;\n opinion_b?: number;\n opinion_d?: number;\n opinion_u?: number;\n tupleContradicted?: boolean;\n userId?: string;\n}\n\nexport interface EpistemicNodeOpinionDoc extends EpistemicNodeOpinionSource {\n _creationTime?: number;\n _id: Id<\"epistemicNodes\">;\n anonymizationClass?: string;\n audienceLabel?: string;\n beliefStatus?: unknown;\n canonicalText?: string;\n confidence?: unknown;\n createdAt?: number;\n createdBy?: string;\n epistemicLayer?: string;\n exportClass?: string;\n globalId?: string;\n metadata?: Record<string, unknown> | null;\n nodeType: \"belief\";\n policyTags?: string[];\n predictionMeta?: unknown;\n projectId?: string;\n publicationStatus?: string;\n sensitivityTier?: string;\n status?: string;\n tenantId?: string;\n topicId?: string;\n updatedAt?: number;\n workspaceId?: string;\n}\n\ninterface EpistemicIndexQuery {\n eq(field: string, value: unknown): EpistemicIndexQuery;\n field(field: string): string;\n gt(field: string, value: unknown): EpistemicIndexQuery;\n lt(field: string, value: unknown): EpistemicIndexQuery;\n}\n\ntype EpistemicBeliefCtx = QueryCtx;\n\ntype AudienceClass = \"internal\" | \"restricted_external\" | \"public\";\n\nconst DEFAULT_CONFIDENCE_POLICY: ConfidencePolicyConfig = {\n scoringMode: \"after_worktree\",\n tupleContradiction: normalizeTupleContradictionPolicy(),\n};\n\nexport type BeliefConfidenceTrigger =\n | \"initial\"\n | \"evidence_added\"\n | \"evidence_removed\"\n | \"contradiction_detected\"\n | \"contradiction_resolved\"\n | \"propagation\"\n | \"agent_assessment\"\n | \"worktree_outcome\"\n | \"worktree_completed\"\n // SL-specific triggers\n | \"fusion\"\n | \"discount\"\n | \"deduction\"\n | \"backfill_synthetic\"\n | VerificationConfidenceTrigger;\n\nexport function readFiniteNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction readOptionalString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value\n : undefined;\n}\n\nfunction readStringArray(value: unknown): string[] | undefined {\n if (!Array.isArray(value)) {\n return;\n }\n const strings = value.filter(\n (item): item is string => typeof item === \"string\" && item.length > 0\n );\n return strings.length === value.length ? strings : undefined;\n}\n\nfunction readRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nexport function readBeliefNodeView(\n value: unknown\n): EpistemicNodeOpinionDoc | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const id = readOptionalString(value._id) as Id<\"epistemicNodes\"> | undefined;\n const nodeType = readOptionalString(value.nodeType);\n if (!(id && nodeType === \"belief\")) {\n return null;\n }\n\n const node: EpistemicNodeOpinionDoc = {\n _id: id,\n nodeType,\n };\n const creationTime = readFiniteNumber(value._creationTime);\n if (creationTime !== undefined) {\n node._creationTime = creationTime;\n }\n const metadata = readRecord(value.metadata);\n if (metadata !== undefined) {\n node.metadata = metadata;\n }\n const opinionA = readFiniteNumber(value.opinion_a);\n if (opinionA !== undefined) {\n node.opinion_a = opinionA;\n }\n const opinionB = readFiniteNumber(value.opinion_b);\n if (opinionB !== undefined) {\n node.opinion_b = opinionB;\n }\n const opinionD = readFiniteNumber(value.opinion_d);\n if (opinionD !== undefined) {\n node.opinion_d = opinionD;\n }\n const opinionU = readFiniteNumber(value.opinion_u);\n if (opinionU !== undefined) {\n node.opinion_u = opinionU;\n }\n const tupleContradicted =\n typeof value.tupleContradicted === \"boolean\"\n ? value.tupleContradicted\n : undefined;\n if (tupleContradicted !== undefined) {\n node.tupleContradicted = tupleContradicted;\n }\n\n const stringFields = {\n anonymizationClass: value.anonymizationClass,\n audienceLabel: value.audienceLabel,\n canonicalText: value.canonicalText,\n createdBy: value.createdBy,\n epistemicLayer: value.epistemicLayer,\n exportClass: value.exportClass,\n globalId: value.globalId,\n projectId: value.projectId,\n publicationStatus: value.publicationStatus,\n sensitivityTier: value.sensitivityTier,\n status: value.status,\n tenantId: value.tenantId,\n topicId: value.topicId,\n userId: value.userId,\n workspaceId: value.workspaceId,\n };\n for (const [field, fieldValue] of Object.entries(stringFields)) {\n const normalized = readOptionalString(fieldValue);\n if (normalized !== undefined) {\n node[field as keyof typeof stringFields] = normalized;\n }\n }\n\n const createdAt = readFiniteNumber(value.createdAt);\n if (createdAt !== undefined) {\n node.createdAt = createdAt;\n }\n const updatedAt = readFiniteNumber(value.updatedAt);\n if (updatedAt !== undefined) {\n node.updatedAt = updatedAt;\n }\n if (value.beliefStatus !== undefined) {\n node.beliefStatus = value.beliefStatus;\n }\n if (value.confidence !== undefined) {\n node.confidence = value.confidence;\n }\n if (value.predictionMeta !== undefined) {\n node.predictionMeta = value.predictionMeta;\n }\n const policyTags = readStringArray(value.policyTags);\n if (policyTags !== undefined) {\n node.policyTags = policyTags;\n }\n\n return node;\n}\n\nfunction readBeliefNodeViews(\n values: readonly unknown[]\n): EpistemicNodeOpinionDoc[] {\n return values.flatMap((value) => {\n const node = readBeliefNodeView(value);\n return node ? [node] : [];\n });\n}\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function assertBaseRateInRange(\n baseRate: number,\n field = \"baseRate\"\n): number {\n if (baseRate < 0 || baseRate > 1) {\n throwStructuredMutationError({\n message: `${field} must be within [0, 1].`,\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"request.valid_shape\",\n suggestion: `Clamp ${field} into the inclusive [0, 1] interval.`,\n details: { field, baseRate },\n });\n }\n return baseRate;\n}\n\nexport function buildBeliefConfidenceRow(args: {\n beliefId: Id<\"epistemicNodes\">;\n belief: number;\n disbelief: number;\n uncertainty: number;\n baseRate: number;\n trigger: BeliefConfidenceTrigger;\n rationale?: string;\n assessedBy: string;\n assessedAt: number;\n slOperator?: SLOperator;\n triggeringEvidenceId?: Id<\"epistemicNodes\">;\n triggeringContradictionId?: Id<\"contradictions\">;\n triggeringWorktreeId?: string;\n}) {\n return {\n beliefId: args.beliefId,\n confidence: confidenceFromSL(\n args.belief,\n args.disbelief,\n args.uncertainty,\n args.baseRate\n ),\n belief: args.belief,\n disbelief: args.disbelief,\n uncertainty: args.uncertainty,\n baseRate: args.baseRate,\n slOperator: args.slOperator ?? (\"prior_seed\" as const),\n trigger: args.trigger,\n ...(args.rationale ? { rationale: args.rationale } : {}),\n assessedBy: args.assessedBy,\n assessedAt: args.assessedAt,\n ...(args.triggeringEvidenceId\n ? {\n triggeringEvidenceId: args.triggeringEvidenceId,\n triggeringEvidenceIds: [String(args.triggeringEvidenceId)],\n }\n : {}),\n ...(args.triggeringContradictionId\n ? {\n triggeringContradictionId: args.triggeringContradictionId,\n }\n : {}),\n ...(args.triggeringWorktreeId\n ? { triggeringWorktreeId: args.triggeringWorktreeId }\n : {}),\n };\n}\n\ntype BeliefStatusResult =\n | { success: true }\n | { success: false; message: \"Evidence node not found\" };\n\nexport function buildBeliefStatusSuccessResult(): BeliefStatusResult {\n return { success: true };\n}\n\nexport function buildBeliefEvidenceNotFoundResult(): BeliefStatusResult {\n const result = {} as Extract<BeliefStatusResult, { success: false }>;\n result.success = false;\n result.message = \"Evidence node not found\";\n return result;\n}\n\nexport function deriveSyntheticBackfillOpinion(\n source: Record<string, unknown>\n): SLOpinion {\n const belief =\n readFiniteNumber(source.opinion_b) ?? readFiniteNumber(source.belief);\n const disbelief =\n readFiniteNumber(source.opinion_d) ?? readFiniteNumber(source.disbelief);\n const uncertainty =\n readFiniteNumber(source.opinion_u) ?? readFiniteNumber(source.uncertainty);\n const baseRate =\n readFiniteNumber(source.opinion_a) ?? readFiniteNumber(source.baseRate);\n\n if (\n belief !== undefined ||\n disbelief !== undefined ||\n uncertainty !== undefined ||\n baseRate !== undefined\n ) {\n try {\n return readOpinionFromRecord(source);\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to decode legacy belief opinion\",\n {\n error,\n }\n );\n return mkOpinion(0, 0, 1, 0.5);\n }\n }\n\n const confidence = clamp01(readFiniteNumber(source.confidence) ?? 0);\n return mkOpinion(confidence, 1 - confidence, 0, 0.5);\n}\n\nexport function clampBeliefLimit(\n limit: number | undefined,\n fallback = DEFAULT_PROJECT_BELIEF_LIMIT\n): number {\n if (!Number.isFinite(limit)) {\n return fallback;\n }\n return Math.max(\n 1,\n Math.min(Math.floor(limit as number), MAX_PROJECT_BELIEF_LIMIT)\n );\n}\n\nexport function readTupleContradictedFlag(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nexport function readBeliefOpinionSnapshot(\n node: EpistemicNodeOpinionSource,\n metadata: Record<string, unknown>\n): SLOpinion {\n try {\n return readOpinionFromRecord({\n ...metadata,\n opinion_b: node.opinion_b,\n opinion_d: node.opinion_d,\n opinion_u: node.opinion_u,\n opinion_a: node.opinion_a,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to read belief opinion snapshot\",\n {\n error,\n beliefId: node._id,\n }\n );\n return mkOpinion(0, 0, 1, 0.5);\n }\n}\n\nexport function deriveTupleContradictionSeverity(node: {\n metadata?: Record<string, unknown> | null;\n}): \"critical\" | \"significant\" | \"minor\" {\n const metadata = node.metadata || {};\n const criticality =\n typeof metadata.criticality === \"string\" ? metadata.criticality : undefined;\n\n if (criticality === \"blocking\") {\n return \"critical\";\n }\n if (criticality === \"supporting\") {\n return \"minor\";\n }\n return \"significant\";\n}\n\nexport function formatTupleContradictionDescription(args: {\n opinion: Opinion;\n policy: ConfidencePolicyConfig[\"tupleContradiction\"];\n}): string {\n return `Tuple-space contradiction detected: b=${args.opinion.b.toFixed(2)} > ${args.policy.beliefThreshold.toFixed(2)} and d=${args.opinion.d.toFixed(2)} > ${args.policy.disbeliefThreshold.toFixed(2)}.`;\n}\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\nexport function generateContentHash(text: string): string {\n const content = `belief:${text.trim().toLowerCase().replace(/\\s+/g, \" \")}`;\n let hash = 5381;\n for (let i = 0; i < content.length; i++) {\n // biome-ignore lint/suspicious/noBitwiseOperators: Preserve deterministic djb2 hash semantics for persisted belief metadata compatibility.\n hash = (hash << 5) + hash + content.charCodeAt(i);\n // biome-ignore lint/suspicious/noBitwiseOperators: Preserve deterministic djb2 hash semantics for persisted belief metadata compatibility.\n hash &= hash;\n }\n return Math.abs(hash).toString(16).padStart(8, \"0\");\n}\n\nexport function resolveBeliefWorktreeId(\n metadata: Record<string, unknown> | undefined\n): string | undefined {\n const worktreeId = metadata?.worktreeId;\n if (typeof worktreeId === \"string\" && worktreeId.trim().length > 0) {\n return worktreeId;\n }\n\n const sprintId = metadata?.sprintId;\n return typeof sprintId === \"string\" && sprintId.trim().length > 0\n ? sprintId\n : undefined;\n}\n\n// Map pillar names to valid pillar literals\ntype ValidPillar =\n | \"market\"\n | \"competition\"\n | \"product\"\n | \"team\"\n | \"financials\"\n | \"regulatory\"\n | \"timing\"\n | \"customer\"\n | \"technology\"\n | \"distribution\"\n | \"deal\"\n | \"risks\"\n | \"other\";\n\nexport function normalizePillar(pillar?: string): ValidPillar {\n if (!pillar) {\n return \"other\";\n }\n const lower = pillar.toLowerCase();\n const validPillars: ValidPillar[] = [\n \"market\",\n \"competition\",\n \"product\",\n \"team\",\n \"financials\",\n \"regulatory\",\n \"timing\",\n \"customer\",\n \"technology\",\n \"distribution\",\n \"deal\",\n \"risks\",\n ];\n return (validPillars.find((p) => lower.includes(p)) ||\n \"other\") as ValidPillar;\n}\n\nexport async function markBeliefGraphDirty(\n ctx: EpistemicBeliefCtx,\n scope: { projectId?: string | null; topicId?: string | null }\n): Promise<void> {\n const projectId =\n typeof scope.projectId === \"string\" && scope.projectId.trim().length > 0\n ? scope.projectId\n : undefined;\n const topicId =\n typeof scope.topicId === \"string\" && scope.topicId.trim().length > 0\n ? scope.topicId\n : undefined;\n\n if (!(projectId || topicId)) {\n return;\n }\n\n if (projectId) {\n await ctx.scheduler.runAfter(\n 0,\n internal.graphAnalysisCache.markCacheStaleInternal,\n { projectId }\n );\n }\n if (topicId) {\n await ctx.scheduler.runAfter(\n 0,\n internal.graphAnalysisCache.markCacheStaleByTopic,\n { topicId }\n );\n }\n\n const activityScopeId = topicId ?? projectId;\n if (!activityScopeId) {\n throw new Error(\n \"Expected belief graph dirty scope to include a topic or project id.\"\n );\n }\n\n await resolveGraphPrimitivesAppResolvers(ctx).patchProject(\n ctx,\n activityScopeId,\n {\n lastActivityAt: Date.now(),\n }\n );\n}\n\nexport async function resolveBeliefScopeOrNull(\n ctx: QueryCtx,\n args: BeliefScopeArgs\n) {\n if (!(args.projectId || args.topicId)) {\n return null;\n }\n\n try {\n return await resolveTopicProjectScope(ctx, {\n projectId: args.projectId ?? undefined,\n topicId: args.topicId ?? undefined,\n });\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to resolve belief scope\",\n {\n error,\n projectId: args.projectId,\n topicId: args.topicId,\n }\n );\n return null;\n }\n}\n\nexport async function getBeliefNodesForScope(\n ctx: EpistemicBeliefCtx,\n scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>,\n args?: { scanLimit?: number; status?: string }\n) {\n const baseQuery = ctx.db\n .query(\"epistemicNodes\")\n .withIndex(\"by_topic_type\", (q: EpistemicIndexQuery) =>\n q.eq(\"topicId\", scope.topicId).eq(\"nodeType\", \"belief\")\n );\n const rows =\n typeof args?.scanLimit === \"number\"\n ? await baseQuery.order(\"desc\").take(args.scanLimit)\n : await baseQuery.collect();\n const nodes = readBeliefNodeViews(rows);\n const scopedNodes = nodes.filter((node) =>\n nodeMatchesWorkspaceReasoningScope(node, scope)\n );\n\n if (!args?.status) {\n return scopedNodes;\n }\n\n return scopedNodes.filter(\n (node: EpistemicNodeOpinionDoc) => node.status === args.status\n );\n}\n\nexport function createBeliefAudienceResolver(\n registryRows: Array<{\n audienceKey?: string | null;\n audienceClass: AudienceClass;\n }>\n) {\n const audienceClassByKey = new Map<string, AudienceClass>(\n registryRows.map((row) => [\n normalizeAudienceKey(row.audienceKey),\n row.audienceClass,\n ])\n );\n\n return (\n audienceKey: string | undefined | null,\n fallback: AudienceClass\n ): AudienceClass => {\n const key = normalizeAudienceKey(audienceKey);\n if (!key) {\n return fallback;\n }\n return (\n audienceClassByKey.get(key) ??\n (classFromAudienceKey(key, fallback) as AudienceClass)\n );\n };\n}\n\nexport function flattenBeliefNode(node: EpistemicNodeOpinionDoc) {\n const meta = node.metadata || {};\n const worktreeId = resolveBeliefWorktreeId(meta);\n const tupleContradicted =\n readTupleContradictedFlag(node.tupleContradicted) ??\n readTupleContradictedFlag(meta.tupleContradicted) ??\n false;\n\n return {\n _id: node._id,\n _epistemicNodeId: node._id,\n _creationTime: node._creationTime,\n belief: node.canonicalText,\n formulation: node.canonicalText,\n projectId: node.projectId,\n topicId: node.topicId,\n userId: node.userId || node.createdBy || \"\",\n confidence: (meta.confidence as \"high\" | \"medium\" | \"low\") || \"untested\",\n status: node.status,\n beliefStatus: resolveBeliefStatus(node, meta),\n topic: (meta.topic as string) || (meta.pillar as string) || \"other\",\n pillar: (meta.pillar as string) || (meta.topic as string) || \"\",\n category: (meta.category as string) || \"\",\n subcategory: (meta.subcategory as string) || \"\",\n categoryIcon: (meta.categoryIcon as string) || \"\",\n supportingEvidence: (meta.supportingEvidenceIds as string[]) || [],\n contradictingEvidence: (meta.contradictingEvidenceIds as string[]) || [],\n testingQuestions: (meta.testingQuestionIds as string[]) || [],\n linkedInsights: (meta.linkedInsightIds as string[]) || [],\n createdAt: node.createdAt,\n updatedAt: node.updatedAt || node.createdAt,\n tupleContradicted,\n sprintId: (meta.sprintId as string) || undefined,\n worktreeId,\n sourceBeliefIds: (meta.sourceBeliefIds as string[]) || undefined,\n criticality:\n (meta.criticality as\n | \"critical\"\n | \"supporting\"\n | \"nice_to_have\"\n | \"unanalyzed\"\n | \"blocking\"\n | \"important\") || \"unanalyzed\",\n rationale: (meta.rationale as string) || \"\",\n audienceLabel: node.audienceLabel,\n policyTags: node.policyTags,\n sensitivityTier: node.sensitivityTier,\n exportClass: node.exportClass,\n anonymizationClass: node.anonymizationClass,\n };\n}\n\nexport function resolveBeliefStatus(\n node: {\n beliefStatus?: unknown;\n confidence?: unknown;\n predictionMeta?: unknown;\n },\n metadata: Record<string, unknown>\n): BeliefLifecycleStatus {\n return resolveBeliefLifecycleStatus({\n beliefStatus: node.beliefStatus,\n confidence: node.confidence,\n predictionMeta: node.predictionMeta,\n metadata,\n });\n}\n\nexport async function hasCompletedWorktreeForBelief(\n ctx: EpistemicBeliefCtx,\n beliefNodeId: Id<\"epistemicNodes\">\n): Promise<boolean> {\n // Check if the belief is linked to a completed worktree via worktreeBeliefCluster\n const clusterMembership = await ctx.db\n .query(\"worktreeBeliefCluster\")\n .withIndex(\"by_belief\", (q: EpistemicIndexQuery) =>\n q.eq(\"beliefId\", beliefNodeId)\n )\n .collect();\n for (const membership of clusterMembership) {\n const worktree = await ctx.db.get(membership.worktreeId);\n if (worktree?.status === \"completed\" || worktree?.status === \"merged\") {\n return true;\n }\n }\n return false;\n}\n\nexport async function getActiveConfidencePolicy(\n ctx: EpistemicBeliefCtx\n): Promise<ConfidencePolicyConfig> {\n try {\n const activeConfig = await ctx.db\n .query(\"logicSprintScoring\")\n .withIndex(\"by_active\", (q: EpistemicIndexQuery) =>\n q.eq(\"isActive\", true)\n )\n .first();\n\n return {\n scoringMode:\n activeConfig?.confidencePolicy === \"always\"\n ? \"always\"\n : DEFAULT_CONFIDENCE_POLICY.scoringMode,\n tupleContradiction: normalizeTupleContradictionPolicy(\n activeConfig?.tupleContradictionPolicy as\n | Partial<ConfidencePolicyConfig[\"tupleContradiction\"]>\n | undefined\n ),\n };\n } catch (error) {\n debugGraphPrimitiveFallback(\n \"[epistemicBeliefs] Failed to load active confidence policy\",\n {\n error,\n }\n );\n // K-tier/component environments do not carry logicSprintScoring.\n return DEFAULT_CONFIDENCE_POLICY;\n }\n}\n\nexport async function requireAuthenticatedUserId(ctx: {\n auth: { getUserIdentity: () => Promise<unknown> };\n}): Promise<string> {\n const userId = await getCurrentUserId(\n ctx as Parameters<typeof getCurrentUserId>[0]\n );\n if (!userId) {\n throwStructuredMutationError({\n message: \"Authentication required.\",\n status: 401,\n code: \"AUTHENTICATION_REQUIRED\",\n invariantCode: \"auth.required\",\n suggestion:\n \"Provide a valid bearer token before invoking belief mutations.\",\n });\n }\n return userId;\n}\n","// biome-ignore-all lint/style/useFilenamingConvention: Public graph-primitives wildcard-export path; rename requires an export-map migration.\n/** Evidence-gated fork precondition helpers. */\n\nimport type { Doc, Id, MutationCtx } from \"./convex\";\nimport { throwStructuredMutationError } from \"./epistemicBeliefs.helpers\";\n\nexport type ForkMode = \"supersede\" | \"branch\";\nexport type ForkTriggerRelation = \"supports\" | \"contradicts\";\n\nfunction normalizeForkTriggerRelation(\n value: unknown\n): ForkTriggerRelation | null {\n if (value === \"supports\" || value === \"supporting\") {\n return \"supports\";\n }\n if (value === \"contradicts\" || value === \"contradicting\") {\n return \"contradicts\";\n }\n return null;\n}\n\nexport async function resolveForkTriggerEvidence(\n ctx: MutationCtx,\n args: {\n parentNodeId: Id<\"epistemicNodes\">;\n parent: Doc<\"epistemicNodes\">;\n triggeringEvidenceId: Id<\"epistemicNodes\">;\n forkMode: ForkMode;\n }\n): Promise<{\n evidenceNodeId: Id<\"epistemicNodes\">;\n relation: ForkTriggerRelation;\n}> {\n const evidence = await ctx.db.get(args.triggeringEvidenceId);\n if (evidence?.nodeType !== \"evidence\") {\n throwStructuredMutationError({\n message: \"Fork requires an existing evidence node.\",\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"belief.fork_requires_evidence\",\n suggestion:\n \"Create or link evidence first, then fork with triggeringEvidenceId.\",\n details: { triggeringEvidenceId: args.triggeringEvidenceId },\n });\n }\n if (evidence.topicId && evidence.topicId !== args.parent.topicId) {\n throwStructuredMutationError({\n message: \"Fork evidence belongs to a different topic scope.\",\n status: 400,\n code: \"INVALID_ARGUMENT\",\n invariantCode: \"belief.fork_evidence_scope\",\n suggestion:\n \"Use evidence from the same topic/workspace scope as the parent belief.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n },\n });\n }\n\n const evidenceMetadata =\n evidence.metadata && typeof evidence.metadata === \"object\"\n ? (evidence.metadata as Record<string, unknown>)\n : {};\n const parentRefs = new Set(\n [\n String(args.parentNodeId),\n String(args.parent.globalId ?? \"\"),\n String(args.parent._id),\n ].filter(Boolean)\n );\n const evidenceRefs = new Set(\n [\n String(args.triggeringEvidenceId),\n String(evidence.globalId ?? \"\"),\n String(evidence._id),\n ].filter(Boolean)\n );\n\n let relation: ForkTriggerRelation | null = null;\n const linkedBeliefNodeId = String(evidenceMetadata.linkedBeliefNodeId ?? \"\");\n if (linkedBeliefNodeId && parentRefs.has(linkedBeliefNodeId)) {\n relation = normalizeForkTriggerRelation(evidenceMetadata.evidenceRelation);\n }\n\n if (!relation) {\n for (const parentRef of parentRefs) {\n const links = await ctx.db\n .query(\"beliefEvidenceLinks\")\n .withIndex(\"by_beliefId\", (q) => q.eq(\"beliefId\", parentRef))\n .collect();\n const matched = links.find((link) =>\n evidenceRefs.has(String(link.insightId))\n );\n if (matched) {\n relation = normalizeForkTriggerRelation(matched.relation);\n break;\n }\n }\n }\n\n if (!relation) {\n throwStructuredMutationError({\n message:\n \"Fork evidence must already be attached to the parent belief through an SL evidence relation.\",\n status: 409,\n code: \"CONFLICT\",\n invariantCode: \"belief.fork_requires_attached_evidence\",\n suggestion:\n \"Attach the evidence to the parent belief as supports or contradicts before forking.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n },\n });\n }\n if (args.forkMode === \"supersede\" && relation !== \"contradicts\") {\n throwStructuredMutationError({\n message:\n \"Superseding fork requires contradicting evidence against the parent belief.\",\n status: 409,\n code: \"CONFLICT\",\n invariantCode: \"belief.supersede_requires_contradiction\",\n suggestion:\n \"Use forkMode='branch' for a non-replacing fork, or attach contradicting evidence before superseding.\",\n details: {\n parentNodeId: args.parentNodeId,\n triggeringEvidenceId: args.triggeringEvidenceId,\n relation,\n },\n });\n }\n\n return { evidenceNodeId: args.triggeringEvidenceId, relation };\n}\n"]}
@@ -1,8 +1,11 @@
1
- import { r as resolveTopicProjectScope, T as TopicProjectScope } from './topicScope-7zhyeGl7.js';
1
+ import { r as resolveTopicProjectScope, T as TopicProjectScope } from './topicScope-DJVa0mLa.js';
2
2
  import * as convex_values from 'convex/values';
3
3
  import { VerificationConfidenceTrigger, SLOperator, SLOpinion, Opinion, ConfidencePolicyConfig } from '@lucern/confidence';
4
4
  import { B as BeliefLifecycleStatus } from './beliefLifecycle-CXwdDw5e.js';
5
- import { Id, Doc, QueryCtx } from './convex.js';
5
+ import { Id, QueryCtx } from './convex.js';
6
+ export { StructuredMutationErrorData, throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
7
+ import '@lucern/access-control/convex';
8
+ import '@lucern/contracts/convex/unsafeAnyApi';
6
9
 
7
10
  declare const insightIdUnion: convex_values.VId<convex_values.GenericId<"epistemicNodes">, "required">;
8
11
  declare const MAX_PROJECT_BELIEF_LIMIT = 1000;
@@ -10,59 +13,52 @@ declare const optionalBeliefScopeArgs: {
10
13
  readonly projectId: convex_values.VString<string | undefined, "optional">;
11
14
  readonly topicId: convex_values.VString<string | undefined, "optional">;
12
15
  };
13
- /**
14
- * Boundary-safe payload carried inside a {@link ConvexError}. Mirrors the kernel
15
- * copy in packages/reasoning-kernel/src/adapters/beliefs.shared.ts so structured
16
- * refusals from the graph-primitives module survive the Convex client boundary
17
- * (only `ConvexError.data` is preserved across serialization).
18
- */
19
- type StructuredMutationErrorData = {
20
- structuredMutationError: true;
21
- message: string;
22
- status: number;
23
- code: string;
24
- invariantCode?: string;
25
- suggestion?: string;
26
- details?: unknown;
27
- };
28
- type BeliefScopeArgs = {
16
+
17
+ interface BeliefScopeArgs {
29
18
  projectId?: string | null;
30
19
  topicId?: string | null;
31
- };
32
- type EpistemicIndexQuery = {
33
- eq(field: string, value: unknown): EpistemicIndexQuery;
34
- gt(field: string, value: unknown): EpistemicIndexQuery;
35
- lt(field: string, value: unknown): EpistemicIndexQuery;
36
- field(field: string): string;
37
- };
38
- type EpistemicQueryChain<T> = {
39
- withIndex(_name: string, callback: (q: EpistemicIndexQuery) => EpistemicIndexQuery): EpistemicQueryChain<T>;
40
- order(direction: "asc" | "desc"): EpistemicQueryChain<T>;
41
- filter(callback: (q: EpistemicIndexQuery) => EpistemicIndexQuery): EpistemicQueryChain<T>;
42
- first(): Promise<T | null>;
43
- collect(): Promise<T[]>;
44
- take(limit: number): Promise<T[]>;
45
- };
46
- type EpistemicBeliefCtx = QueryCtx & {
47
- db: {
48
- query<T = unknown>(_table: string): EpistemicQueryChain<T>;
49
- get<T = unknown>(id: Id<string>): Promise<T | null>;
50
- };
51
- scheduler: {
52
- runAfter(_delayMs: number, _handler: unknown, _args: unknown): Promise<unknown>;
53
- };
54
- };
20
+ }
21
+ interface EpistemicNodeOpinionSource {
22
+ _id?: unknown;
23
+ metadata?: Record<string, unknown> | null;
24
+ opinion_a?: number;
25
+ opinion_b?: number;
26
+ opinion_d?: number;
27
+ opinion_u?: number;
28
+ tupleContradicted?: boolean;
29
+ userId?: string;
30
+ }
31
+ interface EpistemicNodeOpinionDoc extends EpistemicNodeOpinionSource {
32
+ _creationTime?: number;
33
+ _id: Id<"epistemicNodes">;
34
+ anonymizationClass?: string;
35
+ audienceLabel?: string;
36
+ beliefStatus?: unknown;
37
+ canonicalText?: string;
38
+ confidence?: unknown;
39
+ createdAt?: number;
40
+ createdBy?: string;
41
+ epistemicLayer?: string;
42
+ exportClass?: string;
43
+ globalId?: string;
44
+ metadata?: Record<string, unknown> | null;
45
+ nodeType: "belief";
46
+ policyTags?: string[];
47
+ predictionMeta?: unknown;
48
+ projectId?: string;
49
+ publicationStatus?: string;
50
+ sensitivityTier?: string;
51
+ status?: string;
52
+ tenantId?: string;
53
+ topicId?: string;
54
+ updatedAt?: number;
55
+ workspaceId?: string;
56
+ }
57
+ type EpistemicBeliefCtx = QueryCtx;
55
58
  type AudienceClass = "internal" | "restricted_external" | "public";
56
59
  type BeliefConfidenceTrigger = "initial" | "evidence_added" | "evidence_removed" | "contradiction_detected" | "contradiction_resolved" | "propagation" | "agent_assessment" | "worktree_outcome" | "worktree_completed" | "fusion" | "discount" | "deduction" | "backfill_synthetic" | VerificationConfidenceTrigger;
57
- declare function throwStructuredMutationError(args: {
58
- message: string;
59
- status: number;
60
- code: string;
61
- invariantCode?: string;
62
- suggestion?: string;
63
- details?: unknown;
64
- }): never;
65
60
  declare function readFiniteNumber(value: unknown): number | undefined;
61
+ declare function readBeliefNodeView(value: unknown): EpistemicNodeOpinionDoc | null;
66
62
  declare function assertBaseRateInRange(baseRate: number, field?: string): number;
67
63
  declare function buildBeliefConfidenceRow(args: {
68
64
  beliefId: Id<"epistemicNodes">;
@@ -106,8 +102,10 @@ declare function buildBeliefEvidenceNotFoundResult(): BeliefStatusResult;
106
102
  declare function deriveSyntheticBackfillOpinion(source: Record<string, unknown>): SLOpinion;
107
103
  declare function clampBeliefLimit(limit: number | undefined, fallback?: number): number;
108
104
  declare function readTupleContradictedFlag(value: unknown): boolean | undefined;
109
- declare function readBeliefOpinionSnapshot(node: Doc<"epistemicNodes">, metadata: Record<string, unknown>): SLOpinion;
110
- declare function deriveTupleContradictionSeverity(node: Doc<"epistemicNodes">): "critical" | "significant" | "minor";
105
+ declare function readBeliefOpinionSnapshot(node: EpistemicNodeOpinionSource, metadata: Record<string, unknown>): SLOpinion;
106
+ declare function deriveTupleContradictionSeverity(node: {
107
+ metadata?: Record<string, unknown> | null;
108
+ }): "critical" | "significant" | "minor";
111
109
  declare function formatTupleContradictionDescription(args: {
112
110
  opinion: Opinion;
113
111
  policy: ConfidencePolicyConfig["tupleContradiction"];
@@ -124,22 +122,22 @@ declare function resolveBeliefScopeOrNull(ctx: QueryCtx, args: BeliefScopeArgs):
124
122
  declare function getBeliefNodesForScope(ctx: EpistemicBeliefCtx, scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>, args?: {
125
123
  scanLimit?: number;
126
124
  status?: string;
127
- }): Promise<any[]>;
125
+ }): Promise<EpistemicNodeOpinionDoc[]>;
128
126
  declare function createBeliefAudienceResolver(registryRows: Array<{
129
127
  audienceKey?: string | null;
130
128
  audienceClass: AudienceClass;
131
129
  }>): (audienceKey: string | undefined | null, fallback: AudienceClass) => AudienceClass;
132
- declare function flattenBeliefNode(node: Doc<"epistemicNodes">): {
133
- _id: any;
134
- _epistemicNodeId: any;
135
- _creationTime: any;
136
- belief: any;
137
- formulation: any;
138
- projectId: any;
139
- topicId: any;
140
- userId: any;
130
+ declare function flattenBeliefNode(node: EpistemicNodeOpinionDoc): {
131
+ _id: Id<"epistemicNodes">;
132
+ _epistemicNodeId: Id<"epistemicNodes">;
133
+ _creationTime: number | undefined;
134
+ belief: string | undefined;
135
+ formulation: string | undefined;
136
+ projectId: string | undefined;
137
+ topicId: string | undefined;
138
+ userId: string;
141
139
  confidence: "high" | "medium" | "low";
142
- status: any;
140
+ status: string | undefined;
143
141
  beliefStatus: BeliefLifecycleStatus;
144
142
  topic: string;
145
143
  pillar: string;
@@ -150,19 +148,19 @@ declare function flattenBeliefNode(node: Doc<"epistemicNodes">): {
150
148
  contradictingEvidence: string[];
151
149
  testingQuestions: string[];
152
150
  linkedInsights: string[];
153
- createdAt: any;
154
- updatedAt: any;
151
+ createdAt: number | undefined;
152
+ updatedAt: number | undefined;
155
153
  tupleContradicted: boolean;
156
154
  sprintId: string | undefined;
157
155
  worktreeId: string | undefined;
158
156
  sourceBeliefIds: string[];
159
157
  criticality: "critical" | "blocking" | "supporting" | "nice_to_have" | "unanalyzed" | "important";
160
158
  rationale: string;
161
- audienceLabel: any;
162
- policyTags: any;
163
- sensitivityTier: any;
164
- exportClass: any;
165
- anonymizationClass: any;
159
+ audienceLabel: string | undefined;
160
+ policyTags: string[] | undefined;
161
+ sensitivityTier: string | undefined;
162
+ exportClass: string | undefined;
163
+ anonymizationClass: string | undefined;
166
164
  };
167
165
  declare function resolveBeliefStatus(node: {
168
166
  beliefStatus?: unknown;
@@ -176,8 +174,5 @@ declare function requireAuthenticatedUserId(ctx: {
176
174
  getUserIdentity: () => Promise<unknown>;
177
175
  };
178
176
  }): Promise<string>;
179
- declare function requireProjectWriteAccess(ctx: {
180
- db: unknown;
181
- }, projectId: string, userId: string): Promise<void>;
182
177
 
183
- export { type BeliefConfidenceTrigger, MAX_PROJECT_BELIEF_LIMIT, type StructuredMutationErrorData, assertBaseRateInRange, buildBeliefConfidenceRow, buildBeliefEvidenceNotFoundResult, buildBeliefStatusSuccessResult, clampBeliefLimit, createBeliefAudienceResolver, deriveSyntheticBackfillOpinion, deriveTupleContradictionSeverity, flattenBeliefNode, formatTupleContradictionDescription, generateContentHash, getActiveConfidencePolicy, getBeliefNodesForScope, hasCompletedWorktreeForBelief, insightIdUnion, markBeliefGraphDirty, normalizePillar, optionalBeliefScopeArgs, readBeliefOpinionSnapshot, readFiniteNumber, readTupleContradictedFlag, requireAuthenticatedUserId, requireProjectWriteAccess, resolveBeliefScopeOrNull, resolveBeliefStatus, resolveBeliefWorktreeId, throwStructuredMutationError };
178
+ export { type BeliefConfidenceTrigger, type EpistemicNodeOpinionDoc, MAX_PROJECT_BELIEF_LIMIT, assertBaseRateInRange, buildBeliefConfidenceRow, buildBeliefEvidenceNotFoundResult, buildBeliefStatusSuccessResult, clampBeliefLimit, createBeliefAudienceResolver, deriveSyntheticBackfillOpinion, deriveTupleContradictionSeverity, flattenBeliefNode, formatTupleContradictionDescription, generateContentHash, getActiveConfidencePolicy, getBeliefNodesForScope, hasCompletedWorktreeForBelief, insightIdUnion, markBeliefGraphDirty, normalizePillar, optionalBeliefScopeArgs, readBeliefNodeView, readBeliefOpinionSnapshot, readFiniteNumber, readTupleContradictedFlag, requireAuthenticatedUserId, resolveBeliefScopeOrNull, resolveBeliefStatus, resolveBeliefWorktreeId };