@indexnetwork/protocol 22.0.0-rc.499.1 → 64.0.0-rc.604.2

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 (561) hide show
  1. package/CHANGELOG.md +1841 -0
  2. package/IMPLEMENTATION.md +140 -181
  3. package/README.md +16 -20
  4. package/STABILITY.md +16 -11
  5. package/dist/{intents/intent.module.d.ts → capabilities/intents.d.ts} +182 -192
  6. package/dist/capabilities/intents.js +88 -0
  7. package/dist/capabilities/negotiations.d.ts +17 -0
  8. package/dist/capabilities/negotiations.js +16 -0
  9. package/dist/{networks/network.module.d.ts → capabilities/networks.d.ts} +33 -169
  10. package/dist/{networks/network.module.js → capabilities/networks.js} +6 -17
  11. package/dist/index.d.ts +57 -134
  12. package/dist/index.js +41 -105
  13. package/dist/internal/agents/agent.repository.port.d.ts +59 -0
  14. package/dist/internal/agents/agent.repository.port.js +7 -0
  15. package/dist/internal/agents/agent.types.d.ts +35 -0
  16. package/dist/{agents → internal/agents}/agent.types.js +1 -6
  17. package/dist/{intents → internal/intents}/graph/intent.graph.d.ts +142 -151
  18. package/dist/{intents → internal/intents}/graph/intent.graph.execute.d.ts +5 -1
  19. package/dist/{intents → internal/intents}/graph/intent.graph.execute.js +165 -46
  20. package/dist/internal/intents/graph/intent.graph.infer.d.ts +78 -0
  21. package/dist/internal/intents/graph/intent.graph.infer.js +122 -0
  22. package/dist/internal/intents/graph/intent.graph.js +108 -0
  23. package/dist/{intents → internal/intents}/graph/intent.graph.reconcile.d.ts +18 -9
  24. package/dist/internal/intents/graph/intent.graph.reconcile.js +173 -0
  25. package/dist/internal/intents/graph/intent.graph.shared.d.ts +55 -0
  26. package/dist/{intents → internal/intents}/graph/intent.graph.shared.js +25 -70
  27. package/dist/{intents → internal/intents}/graph/intent.graph.state.d.ts +96 -32
  28. package/dist/{intents → internal/intents}/graph/intent.graph.state.js +42 -31
  29. package/dist/internal/intents/intent.admission.d.ts +16 -0
  30. package/dist/internal/intents/intent.admission.js +30 -0
  31. package/dist/{intents → internal/intents}/intent.inferrer.d.ts +1 -40
  32. package/dist/{intents → internal/intents}/intent.inferrer.js +13 -49
  33. package/dist/internal/intents/intent.preparer.d.ts +52 -0
  34. package/dist/internal/intents/intent.preparer.js +87 -0
  35. package/dist/{intents → internal/intents}/intent.verifier.d.ts +3 -36
  36. package/dist/{intents → internal/intents}/intent.verifier.js +0 -17
  37. package/dist/{networks → internal/networks}/indexer.graph.d.ts +15 -200
  38. package/dist/{networks → internal/networks}/indexer.graph.js +19 -128
  39. package/dist/{networks → internal/networks}/indexer.state.d.ts +8 -63
  40. package/dist/internal/networks/indexer.state.js +70 -0
  41. package/dist/{networks → internal/networks}/membership.graph.d.ts +6 -6
  42. package/dist/{networks → internal/networks}/membership.graph.js +3 -3
  43. package/dist/{networks → internal/networks}/membership.state.d.ts +2 -2
  44. package/dist/{networks → internal/networks}/membership.state.js +2 -2
  45. package/dist/{networks → internal/networks}/network.graph.d.ts +9 -22
  46. package/dist/{networks → internal/networks}/network.graph.js +13 -27
  47. package/dist/{networks → internal/networks}/network.recommender.d.ts +2 -2
  48. package/dist/{networks → internal/networks}/network.recommender.js +2 -2
  49. package/dist/{networks → internal/networks}/network.state.d.ts +4 -7
  50. package/dist/{networks → internal/networks}/network.state.js +4 -4
  51. package/dist/internal/opportunities/negotiation-context.loader.d.ts +26 -0
  52. package/dist/internal/opportunities/negotiation-context.loader.js +36 -0
  53. package/dist/{opportunities → internal/opportunities}/opportunity.actor.d.ts +1 -1
  54. package/dist/{opportunities → internal/opportunities}/opportunity.actor.js +7 -1
  55. package/dist/internal/opportunities/opportunity.counterparties.d.ts +17 -0
  56. package/dist/internal/opportunities/opportunity.counterparties.js +19 -0
  57. package/dist/internal/opportunities/opportunity.events.d.ts +38 -0
  58. package/dist/internal/opportunities/opportunity.events.js +94 -0
  59. package/dist/{opportunities → internal/opportunities}/opportunity.feed-selection.d.ts +3 -9
  60. package/dist/internal/opportunities/opportunity.feed-selection.js +40 -0
  61. package/dist/internal/opportunities/opportunity.graph.modes.d.ts +39 -0
  62. package/dist/internal/opportunities/opportunity.graph.modes.js +138 -0
  63. package/dist/{opportunities → internal/opportunities}/opportunity.labels.d.ts +2 -3
  64. package/dist/internal/opportunities/opportunity.labels.js +9 -0
  65. package/dist/{opportunities → internal/opportunities}/opportunity.presentation.d.ts +17 -86
  66. package/dist/{opportunities → internal/opportunities}/opportunity.presentation.js +54 -447
  67. package/dist/{opportunities → internal/opportunities}/opportunity.update-admission.d.ts +2 -2
  68. package/dist/internal/opportunities/opportunity.utils.d.ts +105 -0
  69. package/dist/internal/opportunities/opportunity.utils.js +165 -0
  70. package/dist/{opportunities → internal/opportunities}/radar/radar.graph.d.ts +17 -17
  71. package/dist/{opportunities → internal/opportunities}/radar/radar.graph.js +41 -161
  72. package/dist/{opportunities → internal/opportunities}/radar/radar.state.d.ts +4 -11
  73. package/dist/{shared → internal/shared}/agent/model-signal.d.ts +1 -1
  74. package/dist/{shared → internal/shared}/agent/model-signal.js +1 -1
  75. package/dist/{shared → internal/shared}/agent/model.config.d.ts +28 -86
  76. package/dist/{shared → internal/shared}/agent/model.config.js +58 -69
  77. package/dist/internal/shared/agent/model.resolver.d.ts +33 -0
  78. package/dist/{shared → internal/shared}/agent/model.resolver.js +18 -33
  79. package/dist/internal/shared/agent/scope.d.ts +20 -0
  80. package/dist/internal/shared/agent/scope.js +24 -0
  81. package/dist/internal/shared/assignment/network-assignment.policy.d.ts +23 -0
  82. package/dist/internal/shared/assignment/network-assignment.policy.js +28 -0
  83. package/dist/{shared → internal/shared}/observability/log.d.ts +3 -6
  84. package/dist/{shared → internal/shared}/observability/log.js +9 -18
  85. package/dist/{shared → internal/shared}/observability/protocol.logger.d.ts +1 -1
  86. package/dist/{shared → internal/shared}/observability/protocol.logger.js +1 -1
  87. package/dist/internal/shared/observability/request-context.d.ts +29 -0
  88. package/dist/internal/shared/observability/request-context.js +17 -0
  89. package/dist/{shared → internal/shared}/utils/social-label.d.ts +2 -2
  90. package/dist/{shared → internal/shared}/utils/social-label.js +1 -1
  91. package/dist/platform/database/capabilities.d.ts +59 -0
  92. package/dist/{shared/interfaces/database.entities.d.ts → platform/database/entities.d.ts} +81 -121
  93. package/dist/{shared/interfaces/database.identity-queries.d.ts → platform/database/identity-queries.d.ts} +55 -20
  94. package/dist/platform/database/member-queries.d.ts +55 -0
  95. package/dist/platform/database/member-queries.js +4 -0
  96. package/dist/platform/database/negotiation.d.ts +38 -0
  97. package/dist/{shared/interfaces/database.network-queries.d.ts → platform/database/network-queries.d.ts} +66 -67
  98. package/dist/platform/database/network-queries.js +4 -0
  99. package/dist/{shared/interfaces/database.opportunity-queries.d.ts → platform/database/opportunity-queries.d.ts} +25 -109
  100. package/dist/{shared/interfaces/database.port.d.ts → platform/database/port.d.ts} +52 -117
  101. package/dist/{shared/interfaces/database.port.js → platform/database/port.js} +3 -5
  102. package/dist/platform/database.d.ts +23 -0
  103. package/dist/{shared/interfaces/database.interface.js → platform/database.js} +1 -1
  104. package/dist/{shared/interfaces/cache.interface.d.ts → platform/discovery/cache.d.ts} +2 -4
  105. package/dist/{shared/interfaces/cache.interface.js → platform/discovery/cache.js} +1 -1
  106. package/dist/platform/discovery/embedder.d.ts +31 -0
  107. package/dist/platform/runtime/errors.d.ts +6 -0
  108. package/dist/platform/runtime/errors.js +9 -0
  109. package/dist/platform/runtime/follow-up.d.ts +36 -0
  110. package/dist/platform/runtime/follow-up.js +4 -0
  111. package/dist/platform/runtime/observability.d.ts +34 -0
  112. package/dist/protocol/core.d.ts +11 -0
  113. package/dist/protocol/discovery.rules.d.ts +21 -0
  114. package/dist/protocol/discovery.rules.js +29 -0
  115. package/dist/protocol/negotiation.constants.d.ts +3 -0
  116. package/dist/protocol/negotiation.constants.js +3 -0
  117. package/dist/protocol/negotiation.rules.d.ts +73 -0
  118. package/dist/protocol/negotiation.rules.js +68 -0
  119. package/dist/protocol/protocol.prompt.d.ts +13 -0
  120. package/dist/protocol/protocol.prompt.js +190 -0
  121. package/dist/{shared → protocol}/schemas/discovery-question.schema.d.ts +13 -13
  122. package/dist/{shared → protocol}/schemas/discovery-question.schema.js +2 -2
  123. package/dist/{shared → protocol}/schemas/identity.schema.d.ts +4 -4
  124. package/dist/{shared → protocol}/schemas/identity.schema.js +4 -4
  125. package/dist/{shared → protocol}/schemas/network-assignment.schema.d.ts +11 -20
  126. package/dist/{shared → protocol}/schemas/network-assignment.schema.js +2 -9
  127. package/dist/protocol/schemas/underspecification.schema.d.ts +9 -0
  128. package/dist/protocol/schemas/underspecification.schema.js +12 -0
  129. package/package.json +7 -15
  130. package/dist/agents/agent.dispatcher.port.d.ts +0 -25
  131. package/dist/agents/agent.module.d.ts +0 -19
  132. package/dist/agents/agent.module.js +0 -11
  133. package/dist/agents/agent.repository.port.d.ts +0 -118
  134. package/dist/agents/agent.repository.port.js +0 -10
  135. package/dist/agents/agent.tools.d.ts +0 -16
  136. package/dist/agents/agent.tools.js +0 -351
  137. package/dist/agents/agent.tools.port.d.ts +0 -22
  138. package/dist/agents/agent.tools.port.js +0 -18
  139. package/dist/agents/agent.types.d.ts +0 -76
  140. package/dist/chat/chat-streaming.types.d.ts +0 -618
  141. package/dist/chat/chat-streaming.types.js +0 -297
  142. package/dist/chat/chat.agent.d.ts +0 -292
  143. package/dist/chat/chat.agent.js +0 -1010
  144. package/dist/chat/chat.graph.d.ts +0 -424
  145. package/dist/chat/chat.graph.js +0 -257
  146. package/dist/chat/chat.interrupt.classifier.d.ts +0 -25
  147. package/dist/chat/chat.interrupt.classifier.js +0 -64
  148. package/dist/chat/chat.persona.d.ts +0 -39
  149. package/dist/chat/chat.prompt.d.ts +0 -4
  150. package/dist/chat/chat.prompt.js +0 -12
  151. package/dist/chat/chat.prompt.modules.d.ts +0 -30
  152. package/dist/chat/chat.prompt.modules.js +0 -40
  153. package/dist/chat/chat.question-dedup.d.ts +0 -14
  154. package/dist/chat/chat.question-dedup.js +0 -17
  155. package/dist/chat/chat.state.d.ts +0 -135
  156. package/dist/chat/chat.state.js +0 -120
  157. package/dist/chat/chat.streamer.d.ts +0 -64
  158. package/dist/chat/chat.streamer.js +0 -217
  159. package/dist/chat/chat.suggester.d.ts +0 -23
  160. package/dist/chat/chat.suggester.js +0 -95
  161. package/dist/chat/chat.summarizer.d.ts +0 -20
  162. package/dist/chat/chat.summarizer.js +0 -97
  163. package/dist/chat/chat.title.generator.d.ts +0 -19
  164. package/dist/chat/chat.title.generator.js +0 -66
  165. package/dist/chat/chat.tools.d.ts +0 -5
  166. package/dist/chat/chat.tools.js +0 -62
  167. package/dist/chat/chat.utils.d.ts +0 -41
  168. package/dist/chat/chat.utils.js +0 -88
  169. package/dist/chat/negotiator.persona.d.ts +0 -74
  170. package/dist/chat/negotiator.persona.js +0 -154
  171. package/dist/chat/negotiator.prompt.d.ts +0 -45
  172. package/dist/chat/negotiator.prompt.js +0 -160
  173. package/dist/chat/negotiator.tools.d.ts +0 -42
  174. package/dist/chat/negotiator.tools.js +0 -134
  175. package/dist/chat/onboarding.persona.d.ts +0 -28
  176. package/dist/chat/onboarding.persona.js +0 -86
  177. package/dist/chat/onboarding.prompt.d.ts +0 -6
  178. package/dist/chat/onboarding.prompt.js +0 -63
  179. package/dist/chat/signal.persona.d.ts +0 -47
  180. package/dist/chat/signal.persona.js +0 -319
  181. package/dist/chat/signal.prompt.d.ts +0 -39
  182. package/dist/chat/signal.prompt.js +0 -136
  183. package/dist/contacts/contact.module.d.ts +0 -8
  184. package/dist/contacts/contact.module.js +0 -6
  185. package/dist/contacts/contact.repository.port.d.ts +0 -21
  186. package/dist/contacts/contact.repository.port.js +0 -12
  187. package/dist/contacts/contact.tools.d.ts +0 -17
  188. package/dist/contacts/contact.tools.js +0 -108
  189. package/dist/contacts/contact.tools.port.d.ts +0 -20
  190. package/dist/contacts/contact.tools.port.js +0 -16
  191. package/dist/contacts/contact.types.d.ts +0 -24
  192. package/dist/contacts/contact.types.js +0 -8
  193. package/dist/contexts/context.generator.d.ts +0 -95
  194. package/dist/contexts/context.generator.js +0 -127
  195. package/dist/contexts/context.module.d.ts +0 -13
  196. package/dist/contexts/context.module.js +0 -12
  197. package/dist/contexts/context.tools.port.d.ts +0 -9
  198. package/dist/discovery/hyde.documents.d.ts +0 -9
  199. package/dist/discovery/hyde.documents.js +0 -49
  200. package/dist/discovery/hyde.env.d.ts +0 -8
  201. package/dist/discovery/hyde.env.js +0 -9
  202. package/dist/discovery/hyde.frame.d.ts +0 -150
  203. package/dist/discovery/hyde.frame.js +0 -107
  204. package/dist/discovery/hyde.generator.d.ts +0 -38
  205. package/dist/discovery/hyde.generator.js +0 -103
  206. package/dist/discovery/hyde.graph.d.ts +0 -209
  207. package/dist/discovery/hyde.graph.js +0 -482
  208. package/dist/discovery/hyde.state.d.ts +0 -70
  209. package/dist/discovery/hyde.state.js +0 -85
  210. package/dist/discovery/hyde.strategies.d.ts +0 -17
  211. package/dist/discovery/hyde.strategies.js +0 -34
  212. package/dist/discovery/hyde.validator.d.ts +0 -78
  213. package/dist/discovery/hyde.validator.js +0 -48
  214. package/dist/discovery/index.d.ts +0 -26
  215. package/dist/discovery/index.js +0 -19
  216. package/dist/discovery/lens.inferrer.d.ts +0 -214
  217. package/dist/discovery/lens.inferrer.js +0 -152
  218. package/dist/enrichment/enrichment.generator.d.ts +0 -68
  219. package/dist/enrichment/enrichment.generator.js +0 -95
  220. package/dist/enrichment/enrichment.graph.d.ts +0 -544
  221. package/dist/enrichment/enrichment.graph.js +0 -695
  222. package/dist/enrichment/enrichment.state.d.ts +0 -141
  223. package/dist/enrichment/enrichment.state.js +0 -115
  224. package/dist/enrichment/enrichment.tools.context-read.d.ts +0 -10
  225. package/dist/enrichment/enrichment.tools.context-read.js +0 -353
  226. package/dist/enrichment/enrichment.tools.context-write.d.ts +0 -9
  227. package/dist/enrichment/enrichment.tools.context-write.js +0 -417
  228. package/dist/enrichment/enrichment.tools.d.ts +0 -13
  229. package/dist/enrichment/enrichment.tools.helpers.d.ts +0 -139
  230. package/dist/enrichment/enrichment.tools.helpers.js +0 -234
  231. package/dist/enrichment/enrichment.tools.js +0 -153
  232. package/dist/intents/graph/intent.graph.infer.d.ts +0 -44
  233. package/dist/intents/graph/intent.graph.infer.js +0 -97
  234. package/dist/intents/graph/intent.graph.js +0 -134
  235. package/dist/intents/graph/intent.graph.reconcile.js +0 -274
  236. package/dist/intents/graph/intent.graph.shared.d.ts +0 -68
  237. package/dist/intents/intake/intake.orchestrator.d.ts +0 -203
  238. package/dist/intents/intake/intake.orchestrator.js +0 -255
  239. package/dist/intents/intake/intake.pack.generator.d.ts +0 -57
  240. package/dist/intents/intake/intake.pack.generator.js +0 -90
  241. package/dist/intents/intent.clarifier.d.ts +0 -51
  242. package/dist/intents/intent.clarifier.js +0 -201
  243. package/dist/intents/intent.indexer.d.ts +0 -82
  244. package/dist/intents/intent.indexer.js +0 -170
  245. package/dist/intents/intent.module.js +0 -103
  246. package/dist/intents/intent.proposal.d.ts +0 -37
  247. package/dist/intents/intent.proposal.js +0 -14
  248. package/dist/intents/intent.reconciler.d.ts +0 -105
  249. package/dist/intents/intent.reconciler.js +0 -186
  250. package/dist/intents/intent.tools.d.ts +0 -27
  251. package/dist/intents/intent.tools.js +0 -808
  252. package/dist/maintenance/maintenance.graph.d.ts +0 -239
  253. package/dist/maintenance/maintenance.graph.js +0 -199
  254. package/dist/maintenance/maintenance.state.d.ts +0 -35
  255. package/dist/maintenance/maintenance.state.js +0 -55
  256. package/dist/mcp/elicitation.builder.d.ts +0 -53
  257. package/dist/mcp/elicitation.builder.js +0 -74
  258. package/dist/mcp/elicitation.dispatcher.d.ts +0 -36
  259. package/dist/mcp/elicitation.dispatcher.js +0 -86
  260. package/dist/mcp/mcp.authorization-policy.d.ts +0 -252
  261. package/dist/mcp/mcp.authorization-policy.js +0 -535
  262. package/dist/mcp/mcp.server.d.ts +0 -90
  263. package/dist/mcp/mcp.server.js +0 -631
  264. package/dist/negotiations/insight.generator.d.ts +0 -31
  265. package/dist/negotiations/insight.generator.js +0 -105
  266. package/dist/negotiations/negotiation.agent.d.ts +0 -130
  267. package/dist/negotiations/negotiation.agent.js +0 -396
  268. package/dist/negotiations/negotiation.answer-consumption.d.ts +0 -223
  269. package/dist/negotiations/negotiation.answer-consumption.js +0 -275
  270. package/dist/negotiations/negotiation.attribution.d.ts +0 -91
  271. package/dist/negotiations/negotiation.attribution.js +0 -109
  272. package/dist/negotiations/negotiation.candidates.d.ts +0 -83
  273. package/dist/negotiations/negotiation.candidates.js +0 -162
  274. package/dist/negotiations/negotiation.client-dm.d.ts +0 -50
  275. package/dist/negotiations/negotiation.client-dm.js +0 -66
  276. package/dist/negotiations/negotiation.consultation-policy.d.ts +0 -95
  277. package/dist/negotiations/negotiation.consultation-policy.js +0 -159
  278. package/dist/negotiations/negotiation.deadlock.contracts.d.ts +0 -10
  279. package/dist/negotiations/negotiation.deadlock.d.ts +0 -87
  280. package/dist/negotiations/negotiation.deadlock.js +0 -150
  281. package/dist/negotiations/negotiation.detail-reader.d.ts +0 -94
  282. package/dist/negotiations/negotiation.detail-reader.js +0 -91
  283. package/dist/negotiations/negotiation.expected-speaker.d.ts +0 -33
  284. package/dist/negotiations/negotiation.expected-speaker.js +0 -59
  285. package/dist/negotiations/negotiation.graph.d.ts +0 -694
  286. package/dist/negotiations/negotiation.graph.finalize.d.ts +0 -5
  287. package/dist/negotiations/negotiation.graph.finalize.js +0 -403
  288. package/dist/negotiations/negotiation.graph.init.d.ts +0 -54
  289. package/dist/negotiations/negotiation.graph.init.js +0 -256
  290. package/dist/negotiations/negotiation.graph.js +0 -94
  291. package/dist/negotiations/negotiation.graph.screen.d.ts +0 -23
  292. package/dist/negotiations/negotiation.graph.screen.js +0 -108
  293. package/dist/negotiations/negotiation.graph.shared.d.ts +0 -111
  294. package/dist/negotiations/negotiation.graph.shared.js +0 -168
  295. package/dist/negotiations/negotiation.graph.turn.d.ts +0 -134
  296. package/dist/negotiations/negotiation.graph.turn.js +0 -662
  297. package/dist/negotiations/negotiation.hermes-contract.d.ts +0 -31
  298. package/dist/negotiations/negotiation.hermes-contract.js +0 -72
  299. package/dist/negotiations/negotiation.intent-snapshot-provenance.d.ts +0 -21
  300. package/dist/negotiations/negotiation.intent-snapshot-provenance.js +0 -28
  301. package/dist/negotiations/negotiation.lifecycle-narration.d.ts +0 -18
  302. package/dist/negotiations/negotiation.lifecycle-narration.js +0 -87
  303. package/dist/negotiations/negotiation.memory.d.ts +0 -65
  304. package/dist/negotiations/negotiation.memory.js +0 -83
  305. package/dist/negotiations/negotiation.module.d.ts +0 -36
  306. package/dist/negotiations/negotiation.module.js +0 -23
  307. package/dist/negotiations/negotiation.protocol.d.ts +0 -1018
  308. package/dist/negotiations/negotiation.protocol.js +0 -224
  309. package/dist/negotiations/negotiation.question-safety.d.ts +0 -52
  310. package/dist/negotiations/negotiation.question-safety.js +0 -119
  311. package/dist/negotiations/negotiation.reflect.d.ts +0 -194
  312. package/dist/negotiations/negotiation.reflect.js +0 -145
  313. package/dist/negotiations/negotiation.scope.d.ts +0 -41
  314. package/dist/negotiations/negotiation.scope.js +0 -39
  315. package/dist/negotiations/negotiation.screen.contracts.d.ts +0 -88
  316. package/dist/negotiations/negotiation.screen.contracts.js +0 -58
  317. package/dist/negotiations/negotiation.screen.d.ts +0 -78
  318. package/dist/negotiations/negotiation.screen.js +0 -112
  319. package/dist/negotiations/negotiation.stall-gap.d.ts +0 -83
  320. package/dist/negotiations/negotiation.stall-gap.js +0 -152
  321. package/dist/negotiations/negotiation.stance.contracts.d.ts +0 -123
  322. package/dist/negotiations/negotiation.stance.contracts.js +0 -317
  323. package/dist/negotiations/negotiation.state.d.ts +0 -597
  324. package/dist/negotiations/negotiation.state.js +0 -286
  325. package/dist/negotiations/negotiation.summarizer.d.ts +0 -25
  326. package/dist/negotiations/negotiation.summarizer.js +0 -101
  327. package/dist/negotiations/negotiation.task-lock-policy.d.ts +0 -10
  328. package/dist/negotiations/negotiation.task-lock-policy.js +0 -22
  329. package/dist/negotiations/negotiation.tools.d.ts +0 -18
  330. package/dist/negotiations/negotiation.tools.js +0 -842
  331. package/dist/negotiations/negotiation.tools.port.d.ts +0 -17
  332. package/dist/negotiations/negotiation.turn-cap.d.ts +0 -9
  333. package/dist/negotiations/negotiation.turn-cap.js +0 -12
  334. package/dist/networks/indexer.state.js +0 -112
  335. package/dist/networks/network.tools.d.ts +0 -36
  336. package/dist/networks/network.tools.js +0 -594
  337. package/dist/opportunities/delivery-card.cache.d.ts +0 -25
  338. package/dist/opportunities/delivery-card.cache.js +0 -43
  339. package/dist/opportunities/discovery.env.d.ts +0 -20
  340. package/dist/opportunities/discovery.env.js +0 -109
  341. package/dist/opportunities/discriminator/discriminator.adjustments.d.ts +0 -90
  342. package/dist/opportunities/discriminator/discriminator.adjustments.js +0 -141
  343. package/dist/opportunities/discriminator/discriminator.assigner.d.ts +0 -78
  344. package/dist/opportunities/discriminator/discriminator.assigner.js +0 -153
  345. package/dist/opportunities/discriminator/discriminator.env.d.ts +0 -103
  346. package/dist/opportunities/discriminator/discriminator.env.js +0 -103
  347. package/dist/opportunities/discriminator/discriminator.miner.d.ts +0 -114
  348. package/dist/opportunities/discriminator/discriminator.miner.js +0 -228
  349. package/dist/opportunities/discriminator/discriminator.push.d.ts +0 -13
  350. package/dist/opportunities/discriminator/discriminator.push.js +0 -19
  351. package/dist/opportunities/discriminator/discriminator.question.d.ts +0 -58
  352. package/dist/opportunities/discriminator/discriminator.question.js +0 -155
  353. package/dist/opportunities/discriminator/discriminator.scorer.d.ts +0 -32
  354. package/dist/opportunities/discriminator/discriminator.scorer.js +0 -105
  355. package/dist/opportunities/discriminator/discriminator.shadow.d.ts +0 -32
  356. package/dist/opportunities/discriminator/discriminator.shadow.js +0 -90
  357. package/dist/opportunities/discriminator/discriminator.types.d.ts +0 -93
  358. package/dist/opportunities/discriminator/discriminator.types.js +0 -18
  359. package/dist/opportunities/negotiation-context.loader.d.ts +0 -59
  360. package/dist/opportunities/negotiation-context.loader.js +0 -90
  361. package/dist/opportunities/negotiation-evidence/negotiation-evidence.env.d.ts +0 -43
  362. package/dist/opportunities/negotiation-evidence/negotiation-evidence.env.js +0 -44
  363. package/dist/opportunities/negotiation-evidence/negotiation-evidence.extractor.d.ts +0 -24
  364. package/dist/opportunities/negotiation-evidence/negotiation-evidence.extractor.js +0 -188
  365. package/dist/opportunities/negotiation-evidence/negotiation-evidence.miner.d.ts +0 -26
  366. package/dist/opportunities/negotiation-evidence/negotiation-evidence.miner.js +0 -112
  367. package/dist/opportunities/negotiation-evidence/negotiation-evidence.shadow.d.ts +0 -19
  368. package/dist/opportunities/negotiation-evidence/negotiation-evidence.shadow.js +0 -61
  369. package/dist/opportunities/negotiation-evidence/negotiation-evidence.types.d.ts +0 -191
  370. package/dist/opportunities/negotiation-evidence/negotiation-evidence.types.js +0 -18
  371. package/dist/opportunities/negotiation-evidence/negotiation-evidence.verifier.d.ts +0 -34
  372. package/dist/opportunities/negotiation-evidence/negotiation-evidence.verifier.js +0 -91
  373. package/dist/opportunities/negotiation-summary.builder.d.ts +0 -37
  374. package/dist/opportunities/negotiation-summary.builder.js +0 -66
  375. package/dist/opportunities/opportunity.discovery-negotiation-summary.d.ts +0 -14
  376. package/dist/opportunities/opportunity.discovery-negotiation-summary.js +0 -46
  377. package/dist/opportunities/opportunity.enricher.d.ts +0 -71
  378. package/dist/opportunities/opportunity.enricher.js +0 -280
  379. package/dist/opportunities/opportunity.evaluator.d.ts +0 -289
  380. package/dist/opportunities/opportunity.evaluator.js +0 -516
  381. package/dist/opportunities/opportunity.evidence.d.ts +0 -22
  382. package/dist/opportunities/opportunity.evidence.js +0 -87
  383. package/dist/opportunities/opportunity.existing-negotiation.d.ts +0 -79
  384. package/dist/opportunities/opportunity.existing-negotiation.js +0 -118
  385. package/dist/opportunities/opportunity.feed-selection.js +0 -96
  386. package/dist/opportunities/opportunity.graph.d.ts +0 -1611
  387. package/dist/opportunities/opportunity.graph.discovery-strategies.d.ts +0 -109
  388. package/dist/opportunities/opportunity.graph.discovery-strategies.js +0 -451
  389. package/dist/opportunities/opportunity.graph.discovery.d.ts +0 -69
  390. package/dist/opportunities/opportunity.graph.discovery.js +0 -397
  391. package/dist/opportunities/opportunity.graph.evaluation.d.ts +0 -82
  392. package/dist/opportunities/opportunity.graph.evaluation.js +0 -608
  393. package/dist/opportunities/opportunity.graph.js +0 -193
  394. package/dist/opportunities/opportunity.graph.modes.d.ts +0 -538
  395. package/dist/opportunities/opportunity.graph.modes.js +0 -538
  396. package/dist/opportunities/opportunity.graph.negotiate.d.ts +0 -109
  397. package/dist/opportunities/opportunity.graph.negotiate.js +0 -392
  398. package/dist/opportunities/opportunity.graph.persist-node.d.ts +0 -93
  399. package/dist/opportunities/opportunity.graph.persist-node.js +0 -765
  400. package/dist/opportunities/opportunity.graph.prep.d.ts +0 -150
  401. package/dist/opportunities/opportunity.graph.prep.js +0 -381
  402. package/dist/opportunities/opportunity.graph.shared.d.ts +0 -173
  403. package/dist/opportunities/opportunity.graph.shared.js +0 -199
  404. package/dist/opportunities/opportunity.introducer-feature.d.ts +0 -2
  405. package/dist/opportunities/opportunity.introducer-feature.js +0 -4
  406. package/dist/opportunities/opportunity.introducer.d.ts +0 -77
  407. package/dist/opportunities/opportunity.introducer.js +0 -99
  408. package/dist/opportunities/opportunity.labels.js +0 -10
  409. package/dist/opportunities/opportunity.lifecycle.d.ts +0 -63
  410. package/dist/opportunities/opportunity.lifecycle.js +0 -181
  411. package/dist/opportunities/opportunity.module.d.ts +0 -54
  412. package/dist/opportunities/opportunity.module.js +0 -39
  413. package/dist/opportunities/opportunity.newborn-stamping.d.ts +0 -41
  414. package/dist/opportunities/opportunity.newborn-stamping.js +0 -81
  415. package/dist/opportunities/opportunity.owner-approval.d.ts +0 -118
  416. package/dist/opportunities/opportunity.owner-approval.js +0 -34
  417. package/dist/opportunities/opportunity.owner-provenance.d.ts +0 -6
  418. package/dist/opportunities/opportunity.owner-provenance.js +0 -28
  419. package/dist/opportunities/opportunity.persist.d.ts +0 -58
  420. package/dist/opportunities/opportunity.persist.js +0 -145
  421. package/dist/opportunities/opportunity.persistence-admission.d.ts +0 -39
  422. package/dist/opportunities/opportunity.persistence-admission.js +0 -59
  423. package/dist/opportunities/opportunity.state.d.ts +0 -451
  424. package/dist/opportunities/opportunity.state.js +0 -256
  425. package/dist/opportunities/opportunity.tools.cards.d.ts +0 -138
  426. package/dist/opportunities/opportunity.tools.cards.js +0 -212
  427. package/dist/opportunities/opportunity.tools.d.ts +0 -12
  428. package/dist/opportunities/opportunity.tools.js +0 -236
  429. package/dist/opportunities/opportunity.tools.list.d.ts +0 -10
  430. package/dist/opportunities/opportunity.tools.list.js +0 -489
  431. package/dist/opportunities/opportunity.tools.port.d.ts +0 -16
  432. package/dist/opportunities/opportunity.utils.d.ts +0 -217
  433. package/dist/opportunities/opportunity.utils.js +0 -395
  434. package/dist/opportunities/outcome/outcome.env.d.ts +0 -60
  435. package/dist/opportunities/outcome/outcome.env.js +0 -63
  436. package/dist/opportunities/outcome/outcome.hypotheses.d.ts +0 -29
  437. package/dist/opportunities/outcome/outcome.hypotheses.js +0 -117
  438. package/dist/opportunities/outcome/outcome.shadow.d.ts +0 -56
  439. package/dist/opportunities/outcome/outcome.shadow.js +0 -87
  440. package/dist/opportunities/outcome/outcome.types.d.ts +0 -110
  441. package/dist/opportunities/outcome/outcome.types.js +0 -26
  442. package/dist/opportunities/radar/radar.health.d.ts +0 -31
  443. package/dist/opportunities/radar/radar.health.js +0 -75
  444. package/dist/premises/premise.analyzer.d.ts +0 -35
  445. package/dist/premises/premise.analyzer.js +0 -115
  446. package/dist/premises/premise.decomposer.d.ts +0 -69
  447. package/dist/premises/premise.decomposer.js +0 -213
  448. package/dist/premises/premise.graph.d.ts +0 -345
  449. package/dist/premises/premise.graph.js +0 -278
  450. package/dist/premises/premise.indexer.d.ts +0 -35
  451. package/dist/premises/premise.indexer.js +0 -86
  452. package/dist/premises/premise.state.d.ts +0 -67
  453. package/dist/premises/premise.state.js +0 -94
  454. package/dist/premises/premise.tools.d.ts +0 -3
  455. package/dist/premises/premise.tools.js +0 -248
  456. package/dist/questions/question.env.d.ts +0 -27
  457. package/dist/questions/question.env.js +0 -27
  458. package/dist/questions/question.input.d.ts +0 -107
  459. package/dist/questions/question.module.d.ts +0 -30
  460. package/dist/questions/question.module.js +0 -28
  461. package/dist/questions/question.schema.d.ts +0 -1529
  462. package/dist/questions/question.schema.js +0 -420
  463. package/dist/shared/agent/activity-projection.d.ts +0 -271
  464. package/dist/shared/agent/activity-projection.js +0 -254
  465. package/dist/shared/agent/canonical-guidance.d.ts +0 -30
  466. package/dist/shared/agent/canonical-guidance.js +0 -246
  467. package/dist/shared/agent/model.resolver.d.ts +0 -48
  468. package/dist/shared/agent/tool.factory.d.ts +0 -17
  469. package/dist/shared/agent/tool.factory.js +0 -221
  470. package/dist/shared/agent/tool.helpers.d.ts +0 -482
  471. package/dist/shared/agent/tool.helpers.js +0 -232
  472. package/dist/shared/agent/tool.registry.d.ts +0 -25
  473. package/dist/shared/agent/tool.registry.js +0 -76
  474. package/dist/shared/agent/tool.runtime.d.ts +0 -28
  475. package/dist/shared/agent/tool.runtime.js +0 -194
  476. package/dist/shared/agent/tool.scope.d.ts +0 -44
  477. package/dist/shared/agent/tool.scope.js +0 -50
  478. package/dist/shared/agent/utility.tools.d.ts +0 -15
  479. package/dist/shared/agent/utility.tools.js +0 -322
  480. package/dist/shared/assignment/network-assignment.policy.d.ts +0 -61
  481. package/dist/shared/assignment/network-assignment.policy.js +0 -105
  482. package/dist/shared/interfaces/agent-dispatcher.interface.d.ts +0 -100
  483. package/dist/shared/interfaces/agent-dispatcher.interface.js +0 -12
  484. package/dist/shared/interfaces/auth.interface.d.ts +0 -37
  485. package/dist/shared/interfaces/auth.interface.js +0 -1
  486. package/dist/shared/interfaces/chat-message-writer.interface.d.ts +0 -18
  487. package/dist/shared/interfaces/chat-message-writer.interface.js +0 -1
  488. package/dist/shared/interfaces/chat-session.interface.d.ts +0 -23
  489. package/dist/shared/interfaces/chat-session.interface.js +0 -18
  490. package/dist/shared/interfaces/chat-summary.interface.d.ts +0 -16
  491. package/dist/shared/interfaces/chat-summary.interface.js +0 -1
  492. package/dist/shared/interfaces/database.capabilities.d.ts +0 -100
  493. package/dist/shared/interfaces/database.interface.d.ts +0 -16
  494. package/dist/shared/interfaces/database.member-queries.d.ts +0 -219
  495. package/dist/shared/interfaces/database.member-queries.js +0 -4
  496. package/dist/shared/interfaces/database.negotiation.d.ts +0 -329
  497. package/dist/shared/interfaces/database.negotiation.js +0 -26
  498. package/dist/shared/interfaces/database.network-queries.js +0 -4
  499. package/dist/shared/interfaces/database.opportunity-queries.js +0 -4
  500. package/dist/shared/interfaces/delivery-ledger.interface.d.ts +0 -40
  501. package/dist/shared/interfaces/delivery-ledger.interface.js +0 -5
  502. package/dist/shared/interfaces/embedder.interface.d.ts +0 -92
  503. package/dist/shared/interfaces/embedder.interface.js +0 -4
  504. package/dist/shared/interfaces/enrichment-run.interface.d.ts +0 -62
  505. package/dist/shared/interfaces/enrichment-run.interface.js +0 -1
  506. package/dist/shared/interfaces/enrichment.interface.js +0 -1
  507. package/dist/shared/interfaces/negotiation-events.interface.d.ts +0 -77
  508. package/dist/shared/interfaces/negotiation-events.interface.js +0 -6
  509. package/dist/shared/interfaces/negotiation-summary.interface.d.ts +0 -25
  510. package/dist/shared/interfaces/negotiation-summary.interface.js +0 -1
  511. package/dist/shared/interfaces/negotiator-memory.interface.d.ts +0 -58
  512. package/dist/shared/interfaces/negotiator-memory.interface.js +0 -11
  513. package/dist/shared/interfaces/queue.interface.d.ts +0 -23
  514. package/dist/shared/interfaces/queue.interface.js +0 -4
  515. package/dist/shared/interfaces/scraper.interface.js +0 -1
  516. package/dist/shared/interfaces/tool-request-context.interface.d.ts +0 -11
  517. package/dist/shared/interfaces/tool-request-context.interface.js +0 -1
  518. package/dist/shared/observability/request-context.d.ts +0 -27
  519. package/dist/shared/observability/request-context.js +0 -6
  520. package/dist/shared/schemas/mcp-auth.schema.d.ts +0 -87
  521. package/dist/shared/schemas/mcp-auth.schema.js +0 -56
  522. package/dist/shared/schemas/negotiation-digest.schema.d.ts +0 -58
  523. package/dist/shared/schemas/negotiation-digest.schema.js +0 -38
  524. package/dist/shared/schemas/negotiation-state.schema.d.ts +0 -343
  525. package/dist/shared/schemas/negotiation-state.schema.js +0 -81
  526. package/dist/shared/schemas/question-block.fixture.d.ts +0 -12
  527. package/dist/shared/schemas/question-block.fixture.js +0 -39
  528. package/dist/shared/schemas/question-block.schema.d.ts +0 -111
  529. package/dist/shared/schemas/question-block.schema.js +0 -124
  530. package/dist/shared/schemas/structured-question.schema.d.ts +0 -66
  531. package/dist/shared/schemas/structured-question.schema.js +0 -31
  532. package/dist/shared/schemas/underspecification.schema.d.ts +0 -13
  533. package/dist/shared/schemas/underspecification.schema.js +0 -16
  534. /package/dist/{opportunities → internal/opportunities}/opportunity.update-admission.js +0 -0
  535. /package/dist/{opportunities → internal/opportunities}/radar/radar.state.js +0 -0
  536. /package/dist/{shared → internal/shared}/network/metadata.renderer.d.ts +0 -0
  537. /package/dist/{shared → internal/shared}/network/metadata.renderer.js +0 -0
  538. /package/dist/{shared → internal/shared}/observability/debug-meta.sanitizer.d.ts +0 -0
  539. /package/dist/{shared → internal/shared}/observability/debug-meta.sanitizer.js +0 -0
  540. /package/dist/{shared → internal/shared}/observability/performance.d.ts +0 -0
  541. /package/dist/{shared → internal/shared}/observability/performance.js +0 -0
  542. /package/dist/{shared → internal/shared}/observability/trace.d.ts +0 -0
  543. /package/dist/{shared → internal/shared}/observability/trace.js +0 -0
  544. /package/dist/{shared → internal/shared}/utils/claim-safety.d.ts +0 -0
  545. /package/dist/{shared → internal/shared}/utils/claim-safety.js +0 -0
  546. /package/dist/{shared → internal/shared}/utils/telegram-handle.d.ts +0 -0
  547. /package/dist/{shared → internal/shared}/utils/telegram-handle.js +0 -0
  548. /package/dist/{shared/interfaces/database.capabilities.js → platform/database/capabilities.js} +0 -0
  549. /package/dist/{shared/interfaces/database.entities.js → platform/database/entities.js} +0 -0
  550. /package/dist/{shared/interfaces/database.identity-queries.js → platform/database/identity-queries.js} +0 -0
  551. /package/dist/{agents/agent.dispatcher.port.js → platform/database/negotiation.js} +0 -0
  552. /package/dist/{chat/chat.persona.js → platform/database/opportunity-queries.js} +0 -0
  553. /package/dist/{contexts/context.tools.port.js → platform/discovery/embedder.js} +0 -0
  554. /package/dist/{shared/interfaces/scraper.interface.d.ts → platform/discovery/scraper.d.ts} +0 -0
  555. /package/dist/{negotiations/negotiation.deadlock.contracts.js → platform/discovery/scraper.js} +0 -0
  556. /package/dist/{shared/interfaces/enrichment.interface.d.ts → platform/enrichment/ports.d.ts} +0 -0
  557. /package/dist/{negotiations/negotiation.tools.port.js → platform/enrichment/ports.js} +0 -0
  558. /package/dist/{opportunities/opportunity.tools.port.js → platform/runtime/observability.js} +0 -0
  559. /package/dist/{questions/question.input.js → protocol/core.js} +0 -0
  560. /package/dist/{shared → protocol}/schemas/chat-context.schema.d.ts +0 -0
  561. /package/dist/{shared → protocol}/schemas/chat-context.schema.js +0 -0
@@ -1,765 +0,0 @@
1
- /**
2
- * Discovery pipeline, stage 6: persistence.
3
- *
4
- * Three persistence paths share the node — chat introductions, introducer
5
- * discovery (`onBehalfOfUserId`), and plain discovery. Each one decides whether
6
- * an existing opportunity between the same people should be reactivated,
7
- * upgraded, or suppressed before any row is written; only what survives that
8
- * gate reaches `persistOpportunities`.
9
- */
10
- import { timed } from '../shared/observability/performance.js';
11
- import { validateOpportunityActors } from './opportunity.utils.js';
12
- import { hasUnsupportedOpportunityClaim } from '../shared/utils/claim-safety.js';
13
- import { normalizeOpportunityActorIntent } from './opportunity.actor.js';
14
- import { persistOpportunities } from "./opportunity.persist.js";
15
- import { INTRODUCER_DISCOVERY_SOURCE } from "./opportunity.introducer.js";
16
- import { stampEligibleNewbornOpportunities } from "./opportunity.newborn-stamping.js";
17
- import { admitOpportunityPersistence, createEligibleOpportunityStatusUpdater } from "./opportunity.persistence-admission.js";
18
- import { belongsToOwnedIntent, DEDUP_WINDOW_MS, isActiveNegotiationTaskFresh, persistDedupLog, persistLog, persistPathLog, triggerForOwner } from "./opportunity.graph.shared.js";
19
- /**
20
- * Only skip 'draft' (chat-only) opportunities during dedup.
21
- * 'latent' must NOT be skipped — background discovery creates latent opportunities,
22
- * and excluding them causes the same user pair to get duplicate opportunities
23
- * when multiple intents trigger separate discovery jobs (IND-166).
24
- */
25
- const DEDUP_SKIP_STATUSES = ['draft'];
26
- /**
27
- * Node 5: Persist
28
- * Creates opportunities from evaluator-proposed actors (networkId, userId, role, optional intent).
29
- */
30
- export async function persistNode(state, deps) {
31
- return timed("OpportunityGraph.persist", async () => {
32
- const startTime = Date.now();
33
- const initialStatus = state.options.initialStatus ?? 'pending';
34
- persistLog.verbose('Starting persistence (dedup-v2)', {
35
- opportunitiesToCreate: state.evaluatedOpportunities.length,
36
- initialStatus,
37
- });
38
- if (state.evaluatedOpportunities.length === 0) {
39
- persistLog.verbose('No opportunities to persist', {
40
- triggerIntentId: state.triggerIntentId,
41
- reason: state.candidates.length === 0 ? 'no_search_candidates' : 'evaluator_rejected_all',
42
- });
43
- return {
44
- opportunities: [],
45
- persistenceOutcome: {
46
- evaluatedCount: 0,
47
- createdCount: 0,
48
- reactivatedCount: 0,
49
- sameTriggerDuplicateSuppressions: 0,
50
- pairActiveNegotiationSuppressions: 0,
51
- crossTriggerAllowedCount: 0,
52
- finalAtomicConflictCount: 0,
53
- },
54
- };
55
- }
56
- try {
57
- const finalTriggerIntentId = state.triggerIntentId;
58
- const admission = await admitOpportunityPersistence(deps.database, {
59
- ownerUserId: state.userId,
60
- triggerIntentId: finalTriggerIntentId,
61
- networkId: state.networkId,
62
- indexScope: state.indexScope,
63
- evaluatedOpportunities: state.evaluatedOpportunities,
64
- });
65
- if (admission.kind === 'empty_scope') {
66
- persistLog.info('Skipped persistence because final discovery scope is empty', {
67
- userId: state.userId,
68
- triggerIntentId: finalTriggerIntentId,
69
- });
70
- return { opportunities: [] };
71
- }
72
- const { allowedNetworkIds: finalAllowedNetworkIds, networkEligibility, evaluatedOpportunities: evaluatedToPersist } = admission;
73
- if (evaluatedToPersist.length < state.evaluatedOpportunities.length) {
74
- persistLog.info('Skipped opportunities with inactive participant network pairs', {
75
- before: state.evaluatedOpportunities.length,
76
- after: evaluatedToPersist.length,
77
- removed: state.evaluatedOpportunities.length - evaluatedToPersist.length,
78
- });
79
- }
80
- if (evaluatedToPersist.length === 0)
81
- return { opportunities: [] };
82
- const updateStatusIfStillEligible = createEligibleOpportunityStatusUpdater(deps.database, finalAllowedNetworkIds, networkEligibility, {
83
- onUnavailableAdapter: () => {
84
- persistLog.error('Network-eligible status update adapter is unavailable; failing closed');
85
- },
86
- });
87
- const ledger = { reactivated: [], existingBetweenActors: [], crossTriggerAllowedCount: 0 };
88
- const ctx = {
89
- state,
90
- deps,
91
- ledger,
92
- updateStatusIfStillEligible,
93
- initialStatus,
94
- now: new Date().toISOString(),
95
- };
96
- const itemsToPersist = [];
97
- const introducerUserForOnBehalf = state.onBehalfOfUserId
98
- ? await deps.database.getUser(state.userId)
99
- : null;
100
- for (const evaluated of evaluatedToPersist) {
101
- persistPathLog.verbose('Selecting persistence path', {
102
- isIntroduction: !!state.introductionContext,
103
- stateUserId: state.userId,
104
- stateIndexId: state.networkId,
105
- evaluatedActorUserIds: evaluated.actors.map(a => a.userId),
106
- });
107
- const data = state.introductionContext
108
- ? buildIntroductionOpportunity(ctx, evaluated)
109
- : state.onBehalfOfUserId
110
- ? await buildIntroducerDiscoveryOpportunity(ctx, evaluated, introducerUserForOnBehalf?.name ?? undefined)
111
- : await buildDiscoveryOpportunity(ctx, evaluated);
112
- if (!data)
113
- continue;
114
- if (hasUnsupportedOpportunityClaim(data.interpretation.reasoning)) {
115
- persistLog.warn('Skipping opportunity with unsupported affiliation/presence claim at persistence boundary', {
116
- source: data.detection.source,
117
- triggerIntentId: data.detection.triggeredBy,
118
- });
119
- continue;
120
- }
121
- try {
122
- validateOpportunityActors(data.actors);
123
- }
124
- catch (err) {
125
- persistLog.warn('Skipping opportunity with invalid actors', {
126
- error: err instanceof Error ? err.message : String(err),
127
- opportunityReasoning: evaluated.reasoning?.slice(0, 80),
128
- });
129
- continue;
130
- }
131
- itemsToPersist.push(data);
132
- }
133
- const itemsForPersistence = await stampEligibleNewbornOpportunities(itemsToPersist, {
134
- ownerUserId: state.userId,
135
- operationMode: state.operationMode,
136
- hasIntroductionContext: Boolean(state.introductionContext),
137
- onBehalfOfUserId: state.onBehalfOfUserId,
138
- targetUserId: state.targetUserId,
139
- discoverySource: state.discoverySource,
140
- resolvedTriggerIntentId: state.resolvedTriggerIntentId,
141
- indexedIntentIds: state.indexedIntents.map((intent) => intent.intentId),
142
- }, deps.stampNewbornOpportunities, {
143
- onUnsafeResult: ({ expected, actual }) => {
144
- persistLog.warn('Newborn stamper returned unsafe length/order; persisting originals', { expected, actual });
145
- },
146
- onFailure: ({ intentId, error }) => {
147
- persistLog.warn('Newborn stamper failed; persisting originals', {
148
- intentId,
149
- error: error instanceof Error ? error.message : String(error),
150
- });
151
- },
152
- });
153
- const intentDedupScope = finalTriggerIntentId && state.discoverySource === 'intent'
154
- ? { triggerIntentId: finalTriggerIntentId, dedupWindowMs: DEDUP_WINDOW_MS }
155
- : undefined;
156
- const { created: createdList, conflicts } = await persistOpportunities({
157
- database: deps.database,
158
- embedder: deps.embedder,
159
- items: itemsForPersistence,
160
- networkEligibility,
161
- intentDedupScope,
162
- });
163
- for (const conflict of conflicts) {
164
- const item = itemsForPersistence[conflict.itemIndex];
165
- const candidateActor = item?.actors.find((actor) => actor.userId !== state.userId);
166
- if (!candidateActor)
167
- continue;
168
- ledger.existingBetweenActors.push({
169
- candidateUserId: candidateActor.userId,
170
- networkId: candidateActor.networkId,
171
- existingOpportunityId: conflict.existingOpportunityId,
172
- existingStatus: conflict.existingStatus,
173
- reason: conflict.reason,
174
- ...(conflict.existingTriggerIntentId
175
- ? { existingTriggerIntentId: conflict.existingTriggerIntentId }
176
- : {}),
177
- });
178
- persistDedupLog.info('Final atomic persistence conflict', {
179
- triggerIntentId: finalTriggerIntentId,
180
- candidateUserId: candidateActor.userId,
181
- existingOpportunityId: conflict.existingOpportunityId,
182
- existingTriggerIntentId: conflict.existingTriggerIntentId,
183
- existingStatus: conflict.existingStatus,
184
- existingAgeMs: Date.now() - new Date(conflict.existingCreatedAt).getTime(),
185
- reason: conflict.reason,
186
- finalAtomic: true,
187
- });
188
- }
189
- const allOpportunities = [...ledger.reactivated, ...createdList];
190
- persistLog.verbose('Persistence complete', {
191
- created: createdList.length,
192
- reactivated: ledger.reactivated.length,
193
- existingBetweenActorsCount: ledger.existingBetweenActors.length,
194
- status: initialStatus,
195
- });
196
- const persistenceOutcome = {
197
- evaluatedCount: state.evaluatedOpportunities.length,
198
- createdCount: createdList.length,
199
- reactivatedCount: ledger.reactivated.length,
200
- sameTriggerDuplicateSuppressions: ledger.existingBetweenActors.filter((entry) => entry.reason === 'same_trigger_recent_duplicate').length,
201
- pairActiveNegotiationSuppressions: ledger.existingBetweenActors.filter((entry) => entry.reason === 'pair_active_negotiation').length,
202
- crossTriggerAllowedCount: ledger.crossTriggerAllowedCount,
203
- finalAtomicConflictCount: conflicts.length,
204
- };
205
- return {
206
- opportunities: allOpportunities,
207
- existingBetweenActors: ledger.existingBetweenActors,
208
- persistenceOutcome,
209
- trace: [{
210
- node: "persist",
211
- detail: `Created ${createdList.length}, reactivated ${ledger.reactivated.length}, ${ledger.existingBetweenActors.length} existing skipped`,
212
- data: {
213
- created: createdList.length,
214
- reactivated: ledger.reactivated.length,
215
- existingSkipped: ledger.existingBetweenActors.length,
216
- totalOutput: allOpportunities.length,
217
- persistenceOutcome,
218
- durationMs: Date.now() - startTime,
219
- },
220
- }],
221
- };
222
- }
223
- catch (error) {
224
- const errMsg = error instanceof Error ? error.message : String(error);
225
- persistLog.error('Failed', { error });
226
- return {
227
- opportunities: [],
228
- existingBetweenActors: [],
229
- error: 'Failed to persist opportunities.',
230
- trace: [{
231
- node: "persist_fatal",
232
- detail: `Persist failed: ${errMsg}`,
233
- data: { error: errMsg },
234
- }],
235
- };
236
- }
237
- });
238
- }
239
- /** Map evaluator actors onto opportunity actors, defaulting the network. */
240
- function toOpportunityActors(evaluated, fallbackNetworkId, premiseLookup) {
241
- return evaluated.actors.map((a) => {
242
- const intent = normalizeOpportunityActorIntent(a.intentId);
243
- return {
244
- networkId: a.networkId ?? fallbackNetworkId,
245
- userId: a.userId,
246
- role: a.role,
247
- ...(intent ? { intent: intent } : {}),
248
- ...(premiseLookup?.has(a.userId) ? { premise: premiseLookup.get(a.userId).premiseId } : {}),
249
- };
250
- });
251
- }
252
- /** Append the viewer as an unapproved introducer unless the evaluator already placed them. */
253
- function withIntroducerActor(evaluatorActors, viewerUserId, networkId) {
254
- return evaluatorActors.some(a => a.userId === viewerUserId)
255
- ? evaluatorActors
256
- : [...evaluatorActors, { networkId, userId: viewerUserId, role: 'introducer', approved: false }];
257
- }
258
- /**
259
- * Introduction path: manual detection, introducer actor, curator_judgment signal.
260
- */
261
- function buildIntroductionOpportunity(ctx, evaluated) {
262
- const { state, initialStatus, now } = ctx;
263
- const indexIdForActors = state.networkId ?? evaluated.actors[0]?.networkId;
264
- if (indexIdForActors === undefined) {
265
- persistLog.warn('Introduction path missing networkId; skipping opportunity', {
266
- userId: state.userId,
267
- actorsCount: evaluated.actors.length,
268
- });
269
- return null;
270
- }
271
- const actors = withIntroducerActor(toOpportunityActors(evaluated, indexIdForActors), state.userId, indexIdForActors);
272
- return {
273
- detection: {
274
- source: 'manual',
275
- createdBy: state.userId,
276
- createdByName: state.introductionContext.createdByName,
277
- timestamp: now,
278
- },
279
- actors,
280
- interpretation: {
281
- category: 'collaboration',
282
- reasoning: evaluated.reasoning,
283
- confidence: evaluated.score / 100,
284
- signals: [
285
- {
286
- type: 'curator_judgment',
287
- weight: 1,
288
- detail: `Introduction by ${state.introductionContext.createdByName ?? 'a member'} via chat`,
289
- },
290
- ],
291
- },
292
- context: {
293
- networkId: state.networkId ?? indexIdForActors,
294
- ...(state.options.conversationId ? { conversationId: state.options.conversationId } : {}),
295
- },
296
- confidence: String(evaluated.score / 100),
297
- status: initialStatus,
298
- };
299
- }
300
- /**
301
- * Introducer discovery path: introducer is state.userId, target is onBehalfOfUserId.
302
- */
303
- async function buildIntroducerDiscoveryOpportunity(ctx, evaluated, introducerName) {
304
- const { state, deps, ledger, updateStatusIfStillEligible, initialStatus, now } = ctx;
305
- const indexIdForActors = state.networkId ?? evaluated.actors[0]?.networkId;
306
- if (indexIdForActors === undefined) {
307
- persistLog.warn('Introducer discovery path missing networkId; skipping opportunity', {
308
- userId: state.userId,
309
- actorsCount: evaluated.actors.length,
310
- });
311
- return null;
312
- }
313
- const actors = withIntroducerActor(toOpportunityActors(evaluated, indexIdForActors), state.userId, indexIdForActors);
314
- const candidateUserId = evaluated.actors.find((a) => a.userId !== state.onBehalfOfUserId)?.userId;
315
- const overlapping = candidateUserId
316
- ? await deps.database.findOpportunitiesByActors([state.onBehalfOfUserId, candidateUserId], { excludeStatuses: DEDUP_SKIP_STATUSES })
317
- : [];
318
- if (overlapping.length > 0) {
319
- const existing = overlapping[0];
320
- const isRecent = new Date(existing.createdAt).getTime() > Date.now() - DEDUP_WINDOW_MS;
321
- const sameIntroducer = existing.actors?.some((actor) => actor.role === 'introducer' && actor.userId === state.userId);
322
- const suppressionNetworkId = (state.networkId ?? indexIdForActors ?? '');
323
- if (existing.status === 'expired' || existing.status === 'stalled') {
324
- // Reactivate expired or stalled opportunities (only if same introducer for expired).
325
- // A different introducer creating for an expired pair falls through to new creation —
326
- // the prior expiry belongs to the original introducer, not this one.
327
- // Stalled opportunities are reactivated regardless of age: a stalled negotiation
328
- // is still in-flight for this pair, so we resume it rather than create a parallel one.
329
- if (existing.status === 'stalled' || sameIntroducer) {
330
- // Introduction path always targets 'draft' (chat-only surface) rather than using
331
- // initialStatus, because introductions are always chat-initiated, not background-discovered.
332
- const reactivated = await updateStatusIfStillEligible(existing.id, 'draft', existing.actors, existing.status);
333
- if (reactivated) {
334
- persistLog.verbose('Reactivated opportunity (introduction path)', {
335
- opportunityId: existing.id,
336
- candidateUserId,
337
- previousStatus: existing.status,
338
- });
339
- ledger.reactivated.push(reactivated);
340
- }
341
- return null;
342
- }
343
- }
344
- else if (existing.status === 'negotiating') {
345
- // Orphan heal (introduction path): same logic as discovery path
346
- const priorTask = await deps.database.getNegotiationTaskForOpportunity(existing.id);
347
- if (priorTask && isActiveNegotiationTaskFresh(priorTask)) {
348
- ledger.existingBetweenActors.push({
349
- candidateUserId: candidateUserId,
350
- networkId: suppressionNetworkId,
351
- existingOpportunityId: existing.id,
352
- existingStatus: existing.status,
353
- });
354
- persistLog.verbose('Skipping negotiating opportunity with active task (introduction path)', {
355
- opportunityId: existing.id,
356
- candidateUserId,
357
- taskState: priorTask.state,
358
- });
359
- return null;
360
- }
361
- const reactivated = await updateStatusIfStillEligible(existing.id, 'draft', existing.actors, existing.status);
362
- if (reactivated) {
363
- persistLog.info('Resuming orphaned negotiating opportunity (introduction path)', {
364
- opportunityId: existing.id,
365
- candidateUserId,
366
- priorTaskState: priorTask?.state,
367
- });
368
- ledger.reactivated.push(reactivated);
369
- }
370
- return null;
371
- }
372
- else if (existing.status === 'latent') {
373
- // Upgrade latent to draft for introduction path
374
- const upgraded = await updateStatusIfStillEligible(existing.id, 'draft', existing.actors, existing.status);
375
- if (upgraded) {
376
- persistLog.verbose('Upgraded latent opportunity to draft (introduction path)', {
377
- opportunityId: existing.id,
378
- candidateUserId,
379
- });
380
- ledger.reactivated.push(upgraded);
381
- }
382
- return null;
383
- }
384
- else if (isRecent && candidateUserId) {
385
- // Time-gated skip: only skip if opportunity was created within DEDUP_WINDOW_MS
386
- ledger.existingBetweenActors.push({
387
- candidateUserId: candidateUserId,
388
- networkId: suppressionNetworkId,
389
- existingOpportunityId: existing.id,
390
- existingStatus: existing.status,
391
- });
392
- persistLog.verbose('Skipping recent duplicate (introduction path)', {
393
- candidateUserId,
394
- existingStatus: existing.status,
395
- existingOpportunityId: existing.id,
396
- });
397
- return null;
398
- }
399
- // Else: existing opportunity is old enough, allow new opportunity creation
400
- persistLog.verbose('Allowing new opportunity; existing is outside dedup window (introduction path)', {
401
- candidateUserId,
402
- existingStatus: existing.status,
403
- existingOpportunityId: existing.id,
404
- });
405
- }
406
- return {
407
- detection: {
408
- source: INTRODUCER_DISCOVERY_SOURCE,
409
- createdBy: state.userId,
410
- createdByName: introducerName,
411
- timestamp: now,
412
- },
413
- actors,
414
- interpretation: {
415
- category: 'collaboration',
416
- reasoning: evaluated.reasoning,
417
- confidence: evaluated.score / 100,
418
- signals: [{
419
- type: 'curator_judgment',
420
- weight: 1,
421
- detail: `Introducer discovery for ${introducerName ?? 'a member'} via background maintenance`,
422
- }],
423
- },
424
- context: {
425
- networkId: state.networkId ?? indexIdForActors,
426
- ...(state.options.conversationId ? { conversationId: state.options.conversationId } : {}),
427
- },
428
- confidence: String(evaluated.score / 100),
429
- status: initialStatus,
430
- };
431
- }
432
- /**
433
- * Discovery path: opportunity_graph source, no introducer, lifecycle guard for agent/patient.
434
- */
435
- async function buildDiscoveryOpportunity(ctx, evaluated) {
436
- const { state, initialStatus, now } = ctx;
437
- const indexIdForActors = state.networkId ?? evaluated.actors[0]?.networkId;
438
- // Build premise lookup from discovery candidates for premise tracking.
439
- // When multiple premise candidates exist for the same user, keep the highest-similarity one.
440
- const premiseLookup = new Map();
441
- for (const c of state.candidates ?? []) {
442
- if (c.candidatePremiseId) {
443
- const existing = premiseLookup.get(c.candidateUserId);
444
- if (!existing || c.similarity > existing.similarity) {
445
- premiseLookup.set(c.candidateUserId, { premiseId: c.candidatePremiseId, similarity: c.similarity });
446
- }
447
- }
448
- }
449
- const actors = toOpportunityActors(evaluated, indexIdForActors, premiseLookup);
450
- applyDiscovererLifecycleSwap(actors, state.userId);
451
- const suppressed = await suppressDiscoveryDuplicate(ctx, evaluated);
452
- if (suppressed)
453
- return null;
454
- return {
455
- detection: {
456
- source: 'opportunity_graph',
457
- createdBy: 'agent-opportunity-finder',
458
- ...(state.discoverySource === 'intent' && state.resolvedTriggerIntentId
459
- ? { triggeredBy: state.resolvedTriggerIntentId }
460
- : {}),
461
- timestamp: now,
462
- },
463
- actors,
464
- interpretation: {
465
- category: 'collaboration',
466
- reasoning: evaluated.reasoning,
467
- confidence: evaluated.score / 100,
468
- signals: [
469
- {
470
- type: evaluated.actors.some((a) => a.intentId) ? 'intent_match' : 'profile_match',
471
- weight: evaluated.score / 100,
472
- detail: 'Entity-bundle evaluator',
473
- },
474
- ],
475
- },
476
- context: {
477
- ...(state.networkId ? { networkId: state.networkId } : {}),
478
- ...(state.options.conversationId ? { conversationId: state.options.conversationId } : {}),
479
- },
480
- confidence: String(evaluated.score / 100),
481
- status: initialStatus,
482
- metadata: {
483
- evidence: evaluated.evidence ?? [],
484
- },
485
- };
486
- }
487
- /**
488
- * The discoverer must be the patient so the opportunity shows up in their
489
- * lifecycle view; swap roles with the counterpart when the evaluator put them
490
- * in the agent seat. Introduced opportunities keep the evaluator's roles.
491
- */
492
- function applyDiscovererLifecycleSwap(actors, discovererUserId) {
493
- if (actors.some(a => a.role === 'introducer'))
494
- return;
495
- const discovererIdx = actors.findIndex(a => a.userId === discovererUserId);
496
- if (discovererIdx < 0 || actors[discovererIdx].role !== 'agent')
497
- return;
498
- const counterpartIdx = actors.findIndex((a, i) => i !== discovererIdx && a.role === 'patient');
499
- actors[discovererIdx] = { ...actors[discovererIdx], role: 'patient' };
500
- if (counterpartIdx >= 0) {
501
- actors[counterpartIdx] = { ...actors[counterpartIdx], role: 'agent' };
502
- }
503
- persistLog.verbose('Swapped discoverer from agent to patient for lifecycle visibility', {
504
- discovererId: discovererUserId,
505
- });
506
- }
507
- /**
508
- * Index-agnostic dedup: find ANY existing opportunity between these users,
509
- * regardless of which index it was created in or whether a focused network
510
- * scope is set. Returns true when the pairing must not be persisted.
511
- */
512
- async function suppressDiscoveryDuplicate(ctx, evaluated) {
513
- const { state, deps, ledger, updateStatusIfStillEligible, initialStatus } = ctx;
514
- const candidateUserId = evaluated.actors.find((a) => a.userId !== state.userId)?.userId;
515
- persistDedupLog.verbose('Checking overlapping opportunities', {
516
- stateUserId: state.userId,
517
- candidateUserId: candidateUserId ?? 'NONE',
518
- evaluatedActors: evaluated.actors.map(a => ({ userId: a.userId, role: a.role })),
519
- });
520
- const overlapping = candidateUserId
521
- ? await deps.database.findOpportunitiesByActors([state.userId, candidateUserId], { excludeStatuses: DEDUP_SKIP_STATUSES })
522
- : [];
523
- persistDedupLog.verbose('findOpportunitiesByActors result', {
524
- count: overlapping.length,
525
- results: overlapping.map(o => ({ id: o.id, status: o.status, actors: o.actors?.map((a) => ({ userId: a.userId, role: a.role })) })),
526
- });
527
- const ownedIntentTriggerId = state.discoverySource === 'intent'
528
- && state.triggerIntentId
529
- && state.resolvedTriggerIntentId === state.triggerIntentId
530
- ? state.triggerIntentId
531
- : undefined;
532
- if (ownedIntentTriggerId && candidateUserId) {
533
- return suppressOwnedIntentDuplicate(ctx, overlapping, candidateUserId, ownedIntentTriggerId);
534
- }
535
- if (overlapping.length === 0)
536
- return false;
537
- const existing = overlapping[0];
538
- const existingIndexId = (existing.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? '');
539
- const isRecent = new Date(existing.createdAt).getTime() > Date.now() - DEDUP_WINDOW_MS;
540
- if (existing.status === 'expired' || existing.status === 'stalled') {
541
- // Reactivate expired or stalled opportunities.
542
- // Stalled opportunities are reactivated regardless of age: a stalled negotiation
543
- // is still in-flight for this pair, so we resume it rather than create a parallel one.
544
- const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
545
- if (reactivated) {
546
- persistLog.verbose('Reactivated opportunity', {
547
- opportunityId: existing.id,
548
- candidateUserId,
549
- previousStatus: existing.status,
550
- newStatus: initialStatus,
551
- });
552
- ledger.reactivated.push(reactivated);
553
- }
554
- return true;
555
- }
556
- if (existing.status === 'negotiating') {
557
- // Orphan heal: if a prior opportunity is stuck in 'negotiating' with a stale task,
558
- // reactivate it so the new discovery run can reuse it instead of creating a duplicate.
559
- const priorTask = await deps.database.getNegotiationTaskForOpportunity(existing.id);
560
- if (priorTask && isActiveNegotiationTaskFresh(priorTask)) {
561
- // Still active — skip (lock gate in init node will handle)
562
- ledger.existingBetweenActors.push({
563
- candidateUserId: candidateUserId,
564
- networkId: existingIndexId,
565
- existingOpportunityId: existing.id,
566
- existingStatus: existing.status,
567
- });
568
- persistLog.verbose('Skipping negotiating opportunity with active task', {
569
- opportunityId: existing.id,
570
- candidateUserId,
571
- taskState: priorTask.state,
572
- });
573
- return true;
574
- }
575
- // Task is stale or missing — reactivate the orphaned negotiating opportunity
576
- const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
577
- if (reactivated) {
578
- persistLog.info('Resuming orphaned negotiating opportunity', {
579
- opportunityId: existing.id,
580
- candidateUserId,
581
- priorTaskState: priorTask?.state,
582
- });
583
- ledger.reactivated.push(reactivated);
584
- }
585
- return true;
586
- }
587
- if (existing.status === 'latent' && initialStatus !== 'latent') {
588
- // Upgrade latent (background-discovered) to the higher-priority status (e.g. pending)
589
- const upgraded = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
590
- if (upgraded) {
591
- persistLog.verbose('Upgraded latent opportunity to higher-priority status', {
592
- opportunityId: existing.id,
593
- candidateUserId,
594
- previousStatus: 'latent',
595
- newStatus: initialStatus,
596
- });
597
- ledger.reactivated.push(upgraded);
598
- }
599
- return true;
600
- }
601
- if (isRecent && candidateUserId) {
602
- // Time-gated skip: only skip if opportunity was created within DEDUP_WINDOW_MS
603
- // This prevents parallel job duplicates while allowing new discoveries for long-connected pairs
604
- ledger.existingBetweenActors.push({
605
- candidateUserId: candidateUserId,
606
- networkId: existingIndexId,
607
- existingOpportunityId: existing.id,
608
- existingStatus: existing.status,
609
- });
610
- persistLog.verbose('Skipping recent duplicate; opportunity created within dedup window', {
611
- candidateUserId,
612
- existingStatus: existing.status,
613
- existingOpportunityId: existing.id,
614
- createdAt: existing.createdAt,
615
- });
616
- return true;
617
- }
618
- // Else: existing opportunity is old enough (outside the 30-day dedup window), allow new opportunity creation
619
- persistLog.verbose('Allowing new opportunity; existing is outside dedup window', {
620
- candidateUserId,
621
- existingStatus: existing.status,
622
- existingOpportunityId: existing.id,
623
- createdAt: existing.createdAt,
624
- });
625
- return false;
626
- }
627
- /**
628
- * Dedup for a discovery run triggered by an intent the owner still holds.
629
- * A pair-global active negotiation always wins; otherwise only opportunities
630
- * carrying the *same* trigger intent can suppress this one.
631
- */
632
- async function suppressOwnedIntentDuplicate(ctx, overlapping, candidateUserId, ownedIntentTriggerId) {
633
- const { state, deps, ledger, updateStatusIfStillEligible, initialStatus } = ctx;
634
- let activeNegotiation;
635
- for (const opportunity of overlapping) {
636
- if (opportunity.status !== 'negotiating')
637
- continue;
638
- const task = await deps.database.getNegotiationTaskForOpportunity(opportunity.id);
639
- if (task && isActiveNegotiationTaskFresh(task)) {
640
- activeNegotiation = { opportunity, taskState: task.state };
641
- break;
642
- }
643
- }
644
- if (activeNegotiation) {
645
- const existingTriggerIntentId = triggerForOwner(activeNegotiation.opportunity, state.userId);
646
- ledger.existingBetweenActors.push({
647
- candidateUserId,
648
- networkId: (activeNegotiation.opportunity.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? ''),
649
- existingOpportunityId: activeNegotiation.opportunity.id,
650
- existingStatus: activeNegotiation.opportunity.status,
651
- reason: 'pair_active_negotiation',
652
- ...(existingTriggerIntentId ? { existingTriggerIntentId } : {}),
653
- });
654
- persistDedupLog.info('Suppressing owned-intent match for pair-global active negotiation', {
655
- triggerIntentId: ownedIntentTriggerId,
656
- candidateUserId,
657
- existingOpportunityId: activeNegotiation.opportunity.id,
658
- existingTriggerIntentId,
659
- existingStatus: activeNegotiation.opportunity.status,
660
- existingAgeMs: Date.now() - new Date(activeNegotiation.opportunity.createdAt).getTime(),
661
- taskState: activeNegotiation.taskState,
662
- reason: 'pair_active_negotiation',
663
- });
664
- return true;
665
- }
666
- const sameTrigger = overlapping
667
- .filter((opportunity) => belongsToOwnedIntent(opportunity, state.userId, ownedIntentTriggerId))
668
- .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
669
- const otherTrigger = overlapping.filter((opportunity) => !belongsToOwnedIntent(opportunity, state.userId, ownedIntentTriggerId));
670
- const existing = sameTrigger[0];
671
- if (!existing) {
672
- if (otherTrigger.length > 0) {
673
- ledger.crossTriggerAllowedCount += 1;
674
- persistDedupLog.info('Allowing cross-trigger match for owned intent', {
675
- triggerIntentId: ownedIntentTriggerId,
676
- candidateUserId,
677
- reason: 'cross_trigger_match_allowed',
678
- otherTriggers: otherTrigger.map((opportunity) => ({
679
- opportunityId: opportunity.id,
680
- triggerIntentId: triggerForOwner(opportunity, state.userId),
681
- status: opportunity.status,
682
- ageMs: Date.now() - new Date(opportunity.createdAt).getTime(),
683
- })),
684
- });
685
- }
686
- return false;
687
- }
688
- const existingIndexId = (existing.context?.networkId ?? state.networkId ?? state.userNetworks?.[0] ?? '');
689
- const isRecent = new Date(existing.createdAt).getTime() > Date.now() - DEDUP_WINDOW_MS;
690
- if (existing.status === 'expired' || existing.status === 'stalled') {
691
- const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
692
- if (reactivated) {
693
- persistLog.info('Reactivated same-trigger opportunity', {
694
- triggerIntentId: ownedIntentTriggerId,
695
- opportunityId: existing.id,
696
- candidateUserId,
697
- previousStatus: existing.status,
698
- newStatus: initialStatus,
699
- });
700
- ledger.reactivated.push(reactivated);
701
- }
702
- return true;
703
- }
704
- if (existing.status === 'negotiating') {
705
- const reactivated = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
706
- if (reactivated) {
707
- persistLog.info('Resuming same-trigger orphaned negotiating opportunity', {
708
- triggerIntentId: ownedIntentTriggerId,
709
- opportunityId: existing.id,
710
- candidateUserId,
711
- });
712
- ledger.reactivated.push(reactivated);
713
- }
714
- return true;
715
- }
716
- if (existing.status === 'latent' && initialStatus !== 'latent') {
717
- const upgraded = await updateStatusIfStillEligible(existing.id, initialStatus, existing.actors, existing.status);
718
- if (upgraded) {
719
- persistLog.info('Upgraded same-trigger latent opportunity', {
720
- triggerIntentId: ownedIntentTriggerId,
721
- opportunityId: existing.id,
722
- candidateUserId,
723
- newStatus: initialStatus,
724
- });
725
- ledger.reactivated.push(upgraded);
726
- }
727
- return true;
728
- }
729
- if (isRecent) {
730
- ledger.existingBetweenActors.push({
731
- candidateUserId,
732
- networkId: existingIndexId,
733
- existingOpportunityId: existing.id,
734
- existingStatus: existing.status,
735
- reason: 'same_trigger_recent_duplicate',
736
- existingTriggerIntentId: ownedIntentTriggerId,
737
- });
738
- persistDedupLog.info('Suppressing recent same-trigger duplicate', {
739
- triggerIntentId: ownedIntentTriggerId,
740
- candidateUserId,
741
- existingOpportunityId: existing.id,
742
- existingTriggerIntentId: ownedIntentTriggerId,
743
- existingStatus: existing.status,
744
- existingAgeMs: Date.now() - new Date(existing.createdAt).getTime(),
745
- reason: 'same_trigger_recent_duplicate',
746
- });
747
- return true;
748
- }
749
- persistDedupLog.info('Allowing same-trigger opportunity outside dedup window', {
750
- triggerIntentId: ownedIntentTriggerId,
751
- candidateUserId,
752
- existingOpportunityId: existing.id,
753
- existingStatus: existing.status,
754
- existingAgeMs: Date.now() - new Date(existing.createdAt).getTime(),
755
- });
756
- return false;
757
- }
758
- /** Trace summary for {@link persistNode}. */
759
- export function persistTraceSummary(result) {
760
- const r = result;
761
- if (r?.error)
762
- return `error: ${r.error}`;
763
- const opps = r?.opportunities;
764
- return opps ? `Persisted ${opps.length} opportunity(ies)` : undefined;
765
- }