@lucern/graph-primitives 1.0.29 → 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 +395 -225
  19. package/dist/contradictions.js.map +1 -1
  20. package/dist/convex.d.ts +65 -30
  21. package/dist/convex.js +7 -3
  22. package/dist/convex.js.map +1 -1
  23. package/dist/debug.js.map +1 -1
  24. package/dist/edgeValidation.js +293 -85
  25. package/dist/edgeValidation.js.map +1 -1
  26. package/dist/edges/contains.d.ts +1 -1
  27. package/dist/edges/contains.js.map +1 -1
  28. package/dist/edges/contradicts.d.ts +1 -1
  29. package/dist/edges/contradicts.js.map +1 -1
  30. package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
  31. package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
  32. package/dist/edges/depends-on.js.map +1 -0
  33. package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
  34. package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
  35. package/dist/edges/derived-from.js.map +1 -0
  36. package/dist/edges/elaborates.d.ts +1 -1
  37. package/dist/edges/elaborates.js.map +1 -1
  38. package/dist/edges/index.d.ts +7 -3
  39. package/dist/edges/index.js +7 -4
  40. package/dist/edges/index.js.map +1 -1
  41. package/dist/edges/informs.d.ts +1 -1
  42. package/dist/edges/informs.js.map +1 -1
  43. package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
  44. package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
  45. package/dist/edges/propagation-types.js.map +1 -0
  46. package/dist/edges/refutes.d.ts +1 -1
  47. package/dist/edges/refutes.js.map +1 -1
  48. package/dist/edges/supports.d.ts +1 -1
  49. package/dist/edges/supports.js.map +1 -1
  50. package/dist/edges/tests.d.ts +1 -1
  51. package/dist/edges/tests.js.map +1 -1
  52. package/dist/edges/utils.d.ts +1 -1
  53. package/dist/edges/utils.js.map +1 -1
  54. package/dist/embeddingTrigger.d.ts +14 -6
  55. package/dist/embeddingTrigger.js +11 -14
  56. package/dist/embeddingTrigger.js.map +1 -1
  57. package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
  58. package/dist/entityBridge.d.ts +1 -1
  59. package/dist/entityBridge.js +602 -225
  60. package/dist/entityBridge.js.map +1 -1
  61. package/dist/entityCanonicalMatch.d.ts +14 -12
  62. package/dist/entityCanonicalMatch.js.map +1 -1
  63. package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
  64. package/dist/entityLifecycle.d.ts +1 -1
  65. package/dist/entityLifecycle.js +854 -480
  66. package/dist/entityLifecycle.js.map +1 -1
  67. package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
  68. package/dist/entityValidation.d.ts +3 -1
  69. package/dist/entityValidation.js +60 -8
  70. package/dist/entityValidation.js.map +1 -1
  71. package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
  72. package/dist/epistemicAnswers.d.ts +1 -1
  73. package/dist/epistemicAnswers.js +587 -545
  74. package/dist/epistemicAnswers.js.map +1 -1
  75. package/dist/epistemicBeliefs.admin.d.ts +8 -8
  76. package/dist/epistemicBeliefs.admin.js +365 -166
  77. package/dist/epistemicBeliefs.admin.js.map +1 -1
  78. package/dist/epistemicBeliefs.backfills.d.ts +8 -8
  79. package/dist/epistemicBeliefs.backfills.js +655 -289
  80. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  81. package/dist/epistemicBeliefs.confidence.d.ts +19 -15
  82. package/dist/epistemicBeliefs.confidence.js +633 -386
  83. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  84. package/dist/epistemicBeliefs.core.d.ts +6 -6
  85. package/dist/epistemicBeliefs.core.js +717 -371
  86. package/dist/epistemicBeliefs.core.js.map +1 -1
  87. package/dist/epistemicBeliefs.d.ts +11 -9
  88. package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
  89. package/dist/epistemicBeliefs.forkEvidence.js +8 -8
  90. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  91. package/dist/epistemicBeliefs.helpers.d.ts +68 -49
  92. package/dist/epistemicBeliefs.helpers.js +358 -211
  93. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  94. package/dist/epistemicBeliefs.internal.d.ts +5 -5
  95. package/dist/epistemicBeliefs.internal.js +1248 -1026
  96. package/dist/epistemicBeliefs.internal.js.map +1 -1
  97. package/dist/epistemicBeliefs.js +4942 -3590
  98. package/dist/epistemicBeliefs.js.map +1 -1
  99. package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
  100. package/dist/epistemicBeliefs.lifecycle.js +1138 -781
  101. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  102. package/dist/epistemicBeliefs.links.d.ts +7 -7
  103. package/dist/epistemicBeliefs.links.js +404 -267
  104. package/dist/epistemicBeliefs.links.js.map +1 -1
  105. package/dist/epistemicBeliefs.queries.d.ts +4 -4
  106. package/dist/epistemicBeliefs.queries.js +175 -20
  107. package/dist/epistemicBeliefs.queries.js.map +1 -1
  108. package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
  109. package/dist/epistemicBeliefs.topicAnchor.js +12 -5
  110. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  111. package/dist/epistemicContracts.d.ts +28 -3
  112. package/dist/epistemicContracts.evaluators.d.ts +2 -0
  113. package/dist/epistemicContracts.evaluators.js +1062 -576
  114. package/dist/epistemicContracts.evaluators.js.map +1 -1
  115. package/dist/epistemicContracts.handlers.d.ts +15 -32
  116. package/dist/epistemicContracts.handlers.js +1829 -1351
  117. package/dist/epistemicContracts.handlers.js.map +1 -1
  118. package/dist/epistemicContracts.js +1131 -636
  119. package/dist/epistemicContracts.js.map +1 -1
  120. package/dist/epistemicContracts.metrics.d.ts +2 -0
  121. package/dist/epistemicContracts.metrics.js +375 -158
  122. package/dist/epistemicContracts.metrics.js.map +1 -1
  123. package/dist/epistemicContracts.types.d.ts +87 -81
  124. package/dist/epistemicEdgeCreation.d.ts +2 -0
  125. package/dist/epistemicEdgeCreation.js +87 -16
  126. package/dist/epistemicEdgeCreation.js.map +1 -1
  127. package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
  128. package/dist/epistemicEdges.d.ts +6 -5
  129. package/dist/epistemicEdges.handlers.d.ts +3 -3
  130. package/dist/epistemicEdges.handlers.js +129 -24
  131. package/dist/epistemicEdges.handlers.js.map +1 -1
  132. package/dist/epistemicEdges.helpers.d.ts +6 -4
  133. package/dist/epistemicEdges.helpers.js +37 -2
  134. package/dist/epistemicEdges.helpers.js.map +1 -1
  135. package/dist/epistemicEdges.js +1966 -1202
  136. package/dist/epistemicEdges.js.map +1 -1
  137. package/dist/epistemicEdges.mutations.d.ts +7 -7
  138. package/dist/epistemicEdges.mutations.js +956 -579
  139. package/dist/epistemicEdges.mutations.js.map +1 -1
  140. package/dist/epistemicEdges.queries.d.ts +16 -16
  141. package/dist/epistemicEdges.queries.js +639 -367
  142. package/dist/epistemicEdges.queries.js.map +1 -1
  143. package/dist/epistemicEdges.types.d.ts +10 -8
  144. package/dist/epistemicEvidence.d.ts +4 -1
  145. package/dist/epistemicEvidence.js +933 -532
  146. package/dist/epistemicEvidence.js.map +1 -1
  147. package/dist/epistemicEvidenceHelpers.d.ts +26 -10
  148. package/dist/epistemicEvidenceHelpers.js +239 -200
  149. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  150. package/dist/epistemicEvidenceMutations.d.ts +8 -8
  151. package/dist/epistemicEvidenceMutations.js +840 -692
  152. package/dist/epistemicEvidenceMutations.js.map +1 -1
  153. package/dist/epistemicEvidenceQueries.d.ts +8 -8
  154. package/dist/epistemicEvidenceQueries.js +514 -238
  155. package/dist/epistemicEvidenceQueries.js.map +1 -1
  156. package/dist/epistemicHelpers.d.ts +4 -2
  157. package/dist/epistemicHelpers.js +308 -134
  158. package/dist/epistemicHelpers.js.map +1 -1
  159. package/dist/epistemicInsert.d.ts +16 -4
  160. package/dist/epistemicInsert.js +6 -3
  161. package/dist/epistemicInsert.js.map +1 -1
  162. package/dist/epistemicLayerRules.d.ts +10 -8
  163. package/dist/epistemicLayerRules.js +1 -5
  164. package/dist/epistemicLayerRules.js.map +1 -1
  165. package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
  166. package/dist/epistemicLinking.d.ts +1 -1
  167. package/dist/epistemicLinking.js +177 -100
  168. package/dist/epistemicLinking.js.map +1 -1
  169. package/dist/epistemicNodeCreation.d.ts +2 -0
  170. package/dist/epistemicNodeCreation.js +203 -40
  171. package/dist/epistemicNodeCreation.js.map +1 -1
  172. package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
  173. package/dist/epistemicNodes.d.ts +3 -3
  174. package/dist/epistemicNodes.helpers.d.ts +24 -15
  175. package/dist/epistemicNodes.helpers.js.map +1 -1
  176. package/dist/epistemicNodes.internal.d.ts +6 -6
  177. package/dist/epistemicNodes.internal.js +389 -319
  178. package/dist/epistemicNodes.internal.js.map +1 -1
  179. package/dist/epistemicNodes.js +700 -504
  180. package/dist/epistemicNodes.js.map +1 -1
  181. package/dist/epistemicNodes.mutations.d.ts +6 -6
  182. package/dist/epistemicNodes.mutations.js +560 -463
  183. package/dist/epistemicNodes.mutations.js.map +1 -1
  184. package/dist/epistemicNodes.queries.d.ts +8 -8
  185. package/dist/epistemicNodes.queries.js +311 -314
  186. package/dist/epistemicNodes.queries.js.map +1 -1
  187. package/dist/epistemicNodes.validators.d.ts +2 -2
  188. package/dist/epistemicNodes.validators.js.map +1 -1
  189. package/dist/epistemicQuestions.conviction.d.ts +8 -8
  190. package/dist/epistemicQuestions.conviction.js +665 -484
  191. package/dist/epistemicQuestions.conviction.js.map +1 -1
  192. package/dist/epistemicQuestions.create.d.ts +4 -4
  193. package/dist/epistemicQuestions.create.js +640 -612
  194. package/dist/epistemicQuestions.create.js.map +1 -1
  195. package/dist/epistemicQuestions.d.ts +8 -5
  196. package/dist/epistemicQuestions.evidence.d.ts +2 -2
  197. package/dist/epistemicQuestions.evidence.js +475 -383
  198. package/dist/epistemicQuestions.evidence.js.map +1 -1
  199. package/dist/epistemicQuestions.helpers.d.ts +125 -24
  200. package/dist/epistemicQuestions.helpers.js +240 -209
  201. package/dist/epistemicQuestions.helpers.js.map +1 -1
  202. package/dist/epistemicQuestions.js +3474 -2823
  203. package/dist/epistemicQuestions.js.map +1 -1
  204. package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
  205. package/dist/epistemicQuestions.lifecycle.js +607 -546
  206. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  207. package/dist/epistemicQuestions.queries.d.ts +12 -7
  208. package/dist/epistemicQuestions.queries.js +305 -244
  209. package/dist/epistemicQuestions.queries.js.map +1 -1
  210. package/dist/epistemicQuestions.sprint.d.ts +2 -2
  211. package/dist/epistemicQuestions.sprint.js +600 -394
  212. package/dist/epistemicQuestions.sprint.js.map +1 -1
  213. package/dist/epistemicQuestions.tail.d.ts +6 -6
  214. package/dist/epistemicQuestions.tail.js +572 -433
  215. package/dist/epistemicQuestions.tail.js.map +1 -1
  216. package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
  217. package/dist/epistemicSources.d.ts +1 -1
  218. package/dist/epistemicSources.js +351 -311
  219. package/dist/epistemicSources.js.map +1 -1
  220. package/dist/evaluators/index.d.ts +8 -6
  221. package/dist/evaluators/index.js +399 -167
  222. package/dist/evaluators/index.js.map +1 -1
  223. package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
  224. package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
  225. package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
  226. package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
  227. package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
  228. package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
  229. package/dist/evaluators/shared.d.ts +2 -2
  230. package/dist/evaluators/shared.js +3 -1
  231. package/dist/evaluators/shared.js.map +1 -1
  232. package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
  233. package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
  234. package/dist/evaluators/test-runner-evaluator.js.map +1 -0
  235. package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
  236. package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
  237. package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
  238. package/dist/graphTypes.js +6 -2
  239. package/dist/graphTypes.js.map +1 -1
  240. package/dist/helpers.d.ts +2 -0
  241. package/dist/helpers.js +313 -93
  242. package/dist/helpers.js.map +1 -1
  243. package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
  244. package/dist/index.d.ts +86 -83
  245. package/dist/index.js +16914 -11760
  246. package/dist/index.js.map +1 -1
  247. package/dist/invariantEnforcement.d.ts +3 -3
  248. package/dist/invariantEnforcement.js.map +1 -1
  249. package/dist/logicalRoleInference.d.ts +2 -0
  250. package/dist/logicalRoleInference.js +1 -1
  251. package/dist/logicalRoleInference.js.map +1 -1
  252. package/dist/matcherFeedbackUtils.d.ts +2 -2
  253. package/dist/matcherFeedbackUtils.js.map +1 -1
  254. package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
  255. package/dist/ontology-matching.d.ts +1 -1
  256. package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
  257. package/dist/ontologyApproval.d.ts +1 -1
  258. package/dist/ontologyApproval.js +7 -1
  259. package/dist/ontologyApproval.js.map +1 -1
  260. package/dist/ontologyDefinitions.d.ts +14 -24
  261. package/dist/ontologyDefinitions.js +269 -34
  262. package/dist/ontologyDefinitions.js.map +1 -1
  263. package/dist/ontologyHelpers.d.ts +13 -13
  264. package/dist/ontologyHelpers.js.map +1 -1
  265. package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
  266. package/dist/ontologyRegistry.d.ts +1 -1
  267. package/dist/ontologyRegistry.js +34 -6
  268. package/dist/ontologyRegistry.js.map +1 -1
  269. package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
  270. package/dist/projectionReconciliation.d.ts +1 -1
  271. package/dist/projectionReconciliation.js +57 -10
  272. package/dist/projectionReconciliation.js.map +1 -1
  273. package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
  274. package/dist/projectionStaleness.d.ts +1 -1
  275. package/dist/projectionStaleness.js +8 -2
  276. package/dist/projectionStaleness.js.map +1 -1
  277. package/dist/proof-attestation.json +1 -1
  278. package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
  279. package/dist/questionEvidenceLinks.d.ts +1 -1
  280. package/dist/questionEvidenceLinks.js +564 -347
  281. package/dist/questionEvidenceLinks.js.map +1 -1
  282. package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
  283. package/dist/resolverTypes.d.ts +4 -2
  284. package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
  285. package/dist/resolvers.d.ts +5 -3
  286. package/dist/resolvers.js +121 -77
  287. package/dist/resolvers.js.map +1 -1
  288. package/dist/scopeResolverCompat.d.ts +10 -7
  289. package/dist/scopeResolverCompat.js +106 -123
  290. package/dist/scopeResolverCompat.js.map +1 -1
  291. package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
  292. package/dist/text-matching.d.ts +1 -1
  293. package/dist/topicOntologyResolver.d.ts +22 -21
  294. package/dist/topicOntologyResolver.js +54 -32
  295. package/dist/topicOntologyResolver.js.map +1 -1
  296. package/dist/topicProjectOverlay.d.ts +30 -20
  297. package/dist/topicProjectOverlay.js +120 -76
  298. package/dist/topicProjectOverlay.js.map +1 -1
  299. package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
  300. package/dist/topicScope.d.ts +3 -1
  301. package/dist/topicScope.js +104 -119
  302. package/dist/topicScope.js.map +1 -1
  303. package/dist/workflowBridge.d.ts +26 -15
  304. package/dist/workflowBridge.js +140 -144
  305. package/dist/workflowBridge.js.map +1 -1
  306. package/dist/workspaceIsolation.d.ts +14 -12
  307. package/dist/workspaceIsolation.js +108 -122
  308. package/dist/workspaceIsolation.js.map +1 -1
  309. package/package.json +4 -4
  310. package/dist/edges/dependsOn.js.map +0 -1
  311. package/dist/edges/derivedFrom.js.map +0 -1
  312. package/dist/edges/propagationTypes.js.map +0 -1
  313. package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
  314. package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
  315. package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
  316. package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
  317. package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
  318. package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
  319. package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
@@ -1,37 +1,53 @@
1
- import { r as resolveTopicProjectScope, T as TopicProjectScope } from './topicScope-7zhyeGl7.js';
1
+ import * as _lucern_access_control_convex_js from '@lucern/access-control/convex.js';
2
+ import { r as resolveTopicProjectScope, T as TopicProjectScope } from './topicScope-DJVa0mLa.js';
2
3
  import * as convex_values from 'convex/values';
3
4
  import { Doc, QueryCtx, MutationCtx } from './convex.js';
5
+ import '@lucern/access-control/convex';
6
+ import '@lucern/contracts/convex/unsafeAnyApi';
4
7
 
5
8
  type EvidenceKind = "fact" | "observation" | "claim" | "quote" | "statistic" | "signal";
6
9
  type AudienceClass = "internal" | "restricted_external" | "public";
7
- type EvidenceScopeArgs = {
10
+ interface EvidenceScopeArgs {
8
11
  projectId?: string | null;
9
12
  topicId?: string | null;
10
- };
13
+ }
11
14
  type EvidenceNodeDoc = Doc<"epistemicNodes">;
12
15
  declare const optionalEvidenceScopeArgs: {
13
16
  readonly projectId: convex_values.VString<string | undefined, "optional">;
14
17
  readonly topicId: convex_values.VString<string | undefined, "optional">;
15
18
  };
16
- declare const LEGACY_SPRINT_LINK_KEY: string;
17
19
  declare function generateContentHash(text: string): string;
18
20
  declare function normalizeKind(kind?: string): EvidenceKind;
19
21
  declare function normalizeSourceType(sourceType?: string): "proprietary" | "verified" | "ai_generated";
20
22
  declare function markProjectGraphDirty(ctx: QueryCtx | MutationCtx, projectId: string | undefined | null, topicId?: string | undefined | null): Promise<void>;
21
23
  declare function clampEvidenceLimit(limit: number | undefined, fallback?: number): number;
22
24
  declare function dedupeEvidenceNodes(nodes: EvidenceNodeDoc[]): EvidenceNodeDoc[];
23
- declare function evidenceMatchesScope(node: Pick<EvidenceNodeDoc, "topicId" | "projectId">, scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>): boolean;
25
+ declare function evidenceMatchesScope(node: unknown, scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>): boolean;
24
26
  declare function resolveEvidenceLinkedWorktreeId(metadata: Record<string, unknown> | undefined): string | undefined;
25
27
  declare function resolveEvidenceScopeOrNull(ctx: QueryCtx | MutationCtx, args: EvidenceScopeArgs): Promise<TopicProjectScope | null>;
26
28
  declare function getEvidenceNodesForScope(ctx: QueryCtx, scope: Awaited<ReturnType<typeof resolveTopicProjectScope>>, args?: {
27
29
  scanLimit?: number;
28
30
  }): Promise<EvidenceNodeDoc[]>;
29
- type AudienceRow = {
30
- audienceKey?: string | null;
31
+ interface AudienceRow {
31
32
  audienceClass: AudienceClass;
32
- };
33
+ audienceKey?: string | null;
34
+ }
33
35
  declare function createEvidenceAudienceResolver(registryRows: AudienceRow[]): (audienceKey: string | undefined | null, fallback: AudienceClass) => AudienceClass;
34
- declare function flattenEvidenceNode(n: EvidenceNodeDoc): any;
36
+ declare function flattenEvidenceNode(n: EvidenceNodeDoc): {
37
+ text: {};
38
+ title: {};
39
+ kind: string;
40
+ tags: string[];
41
+ sourceQuestionId: string | undefined;
42
+ linkedBeliefId: string | undefined;
43
+ linkedWorktreeId: string | undefined;
44
+ linkedSprintId: string | undefined;
45
+ sprintIndex: number | undefined;
46
+ externalSourceUrl: string | undefined;
47
+ externalSourceType: string | undefined;
48
+ _creationTime?: number;
49
+ _id: string | _lucern_access_control_convex_js.Id<"epistemicNodes">;
50
+ };
35
51
  declare function formatEvidenceNode(n: {
36
52
  _id: string;
37
53
  projectId: string;
@@ -44,7 +60,6 @@ declare function formatEvidenceNode(n: {
44
60
  createdAt: number;
45
61
  updatedAt: number;
46
62
  }): {
47
- [LEGACY_SPRINT_LINK_KEY]: string | undefined;
48
63
  _id: string;
49
64
  _epistemicNodeId: string;
50
65
  _creationTime: number;
@@ -59,6 +74,7 @@ declare function formatEvidenceNode(n: {
59
74
  sourceArtifactId: unknown;
60
75
  sourceQuestionId: unknown;
61
76
  linkedWorktreeId: string | undefined;
77
+ linkedSprintId: string | undefined;
62
78
  sourceAnchor: unknown;
63
79
  aiProvider: unknown;
64
80
  verificationStatus: unknown;
@@ -1,8 +1,15 @@
1
1
  import { normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
2
- import { componentsGeneric, anyApi } from 'convex/server';
2
+ import { unsafeConvexAnyApi } from '@lucern/contracts/convex/unsafeAnyApi';
3
+ import { componentsGeneric } from 'convex/server';
3
4
  import { v } from 'convex/values';
4
5
 
5
6
  // src/epistemicEvidenceHelpers.ts
7
+ var unsafeApi = unsafeConvexAnyApi(
8
+ "graph-primitives top-level module bundle lacks a committed Convex _generated/api surface"
9
+ );
10
+ var api = unsafeApi;
11
+ componentsGeneric();
12
+ var internal = unsafeApi;
6
13
 
7
14
  // src/debug.ts
8
15
  function isGraphPrimitiveDebugEnabled() {
@@ -15,9 +22,6 @@ function debugGraphPrimitiveFallback(message, context) {
15
22
  }
16
23
  console.debug(message, context ?? {});
17
24
  }
18
- var api = anyApi;
19
- componentsGeneric();
20
- var internal = anyApi;
21
25
 
22
26
  // src/topicProjectOverlay.ts
23
27
  var LEGACY_SCOPE_FIELD = "graphScopeProjectId";
@@ -37,6 +41,10 @@ function readStringArray(value) {
37
41
  function readMetadata(topic) {
38
42
  return topic.metadata && typeof topic.metadata === "object" ? topic.metadata : {};
39
43
  }
44
+ function omitMetadataKey(metadata, key) {
45
+ const { [key]: _omitted, ...rest } = metadata;
46
+ return rest;
47
+ }
40
48
  function readLegacyProjectId(value) {
41
49
  if (!value) {
42
50
  return;
@@ -117,9 +125,12 @@ async function resolveTopicDoc(ctx, scopeId) {
117
125
  );
118
126
  }
119
127
  try {
120
- const topic = await ctx.runQuery(api.topics.getByLegacyScopeId, {
121
- projectId: String(scopeId)
122
- });
128
+ const topic = await ctx.runQuery(
129
+ api.topics.getByLegacyScopeId,
130
+ {
131
+ projectId: String(scopeId)
132
+ }
133
+ );
123
134
  if (topic?.name !== void 0 && topic?.type !== void 0) {
124
135
  return topic;
125
136
  }
@@ -139,8 +150,18 @@ function materializeTopicProjectOverlay(topic, idMode = "legacy") {
139
150
  const outwardId = idMode === "topic" ? topicId : storageProjectId;
140
151
  const visibility = coerceVisibility(topic.visibility) || coerceVisibility(metadata.visibility) || "private";
141
152
  const status = coerceStatus(topic.status) || coerceStatus(metadata.status) || "active";
142
- const createdAt = typeof topic.createdAt === "number" ? topic.createdAt : typeof topic._creationTime === "number" ? topic._creationTime : 0;
143
- const updatedAt = typeof topic.updatedAt === "number" ? topic.updatedAt : typeof metadata.updatedAt === "number" ? metadata.updatedAt : createdAt;
153
+ let createdAt = 0;
154
+ if (typeof topic.createdAt === "number") {
155
+ createdAt = topic.createdAt;
156
+ } else if (typeof topic._creationTime === "number") {
157
+ createdAt = topic._creationTime;
158
+ }
159
+ let updatedAt = createdAt;
160
+ if (typeof topic.updatedAt === "number") {
161
+ updatedAt = topic.updatedAt;
162
+ } else if (typeof metadata.updatedAt === "number") {
163
+ updatedAt = metadata.updatedAt;
164
+ }
144
165
  return {
145
166
  ...metadata,
146
167
  _id: outwardId,
@@ -209,90 +230,113 @@ async function patchTopicProjectOverlay(ctx, scopeId, value) {
209
230
  if (!topic) {
210
231
  return null;
211
232
  }
212
- const nextMetadata = { ...readMetadata(topic) };
213
- const patch = {};
214
- const topicUpdateArgs = {
215
- id: String(topic._id)
233
+ const plan = buildTopicProjectOverlayPatchPlan(topic, value);
234
+ await applyTopicProjectOverlayPatch(ctx, topic, plan);
235
+ return materializeTopicProjectOverlay({
236
+ ...topic,
237
+ ...plan.patch,
238
+ metadata: plan.nextMetadata
239
+ });
240
+ }
241
+ function buildTopicProjectOverlayPatchPlan(topic, value) {
242
+ const plan = {
243
+ nextMetadata: { ...readMetadata(topic) },
244
+ patch: {},
245
+ topicUpdateArgs: {
246
+ id: String(topic._id)
247
+ }
216
248
  };
217
249
  for (const [key, rawValue] of Object.entries(value)) {
218
- switch (key) {
219
- case "_id":
220
- case "projectId":
221
- case "topicId":
222
- case "legacyProjectId":
223
- case "storageProjectId":
224
- break;
225
- case "name":
226
- case "description":
227
- patch[key] = rawValue;
228
- topicUpdateArgs[key] = rawValue;
229
- break;
230
- case "tenantId":
231
- case "workspaceId":
232
- case "ownerId":
233
- throw new Error(
234
- `patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
235
- );
236
- case "status": {
237
- const status = coerceStatus(rawValue);
238
- if (status) {
239
- patch.status = status;
240
- topicUpdateArgs.status = status;
241
- }
242
- break;
243
- }
244
- case "visibility": {
245
- const visibility = coerceVisibility(rawValue);
246
- if (visibility) {
247
- patch.visibility = visibility;
248
- topicUpdateArgs.visibility = visibility;
249
- }
250
- break;
251
- }
252
- case "type": {
253
- const projectType = readNonEmptyString(rawValue);
254
- if (projectType) {
255
- nextMetadata.projectType = projectType;
256
- } else {
257
- delete nextMetadata.projectType;
258
- }
259
- break;
260
- }
261
- case "updatedAt":
262
- case "createdAt":
263
- break;
264
- default:
265
- if (rawValue === void 0) {
266
- delete nextMetadata[key];
267
- } else {
268
- nextMetadata[key] = rawValue;
269
- }
270
- }
250
+ applyTopicProjectOverlayPatchEntry(plan, key, rawValue);
251
+ }
252
+ plan.patch.updatedAt = Date.now();
253
+ plan.patch.metadata = plan.nextMetadata;
254
+ plan.topicUpdateArgs.metadata = plan.nextMetadata;
255
+ return plan;
256
+ }
257
+ function applyTopicProjectOverlayPatchEntry(plan, key, rawValue) {
258
+ switch (key) {
259
+ case "_id":
260
+ case "projectId":
261
+ case "topicId":
262
+ case "legacyProjectId":
263
+ case "storageProjectId":
264
+ case "updatedAt":
265
+ case "createdAt":
266
+ return;
267
+ case "name":
268
+ case "description":
269
+ plan.patch[key] = rawValue;
270
+ plan.topicUpdateArgs[key] = rawValue;
271
+ return;
272
+ case "tenantId":
273
+ case "workspaceId":
274
+ case "ownerId":
275
+ throw new Error(
276
+ `patchTopicProjectOverlay cannot mutate ${key} via component-owned topics`
277
+ );
278
+ case "status":
279
+ applyTopicStatusPatch(plan, rawValue);
280
+ return;
281
+ case "visibility":
282
+ applyTopicVisibilityPatch(plan, rawValue);
283
+ return;
284
+ case "type":
285
+ applyTopicProjectTypePatch(plan, rawValue);
286
+ return;
287
+ default:
288
+ applyTopicMetadataPatch(plan, key, rawValue);
289
+ }
290
+ }
291
+ function applyTopicStatusPatch(plan, rawValue) {
292
+ const status = coerceStatus(rawValue);
293
+ if (status) {
294
+ plan.patch.status = status;
295
+ plan.topicUpdateArgs.status = status;
296
+ }
297
+ }
298
+ function applyTopicVisibilityPatch(plan, rawValue) {
299
+ const visibility = coerceVisibility(rawValue);
300
+ if (visibility) {
301
+ plan.patch.visibility = visibility;
302
+ plan.topicUpdateArgs.visibility = visibility;
303
+ }
304
+ }
305
+ function applyTopicProjectTypePatch(plan, rawValue) {
306
+ const projectType = readNonEmptyString(rawValue);
307
+ if (projectType) {
308
+ plan.nextMetadata.projectType = projectType;
309
+ return;
310
+ }
311
+ plan.nextMetadata = omitMetadataKey(plan.nextMetadata, "projectType");
312
+ }
313
+ function applyTopicMetadataPatch(plan, key, rawValue) {
314
+ if (rawValue === void 0) {
315
+ plan.nextMetadata = omitMetadataKey(plan.nextMetadata, key);
316
+ return;
271
317
  }
272
- patch.updatedAt = Date.now();
273
- patch.metadata = nextMetadata;
274
- topicUpdateArgs.metadata = nextMetadata;
318
+ plan.nextMetadata[key] = rawValue;
319
+ }
320
+ async function applyTopicProjectOverlayPatch(ctx, topic, plan) {
275
321
  if (typeof ctx.runMutation === "function") {
276
322
  try {
277
- await ctx.runMutation(api.topics.update, topicUpdateArgs);
323
+ await ctx.runMutation(api.topics.update, plan.topicUpdateArgs);
278
324
  } catch (error) {
279
- if (!isMissingLucernChildComponentError(error) || !ctx?.db || typeof ctx.db.patch !== "function") {
325
+ if (!canPatchTopicViaLocalDb(ctx, error)) {
280
326
  throw error;
281
327
  }
282
- await ctx.db.patch(String(topic._id), patch);
328
+ await ctx.db.patch(topic._id, plan.patch);
283
329
  }
284
330
  } else if (ctx?.db && typeof ctx.db.patch === "function") {
285
- await ctx.db.patch(String(topic._id), patch);
331
+ await ctx.db.patch(topic._id, plan.patch);
286
332
  } else {
287
333
  throw new Error(
288
334
  "Cannot patch topic without component adapter (ctx.runMutation unavailable)"
289
335
  );
290
336
  }
291
- return materializeTopicProjectOverlay({
292
- ...topic,
293
- ...patch,
294
- metadata: nextMetadata
295
- });
337
+ }
338
+ function canPatchTopicViaLocalDb(ctx, error) {
339
+ return isMissingLucernChildComponentError(error) && Boolean(ctx?.db) && typeof ctx.db?.patch === "function";
296
340
  }
297
341
 
298
342
  // src/resolvers.ts
@@ -320,7 +364,7 @@ async function patchProjectWithTolerance(ctx, projectId, value) {
320
364
  try {
321
365
  await patchTopicProjectOverlay(ctx, projectId, value);
322
366
  } catch (error) {
323
- if (!isAdvisoryTopicPatch(value) || !isMissingLucernChildComponentError2(error)) {
367
+ if (!(isAdvisoryTopicPatch(value) && isMissingLucernChildComponentError2(error))) {
324
368
  throw error;
325
369
  }
326
370
  console.warn(
@@ -387,13 +431,15 @@ function asMappedProjectId(topic) {
387
431
  if (!topic) {
388
432
  return;
389
433
  }
390
- const directLegacyProjectId = normalizeScopeValue(topic[LEGACY_SCOPE_FIELD2]);
434
+ const directLegacyProjectId = normalizeScopeValue(
435
+ topic[LEGACY_SCOPE_FIELD2]
436
+ );
391
437
  if (directLegacyProjectId) {
392
438
  return directLegacyProjectId;
393
439
  }
394
440
  const metadata = topic.metadata || {};
395
441
  const candidate = metadata[LEGACY_SCOPE_FIELD2] || metadata.legacyProjectId || metadata.projectId || metadata.scopeProjectId;
396
- return candidate ? candidate : void 0;
442
+ return typeof candidate === "string" ? normalizeScopeValue(candidate) : void 0;
397
443
  }
398
444
  function normalizeScopeValue(value) {
399
445
  if (typeof value !== "string") {
@@ -418,8 +464,9 @@ function pickPrimaryTopic(candidates) {
418
464
  })[0];
419
465
  }
420
466
  async function findTopicsByScopeAlias(ctx, scopeId) {
467
+ const query = ctx.db.query("topics");
421
468
  try {
422
- return await ctx.db.query("topics").withIndex(
469
+ return await query.withIndex(
423
470
  "by_graph_scope_project",
424
471
  (q) => q.eq(LEGACY_SCOPE_FIELD2, scopeId)
425
472
  ).collect();
@@ -431,7 +478,7 @@ async function findTopicsByScopeAlias(ctx, scopeId) {
431
478
  scopeId
432
479
  }
433
480
  );
434
- const topics = await ctx.db.query("topics").collect();
481
+ const topics = await query.collect();
435
482
  return topics.filter((topic) => {
436
483
  const normalizedGlobalId = normalizeScopeValue(topic.globalId);
437
484
  const mappedProjectId = asMappedProjectId(topic);
@@ -487,137 +534,115 @@ async function resolveInheritedWorkspaceScope(ctx, topic) {
487
534
  let current = topic;
488
535
  for (let i = 0; i < MAX_DEPTH && current?.parentTopicId; i++) {
489
536
  current = await ctx.db.get(current.parentTopicId);
490
- if (!current) break;
537
+ if (!current) {
538
+ break;
539
+ }
491
540
  if (!tenantId) {
492
541
  tenantId = normalizeScopeValue(current.tenantId);
493
542
  }
494
543
  if (!workspaceId) {
495
544
  workspaceId = normalizeScopeValue(current.workspaceId);
496
545
  }
497
- if (tenantId && workspaceId) break;
546
+ if (tenantId && workspaceId) {
547
+ break;
548
+ }
498
549
  }
499
550
  return { tenantId, workspaceId };
500
551
  }
501
552
  async function resolveTopicProjectScope(ctx, args) {
502
553
  if (args.topicId) {
503
- let topic = null;
504
- try {
505
- topic = await ctx.db.get(
506
- args.topicId
507
- );
508
- } catch (error) {
509
- debugGraphPrimitiveFallback(
510
- "[topicScope] Failed to load topic by direct id",
511
- {
512
- error,
513
- topicId: args.topicId
514
- }
515
- );
516
- }
517
- if (!topic) {
518
- topic = await tryResolveHostTopicById(ctx, String(args.topicId));
519
- }
520
- if (!topic) {
521
- topic = pickPrimaryTopic(
522
- await findTopicsByScopeAlias(ctx, String(args.topicId))
523
- ) ?? null;
524
- }
525
- if (!topic) {
526
- const nodeScope = await resolveTopicNodeScopeOrNull(
527
- ctx,
528
- String(args.topicId)
529
- );
530
- if (nodeScope) {
531
- return nodeScope;
532
- }
533
- throw new Error(`Topic not found: ${String(args.topicId)}`);
534
- }
535
- const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
536
- const mapped = asMappedProjectId(topic);
537
- if (mapped) {
538
- return {
539
- topicId: topic._id,
540
- projectId: mapped,
541
- tenantId: inherited.tenantId,
542
- workspaceId: inherited.workspaceId,
543
- source: "topic"
544
- };
545
- }
546
- return {
547
- topicId: topic._id,
548
- tenantId: inherited.tenantId,
549
- workspaceId: inherited.workspaceId,
550
- source: "topic"
551
- };
554
+ return await resolveScopeFromTopicId(ctx, args.topicId);
552
555
  }
553
556
  if (args.projectId) {
554
- let directTopic = null;
555
- try {
556
- directTopic = await ctx.db.get(
557
- args.projectId
558
- );
559
- } catch (error) {
560
- debugGraphPrimitiveFallback(
561
- "[topicScope] Failed to load direct project topic",
562
- {
563
- error,
564
- projectId: args.projectId
565
- }
566
- );
567
- }
568
- if (directTopic) {
569
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
570
- const mapped = asMappedProjectId(directTopic);
571
- return {
572
- topicId: directTopic._id,
573
- projectId: mapped ?? args.projectId,
574
- tenantId: inherited.tenantId,
575
- workspaceId: inherited.workspaceId,
576
- source: "topic_inferred"
577
- };
578
- }
579
- directTopic = await tryResolveHostTopicByLegacyScope(ctx, args.projectId);
580
- if (directTopic) {
581
- const inherited = await resolveInheritedWorkspaceScope(ctx, directTopic);
582
- const mapped = asMappedProjectId(directTopic);
583
- return {
584
- topicId: directTopic._id,
585
- projectId: mapped ?? args.projectId,
586
- tenantId: inherited.tenantId,
587
- workspaceId: inherited.workspaceId,
588
- source: "topic_inferred"
589
- };
590
- }
591
- const topics = await findTopicsByScopeAlias(ctx, args.projectId);
592
- const primary = pickPrimaryTopic(topics);
593
- if (primary) {
594
- const inherited = await resolveInheritedWorkspaceScope(ctx, primary);
595
- return {
596
- topicId: primary._id,
597
- projectId: args.projectId,
598
- tenantId: inherited.tenantId,
599
- workspaceId: inherited.workspaceId,
600
- source: "project_mapped_topic"
601
- };
602
- }
603
- const nodeScope = await resolveTopicNodeScopeOrNull(
604
- ctx,
605
- String(args.projectId)
606
- );
607
- if (nodeScope) {
608
- return {
609
- ...nodeScope,
610
- projectId: nodeScope.projectId ?? String(args.projectId)
611
- };
612
- }
613
- throw new Error(
614
- `Legacy project scope ${String(args.projectId)} has no mapped topic.`
615
- );
557
+ return await resolveScopeFromLegacyProjectId(ctx, args.projectId);
616
558
  }
617
559
  throw new Error(
618
560
  "Missing scope: provide topicId (preferred) or legacy projectId alias."
619
561
  );
620
562
  }
563
+ async function resolveScopeFromTopicId(ctx, topicId) {
564
+ const topic = await resolveTopicDocFromTopicId(ctx, topicId);
565
+ if (topic) {
566
+ return await buildTopicScope(ctx, topic, "topic");
567
+ }
568
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, String(topicId));
569
+ if (nodeScope) {
570
+ return nodeScope;
571
+ }
572
+ throw new Error(`Topic not found: ${String(topicId)}`);
573
+ }
574
+ async function resolveTopicDocFromTopicId(ctx, topicId) {
575
+ const direct = await tryReadTopicDoc(ctx, topicId, {
576
+ failureLog: "[topicScope] Failed to load topic by direct id",
577
+ idLogKey: "topicId"
578
+ });
579
+ if (direct) {
580
+ return direct;
581
+ }
582
+ const hostTopic = await tryResolveHostTopicById(ctx, String(topicId));
583
+ if (hostTopic) {
584
+ return hostTopic;
585
+ }
586
+ return pickPrimaryTopic(await findTopicsByScopeAlias(ctx, String(topicId))) ?? null;
587
+ }
588
+ async function resolveScopeFromLegacyProjectId(ctx, legacyProjectId) {
589
+ const directTopic = await resolveDirectLegacyProjectTopic(
590
+ ctx,
591
+ legacyProjectId
592
+ );
593
+ if (directTopic) {
594
+ return await buildTopicScope(ctx, directTopic, "topic_inferred", {
595
+ fallbackProjectId: legacyProjectId
596
+ });
597
+ }
598
+ const primary = pickPrimaryTopic(
599
+ await findTopicsByScopeAlias(ctx, legacyProjectId)
600
+ );
601
+ if (primary) {
602
+ return await buildTopicScope(ctx, primary, "project_mapped_topic", {
603
+ fallbackProjectId: legacyProjectId
604
+ });
605
+ }
606
+ const nodeScope = await resolveTopicNodeScopeOrNull(ctx, legacyProjectId);
607
+ if (nodeScope) {
608
+ return {
609
+ ...nodeScope,
610
+ projectId: nodeScope.projectId ?? legacyProjectId
611
+ };
612
+ }
613
+ throw new Error(
614
+ `Legacy project scope ${legacyProjectId} has no mapped topic.`
615
+ );
616
+ }
617
+ async function resolveDirectLegacyProjectTopic(ctx, legacyProjectId) {
618
+ const directTopic = await tryReadTopicDoc(ctx, legacyProjectId, {
619
+ failureLog: "[topicScope] Failed to load direct project topic",
620
+ idLogKey: "projectId"
621
+ });
622
+ return directTopic ?? tryResolveHostTopicByLegacyScope(ctx, legacyProjectId);
623
+ }
624
+ async function tryReadTopicDoc(ctx, id, log) {
625
+ try {
626
+ return await ctx.db.get(id);
627
+ } catch (error) {
628
+ debugGraphPrimitiveFallback(log.failureLog, {
629
+ error,
630
+ [log.idLogKey]: id
631
+ });
632
+ return null;
633
+ }
634
+ }
635
+ async function buildTopicScope(ctx, topic, source, options = {}) {
636
+ const inherited = await resolveInheritedWorkspaceScope(ctx, topic);
637
+ const mapped = asMappedProjectId(topic);
638
+ return {
639
+ topicId: topic._id,
640
+ ...mapped || options.fallbackProjectId ? { projectId: mapped ?? options.fallbackProjectId } : {},
641
+ tenantId: inherited.tenantId,
642
+ workspaceId: inherited.workspaceId,
643
+ source
644
+ };
645
+ }
621
646
  var optionalScopeArgs = {
622
647
  projectId: v.optional(v.string()),
623
648
  topicId: v.optional(v.string())
@@ -660,7 +685,7 @@ function normalizeSourceType(sourceType) {
660
685
  async function markProjectGraphDirty(ctx, projectId, topicId) {
661
686
  const normalizedProjectId = typeof projectId === "string" && projectId.trim().length > 0 ? projectId : void 0;
662
687
  const normalizedTopicId = typeof topicId === "string" && topicId.trim().length > 0 ? topicId : void 0;
663
- if (!normalizedProjectId && !normalizedTopicId) {
688
+ if (!(normalizedProjectId || normalizedTopicId)) {
664
689
  return;
665
690
  }
666
691
  if (normalizedProjectId) {
@@ -681,9 +706,15 @@ async function markProjectGraphDirty(ctx, projectId, topicId) {
681
706
  }
682
707
  );
683
708
  }
709
+ const activityScopeId = normalizedTopicId ?? normalizedProjectId;
710
+ if (!activityScopeId) {
711
+ throw new Error(
712
+ "Expected evidence graph dirty scope to include a topic or project id."
713
+ );
714
+ }
684
715
  await resolveGraphPrimitivesAppResolvers().patchProject(
685
716
  ctx,
686
- normalizedTopicId ?? normalizedProjectId,
717
+ activityScopeId,
687
718
  {
688
719
  lastActivityAt: Date.now()
689
720
  }
@@ -712,7 +743,15 @@ function dedupeEvidenceNodes(nodes) {
712
743
  return deduped;
713
744
  }
714
745
  function evidenceMatchesScope(node, scope) {
715
- return scope.topicId !== void 0 && node.topicId === scope.topicId || scope.projectId !== void 0 && node.projectId === scope.projectId;
746
+ const record = node && typeof node === "object" && !Array.isArray(node) ? node : null;
747
+ if (!record) {
748
+ return false;
749
+ }
750
+ const nodeTopicId = typeof record.topicId === "string" ? record.topicId : void 0;
751
+ const nodeProjectId = typeof record.projectId === "string" ? record.projectId : void 0;
752
+ const scopeTopicId = scope.topicId === void 0 ? void 0 : String(scope.topicId);
753
+ const scopeProjectId = scope.projectId === void 0 ? void 0 : String(scope.projectId);
754
+ return scopeTopicId !== void 0 && nodeTopicId === scopeTopicId || scopeProjectId !== void 0 && nodeProjectId === scopeProjectId;
716
755
  }
717
756
  function resolveEvidenceLinkedWorktreeId(metadata) {
718
757
  const worktreeId = metadata?.linkedWorktreeId;
@@ -723,7 +762,7 @@ function resolveEvidenceLinkedWorktreeId(metadata) {
723
762
  return typeof sprintId === "string" && sprintId.trim().length > 0 ? sprintId : void 0;
724
763
  }
725
764
  async function resolveEvidenceScopeOrNull(ctx, args) {
726
- if (!args.projectId && !args.topicId) {
765
+ if (!(args.projectId || args.topicId)) {
727
766
  return null;
728
767
  }
729
768
  try {