@indexnetwork/protocol 22.0.0-rc.499.1 → 64.0.0

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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # Changelog
2
2
 
3
+ ## 64.0.0
4
+
5
+ ### Breaking changes
6
+
7
+ - Opportunity status is a projection of an append-only event log (`opened`, `agreed`, `committed`, `declined`, `expired`). Remove `updateOpportunityStatus` and `deleteOpportunity` exports, `stampOpportunityActorAction`, and `acceptSiblingOpportunities`. Drop `accepted_by` and `actors.actedAt`. One person's commit no longer accepts the row or opens a conversation.
8
+
9
+ ## 63.0.0
10
+
11
+ ### Breaking changes
12
+
13
+ - **`Intents.clarify()` → `Intents.prepare()`.** Fold recovery answers into the draft, run creation admission, and return `ready` with metadata or `needs_revision` with admission feedback plus a dynamic recovery form. Remove `ClarifyAnswer`, `ClarifyInput`, `ClarifyQuestion`, `ClarifyQuestionOption`, `ClarifyResult`, and `needs_clarification`.
14
+ - Export `PrepareAnswer`, `PrepareInput`, `PrepareResult`, `RecoveryField`, `RecoveryFieldKind`, and `RecoveryFieldOption` instead.
15
+
16
+ ## 62.0.0
17
+
18
+ ### Breaking changes
19
+
20
+ - Remove outcome-feedback capture and mining from the protocol. Remove the `OutcomeOutbox` export and the optional outbox arguments from the database ports `updateOpportunityStatus` and `stampOpportunityActorAction`; hosts must stop supplying these arguments and remove their feedback capture/mining wiring.
21
+ - Remove `PoolDiscriminatorMiner`, `DiscriminatorMiningInput`, `MinedDiscriminator`, `PoolCandidate`, `isOutcomeQuestionsActivated`, `OUTCOME_MAX_CANDIDATES`, `OUTCOME_MAX_PUBLIC_CONTEXT_CHARS`, `OUTCOME_MIN_INDEPENDENT_EXAMPLES`, `runOutcomeShadow`, `OutcomeExample`, `OutcomeLabel`, and `OutcomeShadowResult` from the public entry point. Delete the internal outcome pipeline and its discriminator miner, types, and evidence-verification helpers without compatibility exports.
22
+ - Remove the `poolDiscriminatorMiner`, `poolDiscriminatorAssigner`, and `negotiationEvidenceMiner` model keys. They are no longer accepted by `getModelName` or `EVAL_MODEL_OVERRIDES`.
23
+
24
+ ### Preserved behavior
25
+
26
+ - Negotiation outcomes and presentation, opportunity lifecycle and shared claim-safety guards, and intent preparation, clarification, and scoring are unchanged.
27
+
28
+ ## 61.0.0
29
+
30
+ ### Breaking changes
31
+
32
+ - A standing proposal cannot be proposed over. `decideNegotiationTurn` rejects a `propose` whose previous turn is the other seat's `propose` as the new `propose_over_offer` rejection, and `observeNegotiation` offers `counter`, `accept`, `decline` to a seat facing a proposal. `propose` keeps its two uses: opening a negotiation, and answering a counter.
33
+ - `NEGOTIATION_GUIDANCE` states the rule alongside the accept rule from 60.0.0.
34
+
35
+ ### Why
36
+
37
+ 60.0.0 made `propose` legal at every turn index so an answer to a counter could be re-offered. With nothing stopping a proposal from answering a proposal, two agents that already agreed volleyed restatements until the turn limit: one live negotiation ran `propose > counter > propose` ten times and never settled, each turn saying what the other had just said.
38
+
39
+ ### Preserved behavior
40
+
41
+ - Settled negotiations, turn limits, seat and eligibility checks, race detection, outcomes and their opportunity statuses are unchanged. No stored enum value changed, so no migration is required. A negotiation mid-flight facing a proposal simply loses `propose` from its menu.
42
+
43
+ ## 60.0.0
44
+
45
+ ### Breaking changes
46
+
47
+ - A counter is no longer a standing offer. `decideNegotiationTurn` accepts an `accept` only against the other seat's `propose`; an accept whose previous turn is a counter is rejected as `accept_without_offer`. The seat that asked a question is now the one that settles, because answering means proposing again.
48
+ - `propose` is valid at any turn index, not only the opening one. It is how an answer to a counter is put back on the table. The `propose_not_first` rejection is removed from `NegotiationRejection`; `counter_is_first` still blocks a counter at turn 0, and the opening remains a propose or a decline.
49
+ - `observeNegotiation` derives its menu from the same fact. A seat facing a `propose` sees `propose`, `counter`, `accept`, `decline`; a seat facing a `counter` sees `propose`, `counter`, `decline`; an empty log still sees `propose`, `decline`.
50
+ - `NEGOTIATION_GUIDANCE` states the new rule in place of "counter responds with revised terms".
51
+
52
+ ### Preserved behavior
53
+
54
+ - Settled negotiations, turn limits, seat and eligibility checks, race detection, and the `agreed`/`declined` outcomes and their opportunity statuses are unchanged. No stored enum value changed, so no migration is required. A negotiation mid-flight whose last turn is a counter simply loses `accept` from its menu.
55
+
56
+ ## 59.0.1
57
+
58
+ ### Documentation
59
+
60
+ - `IMPLEMENTATION.md` now describes the host's negotiation routes as they are: `GET /api/negotiations` lists a seat's negotiations, and one is observed and turned through its opportunity at `GET /api/opportunities/:id/negotiation` and `POST /api/opportunities/:id/negotiation/turns`. No exported surface changed.
61
+
62
+ ## 59.0.0
63
+
64
+ ### Breaking changes
65
+
66
+ - Discovery is no longer a post-persist workflow. `IntentFollowUp.onIntentSaved`, `onIntentArchived`, and `onIntentResumed` no longer imply matching work and may do nothing; hosts search on demand instead. The interface shape is unchanged, so implementations keep compiling. `scoreIntent` is unaffected.
67
+ - Remove the `@indexnetwork/discovery` workspace. There is no lens inference, hypothetical-document generation or validation, artifact cache, or match explainer anywhere in the repository. Retrieval is one embedding of the caller's own query against real intent embeddings, and the judging is the caller's.
68
+
69
+ ### Preserved behavior
70
+
71
+ - Pair identity and opening are unchanged: `pairKeyOf` plus `openCounterparties(pairs, decideNegotiationOpening)` still writes the opportunity and its negotiation atomically, and remains the only way one is created. Network/broadcast scope (`resolveDiscoveryNetworkScope`, `renderDiscoveryNetworkContext`), negotiation rules, and opportunity lifecycle/presentation are untouched.
72
+
73
+ ## 58.0.0
74
+
75
+ ### Breaking changes
76
+
77
+ - Extract post-intent discovery into the independent `@indexnetwork/discovery` workspace. Remove `OpportunityGraphFactory`, `OpportunityGraphThresholdOverrides`, `HydeGraphFactory`, `HydeGenerator`, `LensInferrer`, `HydeGraphDatabase`, `HydeCache`, the lens/search DTOs, `buildCandidateEvidence`, and discovery threshold exports from protocol. The extracted path uses plain async TypeScript and validated fetch-based model responses.
78
+ - Replace `IntentFollowUp.generateHyde`, `deleteHyde`, and `resumeDiscovery` with `onIntentSaved`, `onIntentArchived`, and `onIntentResumed`. Scheduling and failure/compensation behavior are unchanged; `scoreIntent` remains a separate best-effort metadata hook.
79
+ - Remove artifact storage methods from protocol database ports and multi-lens retrieval from `Embedder`. Replace `OpportunityGraphDatabase` with the lifecycle/read-only `OpportunityDatabase` port; expose `readOpportunities`, `updateOpportunityStatus`, and `deleteOpportunity` directly. Remove discovery agents from protocol model assignments.
80
+ - Hosts run discovery and commit returned potential pairs with `pairKeyOf` and `decideNegotiationOpening` through atomic `openCounterparties`. Protocol retains intent lifecycle, network/broadcast scope rules, negotiations, and opportunity lifecycle/presentation. Expose `resolveDiscoveryNetworkScope` and `renderDiscoveryNetworkContext` for host composition.
81
+
82
+ ### Preserved behavior
83
+
84
+ - Keep source-grounded frame-v1 cache identity and generation cohorts, validation failure semantics, real-intent candidate retrieval, membership checks, per-lens/per-network budgets, rejection cooldown, ranking limits, explanations, and atomic pair uniqueness. Hypothetical documents remain query-side retrieval artifacts.
85
+
86
+ ## 57.0.0
87
+
88
+ ### Breaking changes
89
+ - `Intents.clarify()` now applies creation admission to the complete draft and returns `ready` with semantic metadata or `needs_clarification` with feedback and questions. Model failures throw for retry; an empty question list no longer substitutes for admission.
90
+ - Explicit graph creation prepares once and persists exactly one new intent verbatim, including when similar intents exist. It no longer infers, rewrites, or reconciles creation into updates or archival. The reconciler agent injection is removed.
91
+ - Hosts may pass authenticated `preparation` to the creation graph to authorize final user revisions without another admission gate. Preserve metadata only when it measures the submitted text; use null metadata after revisions. Never accept preparation objects from untrusted clients.
92
+ - `IntentFollowUp.scoreIntent` is required for best-effort rescoring after edited creation. It must never reject, rewrite, archive, or undo the saved intent and must apply metadata only while the owner and text still match. `Intents.scoreIntent()` returns measurements without admission filters.
93
+ - Export `PreparedIntent` and `IntentSemanticMetadata` for host integration. Existing explicit update, read, archive, and status operations retain their behavior.
94
+
95
+ ### Fixed
96
+ - Restrict the generic-job shortcut to bare requests. Qualified searches containing "a job" use the verifier's existing admission thresholds and specificity verdict.
97
+
3
98
  All notable changes to `@indexnetwork/protocol` are documented here.
4
99
 
5
100
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
@@ -10,6 +105,69 @@ See [STABILITY.md](./STABILITY.md) for the public-contract and tier definitions.
10
105
  > itemized. From `2.0.0` onward, keep this file updated as part of every release
11
106
  > (bump `package.json` and the `[Unreleased]` section before promoting to `main`).
12
107
 
108
+
109
+ ## 56.0.0
110
+
111
+ ### Breaking changes
112
+
113
+ - **The tool layer is gone.** `createToolRegistry`, `invokeToolRuntime`,
114
+ `toolRuntimeErrorToResult`, `getToolTimeoutPolicy`, `resolveChatContext`,
115
+ `createEnrichmentTools`, `createOpportunityTools`, `Intents.createTools`,
116
+ `Networks.createTools`, and the `ResolvedToolContext` / `ToolDeps` /
117
+ `RawToolDefinition` / `EnrichmentToolDeps` / `OpportunityToolDeps` /
118
+ `IntentToolDeps` / `NetworkToolDeps` types are removed, along with every
119
+ `*.tools.ts` factory, `tool.registry.ts`, `tool.runtime.ts`, and
120
+ `tool.helpers.ts`. Hosts expose capabilities as their own REST resources and
121
+ reach the protocol through the graph factories and capability classes, which
122
+ are unchanged. `@indexnetwork/agent`'s own `Tool` loop is a different thing
123
+ and is untouched.
124
+ - **`ToolScopeType` is `ScopeType`** and `deriveAllowedNetworkIds` /
125
+ `deriveDiscoveryNetworkIds` moved to `internal/shared/agent/scope.ts`.
126
+ - **`CompositeToolDatabase` is `CompositeDatabase`.** Same members.
127
+
128
+ ### Changed
129
+
130
+ - Canonical guidance (`GET /api/docs` in the reference host) describes REST
131
+ resources and CLI commands instead of tool names, and the user event stream is
132
+ documented as `GET /api/events`.
133
+
134
+ ## 55.0.0
135
+
136
+ ### Breaking changes
137
+
138
+ - Remove MCP serving and authentication exports: `createMcpServer`, `ScopedDepsFactory`, `McpAuthResolver`, `McpAuthInput`, `McpResolvedIdentity`, `buildMcpOnboardingMessage`, and `ONBOARDING_ALLOWED`.
139
+ - Remove `createOpportunityVerdictTools`, the registry `surface` option, and MCP-only tool context/dependency fields. Hosts compose scoped tools through `createToolRegistry` and `invokeToolRuntime`; owner approval remains a separate explicit HTTP operation.
140
+ - External agents use the HTTP API through CLI 0.24.0. `read_docs` now serves canonical HTTP/CLI workflows, and utility tools use one shared registry. Shared execution limits, cancellation, ownership, and network scoping remain in place.
141
+ - Remove the direct MCP SDK dependency. The API host removes `/mcp` and MCP OAuth discovery and drops only the three obsolete OAuth tables.
142
+
143
+ ## 54.0.1 - 2026-09-09
144
+
145
+ ### Changed
146
+
147
+ - Centralize shared negotiation guidance, MCP instructions, and `read_docs`
148
+ content and composition in `src/protocol/protocol.prompt.ts`. Emitted text,
149
+ topic matching, response envelopes, and package-root exports are unchanged.
150
+ - Share negotiation limits between guidance and enforcement through
151
+ `src/protocol/negotiation.constants.ts`, and document prompt consumers in the
152
+ implementation guide.
153
+
154
+ ## 54.0.0
155
+
156
+ ### Breaking changes
157
+
158
+ - Add the `Negotiations` participation capability, current-state observations,
159
+ protocol guidance, and atomic host commit contract. Submissions carry the
160
+ observed `expectedTurnCount`; stale decisions are refused.
161
+ - `openCounterparties` now receives a protocol decision callback that hosts must
162
+ evaluate against current network membership and active intent assignments.
163
+ - Replace `NEGOTIATION_MAX_TURNS_AMBIENT` (and the private chat limit) with one
164
+ `NEGOTIATION_MAX_TURNS` of 12. Exhaustion blocks further turns with no outcome;
165
+ A2A agreement advances only to pending human approval.
166
+ - The API host renames domain tables with `protocol_` prefixes, adds private
167
+ `agent_sessions`, and composes the independent agent library through its local
168
+ TUI runner. Forward migrations preserve existing records.
169
+
170
+
13
171
  ## Release model
14
172
 
15
173
  Every push to `dev` publishes `<package.json version>-rc.<run>.<attempt>` under
@@ -20,6 +178,1646 @@ went 6.7.1 → 8.0.2 with no 7.x in between because the whole 7.x line shipped a
20
178
  prereleases between the two promotions. To track every change, read `rc`; to
21
179
  pin a supported release, use `latest`.
22
180
 
181
+ ## 53.0.0 - 2026-09-06
182
+
183
+ ### Removed
184
+
185
+ - **BREAKING — `mcpRateLimiter` is gone.** Hosts used to inject a per-principal
186
+ throttle on MCP tool dispatch. That hook is deleted; a tool call runs as soon
187
+ as identity resolves.
188
+
189
+ ## 52.0.0 - 2026-09-06
190
+
191
+ ### Removed
192
+
193
+ - **BREAKING — the MCP capability policy is gone.** `mcp.authorization-policy.ts`
194
+ is deleted along with the `CANONICAL_MCP_CAPABILITY_POLICY_OPTIONS`,
195
+ `McpCapabilityPolicyOptions`, `McpAuthorizationObserver` and
196
+ `McpAuthorizationDenialEvent` exports. `createMcpServer` now takes three
197
+ arguments — `(deps, authResolver, scopedDepsFactory)` — and every
198
+ authenticated caller sees and can call every registered tool. A credential
199
+ names a user, so ownership and membership checks in the handlers are the only
200
+ remaining gate.
201
+ - **BREAKING — agent CRUD is not an MCP tool.** `register_agent`, `list_agents`,
202
+ `update_agent` and `delete_agent` are deleted. Agents are created, updated and
203
+ deleted from the owner's own signed-in session over the host's REST surface.
204
+ `read_own_agent` stays, unchanged, as a plain authenticated tool.
205
+ - The owner-session gate inside `accept_opportunity` and `reject_opportunity` is
206
+ removed. A verdict passed through a key is the owner passing it, and the write
207
+ was always scoped to `context.userId`.
208
+
209
+ ## 51.0.0 - 2026-09-06
210
+
211
+ ### Removed
212
+
213
+ - **BREAKING — an API key names a user, never an agent.**
214
+ `McpResolvedIdentity` is `{ userId }` plus the session flag: `agentId`,
215
+ `enrollmentCapable`, `isHermesAgent` and `networkScopeId` are gone, along with
216
+ `McpApiKeyMetadataSchema`. Nothing derives a principal from key metadata, so
217
+ the `enrollment_key`, `unregistered_key`, `registered_network_agent` and
218
+ `registered_global_agent` capability profiles are gone too — a caller is
219
+ either a session or a key, and a key gets the full product tool set.
220
+ - **BREAKING — `agent_permissions` is deleted.** `AgentPermissionRecord`,
221
+ `AgentWithRelations` and `GrantPermissionInput` are removed from the public
222
+ types; `AgentDatabase` loses `getAgentWithRelations`, `grantPermission`,
223
+ `revokePermission` and `hasPermission`, and gains `getSelectedNegotiator`.
224
+ The `grant_agent_permission` and `revoke_agent_permission` MCP tools are
225
+ gone, `register_agent` no longer takes `permissions`, and `read_own_agent`
226
+ returns the owner's selected negotiator.
227
+ - **BREAKING — tool access rules collapse to four kinds.**
228
+ `McpToolAccessRule` is `authenticated`, `human_only`, `agent_admin` or
229
+ `removed`; `reach` and the stored-permission projection
230
+ (`defineMcpToolPermissionMap`, `McpToolPermissionMap`,
231
+ `MCP_PERMISSION_ACTIONS`, `projectStoredPermissionActions`) are removed.
232
+ Owner verdicts and `delete_network` stay `human_only`; agent CRUD is
233
+ `agent_admin` and reachable only from a session.
234
+
235
+ ### Changed
236
+
237
+ - `ResolvedToolContext` no longer carries `agentId`, so rate limiting and
238
+ owner-verdict checks key off the user and the session flag alone.
239
+
240
+ ## 50.0.0 - 2026-09-05
241
+
242
+ ### Removed
243
+
244
+ - **BREAKING — drop the IND-593 owner-approval proof port.** `update_opportunity`
245
+ send/accept/reject is an ordinary tool call gated by existing MCP/session auth.
246
+ Removed `ownerApprovalProof` from the public schema, plus
247
+ `OpportunityOwnerApprovalAuthority` and related public types,
248
+ `bindOwnerApprovalProvenance`, and `opportunityOwnerActionForStatus`. Owner
249
+ verdict tools (`accept_opportunity` / `reject_opportunity`) still require a
250
+ host-bound session (`context.isSessionAuth`).
251
+
252
+ ## 49.0.1 - 2026-09-05
253
+
254
+ ### Changed
255
+
256
+ - Documentation only. TSDoc and inline comments across `platform/database/` and
257
+ `internal/opportunities/` no longer call a network an "index".
258
+ `IMPLEMENTATION.md` drops the removed `indexer` dependency from its `Networks`
259
+ example and describes `createAssignmentGraph()` as it behaves today: no
260
+ scoring policy, rows written at score 1 with `mode: manual_override`.
261
+ `src/README.md` drops the Intent Indexer agent row, whose file
262
+ (`internal/intents/indexing/intent.indexer.ts`) no longer exists. No public
263
+ surface change.
264
+
265
+ ## 49.0.0 - 2026-09-04
266
+
267
+ ### Removed
268
+
269
+ - **BREAKING — the three intent↔network MCP tools were renamed.** External agents
270
+ must switch tool names; there is no alias or compatibility shim.
271
+ - `create_intent_index` → `add_intent_to_network`
272
+ - `read_intent_indexes` → `list_intent_networks`
273
+ - `delete_intent_index` → `remove_intent_from_network`
274
+
275
+ ### Changed
276
+
277
+ - **BREAKING — host interfaces no longer call a network an "index".** The domain
278
+ renamed indexes to networks, but the ports a host implements still said
279
+ `Index`, so a host had to speak both vocabularies. Every such member is renamed
280
+ in place. Hosts must rename their implementations:
281
+ - `Database`/`UserDatabase`/`SystemDatabase` methods: `getOwnedIndexes` →
282
+ `getOwnedNetworks`, `getUserIndexIds` → `getUserNetworkIds`,
283
+ `getPublicIndexesNotJoined` → `getPublicNetworksNotJoined`,
284
+ `getMembersFromUserIndexes` → `getMembersFromUserNetworks`,
285
+ `getActiveIntentsAcrossIndexes` → `getActiveIntentsAcrossNetworks`,
286
+ `getIntentsInIndex` → `getIntentsInNetwork`, `getUserIntentsInIndex` →
287
+ `getUserIntentsInNetwork`, `getIntentsInIndexForMember` →
288
+ `getIntentsInNetworkForMember`, `getIntentIndexScores` →
289
+ `getIntentNetworkScores`, `deleteIntentIndexAssociations` →
290
+ `deleteIntentNetworkAssociations`, `isIntentAssignedToIndex` →
291
+ `isIntentAssignedToNetwork`, `unassignIntentFromIndex` →
292
+ `unassignIntentFromNetwork`, `isIndexOwner` → `isNetworkOwner`,
293
+ `removeMemberFromIndex` → `removeMemberFromNetwork`, `updateIndexSettings` →
294
+ `updateNetworkSettings`.
295
+ - Entity types: `OwnedIndex` → `OwnedNetwork`, `IndexMemberDetails` →
296
+ `NetworkMemberDetails`, `IndexedIntentDetails` → `NetworkIntentDetails`,
297
+ `UpdateIndexSettingsData` → `UpdateNetworkSettingsData`. The
298
+ `NetworkMembership.indexPrompt` field is now `networkPrompt`.
299
+ - Scope plumbing: `indexScope` is `networkScope` everywhere it appears —
300
+ `SystemDatabase.indexScope`, the `createSystemDatabase` /
301
+ `ScopedDepsFactory.create` third argument, `HydeSearchOptions.indexScope`,
302
+ `ChatToolRequest.indexScope`, and the intent/opportunity graph state channels.
303
+ - Tool context: `ResolvedToolContext.indexName`/`scopedIndex` are `networkName`/
304
+ `scopedNetwork`; `ToolRequestContext.indexName` is `networkName`.
305
+ - Graph registry keys: `graphs.index` → `graphs.network` and
306
+ `graphs.intentIndex` → `graphs.intentNetwork`. Their trace name changed from
307
+ `index` to `network`.
308
+ - `ChatContextAccessError.code` values `INDEX_NOT_FOUND` and
309
+ `INDEX_MEMBERSHIP_REQUIRED` are now `NETWORK_NOT_FOUND` and
310
+ `NETWORK_MEMBERSHIP_REQUIRED`.
311
+ - `resolveIndexNames` → `resolveNetworkNames`;
312
+ `DiscoveryNegotiation.indexContext` → `networkContext`.
313
+ - Presenter context: the `indexName` field returned by `gatherPresenterContext`
314
+ is `networkName`, which also fixes `focusedNetworkLabel` reading a field that
315
+ no longer existed and falling back to the network id.
316
+ - Agent-facing tool descriptions, scope-refusal messages, and `read_docs`
317
+ guidance now say "network" or "community" wherever they said "index".
318
+ - The intent assignment pipeline keeps its verb naming (`getIntentForIndexing`,
319
+ `indexer.graph.ts`, `IndexedIntent`): those describe assigning a signal, not
320
+ the community noun.
321
+
322
+ ## 48.1.0 - 2026-09-04
323
+
324
+ ### Changed
325
+
326
+ - **`read_docs` speaks networks, not indexes.** The topic key `indexes` is now
327
+ `networks` and its section is rewritten in network terms, so `topic=indexes`
328
+ no longer resolves to a section and falls back to the summary. MCP callers are
329
+ unaffected: that surface already served `communities-networks`.
330
+ - **Opportunity-graph log payloads renamed.** `targetIndexesCount` is
331
+ `targetNetworksCount` and the `indexes` key is `networks`, alongside the
332
+ surrounding trace strings. Log-scraping dashboards need updating.
333
+
334
+ ## 48.0.0 - 2026-09-04
335
+
336
+ ### Added
337
+
338
+ - **`Intents.clarify({ payload, answers? })` → `{ payload, questions }`.** One
339
+ stateless round of signal clarification: with no answers it returns the payload
340
+ untouched plus the questions worth asking; with answers it rewrites the payload
341
+ so those answers are stated in it and returns whatever is still open. Nothing
342
+ is stored, so skipping is always valid. `ClarifyAnswer`, `ClarifyInput`,
343
+ `ClarifyQuestion`, `ClarifyQuestionOption` and `ClarifyResult` are exported.
344
+
345
+ ### Removed
346
+
347
+ - **BREAKING: the intake funnel is gone.** `IntakePack`, `IntakePackInput`,
348
+ `IntakePackQuestion`, `IntakePackQuestionOption`, `IntakeAnswer`, `IntakeRound`,
349
+ `FollowUpPlan`, `SynthesisInput` and `SynthesisResult` are removed along with
350
+ the pack generator and intake orchestrator. Clarification is `clarify` now, and
351
+ it holds no run state — hosts can drop their intake pack and run storage.
352
+ - **BREAKING: signals are no longer proposed before they are created.** The
353
+ dry-run branch of `create_intent`, the `intent_proposal` fence it emitted and
354
+ the `autoApprove` argument are gone. `create_intent({ description, networkIds })`
355
+ persists directly, so hosts can drop their proposal storage and their confirm
356
+ and reject endpoints.
357
+ - **BREAKING: networks are no longer assigned by a model.** `IntentNetworkIndexer`,
358
+ `IntentIndexingResult`, `Intents.indexIntent` and the evaluated branch of the
359
+ indexer graph are removed, and so is the threshold scoring behind them. A signal
360
+ reaches exactly the networks its owner names on create or links afterwards with
361
+ `create_intent_index`.
362
+ - **BREAKING: agents no longer have transports.** `AgentTransportRecord`,
363
+ `CreateTransportInput` and the `AgentDatabase` methods `createTransport`,
364
+ `deleteTransport`, `recordTransportFailure` and `recordTransportSuccess` are
365
+ removed, and `AgentWithRelations` no longer carries a `transports` array. No
366
+ delivery loop ever read the rows. Hosts can drop their `agent_transports`
367
+ storage.
368
+ - `createIntentSuggested` and `suggestedIntentDescription` from the opportunity
369
+ graph state. Nothing routed on them.
370
+
371
+ ## 47.0.0 - 2026-09-03
372
+
373
+ ### Removed
374
+
375
+ - **BREAKING: `'personal'` is no longer an agent type.** `AgentRecord.type` and
376
+ `CreateAgentInput.type` are now `'external' | 'system'`. The `personal` row was
377
+ the auto-provisioned per-user negotiator behind the in-process negotiation
378
+ loop; nothing reads it since that loop was deleted. Hosts must delete their
379
+ `personal` rows and shrink their own enum — user-registered agents are
380
+ `external`.
381
+
382
+ ## 46.0.0 - 2026-09-03
383
+
384
+ ### Removed
385
+
386
+ - **BREAKING: the question surface is gone.** `Question`, `QuestionPurpose`,
387
+ `QuestionPurposeSchema`, `QuestionStrategy`, `QuestionStrategySchema`,
388
+ `QuestionRecoverySnapshot` and `QuestionVoidedReason` are removed along with
389
+ `question.ts`, and so are the question-block exports (`QuestionBlockSchema`,
390
+ `QuestionBlockQuestionSchema`, `QuestionBlock`, `QuestionBlockQuestion`,
391
+ `ParsedQuestionMessage`, `parseQuestionMessage`, `serializeQuestionMessage`,
392
+ `questionBlockFixture`, `questionMessageFixture`, `questionProseFixture`).
393
+ The durable question system was retired generator-first; nothing produced,
394
+ stored or rendered these shapes any more. Hosts can drop their `questions`
395
+ storage with them.
396
+ - `UnderspecificationTypeSchema` and `UnderspecificationType` now come straight
397
+ from `protocol/schemas/underspecification.schema.ts`. The exported names and
398
+ types are unchanged; only the (never-contractual) internal module moved.
399
+
400
+ ## 46.0.0 - 2026-09-03
401
+
402
+ ### Removed
403
+
404
+ - **BREAKING: `upsertDiscoveryMatchCandidates` and `openCandidates` are replaced
405
+ by `openCounterparties(pairs)`.** Discovery no longer stages a scored pair
406
+ before opening it: it hands the host the pair and the host writes the
407
+ opportunity and its negotiation in one transaction, keyed on `pairKey`. Hosts
408
+ can drop their candidates table; the pair-uniqueness it enforced belongs on
409
+ the negotiation.
410
+ - **BREAKING: `DiscoveryMatchCandidate`, `CreateDiscoveryMatchCandidateData` and
411
+ `DiscoveryMatchCandidateStatus` are gone.** `CreateIntentCounterpartyData`
412
+ replaces the create shape as a call payload rather than a stored entity.
413
+
414
+ ## 45.0.0 - 2026-09-03
415
+
416
+ ### Added
417
+
418
+ - **`NegotiationContextDatabase`** (`platform/database/negotiation.ts`), with
419
+ `NegotiationContextRecord`, `NegotiationContextTurn` and
420
+ `NegotiationContextOutcome`. The host reads one negotiation record and its
421
+ turn log; the loader turns that into the prompt block and the negotiating
422
+ chip. It replaces every task-shaped read the old loader performed.
423
+ - **`OpportunityGraphDatabase.openCandidates`** returns `OpenedNegotiation[]`.
424
+ Discovery now opens the opportunity and its negotiation record together, so
425
+ the graph never leaves a scored candidate without a record to negotiate in.
426
+
427
+ ### Removed
428
+
429
+ - **BREAKING: `NegotiationGraphDatabase` is gone**, along with
430
+ `NegotiationTurnSchema`, the `negotiation-evidence` module and its exports,
431
+ the negotiation digest schema, and `CreateAndOpenResult`. Index is the server
432
+ for a negotiation: it validates turn order, appends the turn and computes the
433
+ settlement, so there is no in-process graph left to give a port.
434
+ - **BREAKING: `listPendingCandidatesForIntent` is replaced by `openCandidates`**
435
+ on the discovery database port.
436
+ - **BREAKING: `'stalled'` is gone from `OpportunityStatus`.** It was the
437
+ turn-cap outcome of the A2A task loop; the negotiation record has two
438
+ outcomes and a close, so nothing produces it.
439
+
440
+ ## 44.0.0 - 2026-09-03
441
+
442
+ ### Removed
443
+
444
+ - **BREAKING: `NegotiationRoundLogDatabase`, `NegotiationRoundLogEventKind` and
445
+ `NegotiationRoundLogEventRecord` are gone.** The port was orphaned when the
446
+ in-process negotiation graph and its `foldNegotiationRoundLog` were deleted:
447
+ nothing composed it into `NegotiationGraphDatabase` and no host implemented
448
+ its two methods. Hosts that declared them can delete those implementations
449
+ along with their `negotiation_round_log_events` storage.
450
+
451
+ ## 43.0.0 - 2026-09-02
452
+
453
+ ### Removed
454
+
455
+ - **BREAKING: `McpAuthInputSchema` no longer accepts `telegramHandle` or
456
+ `telegramUsername`.** The MCP server stops reading the `x-telegram-handle` and
457
+ `x-telegram-username` headers, and the host no longer binds a Telegram handle
458
+ to an account at authentication time. Telegram on a user profile is now only a
459
+ social link, so `telegram-handle.ts` and `social-label.ts` are unchanged.
460
+
461
+ ## 42.0.0 - 2026-09-02
462
+
463
+ ### Removed
464
+
465
+ - **BREAKING: the premises capability is gone.** `create_premise`,
466
+ `read_premises`, `update_premise`, and `retract_premise` are no longer
467
+ registered; `PremiseGraphFactory`, `PremiseGraphDatabase`, `PremiseRecord`,
468
+ `OpportunityActor.premise`, and every premise method on the host database
469
+ ports are removed. Matching is intent-only: `HydeTargetCorpus` drops
470
+ `'premises'`, the `query_premise` evidence kind and the
471
+ `sourcePremiseId`/`candidatePremiseId` candidate fields are gone, and
472
+ `manage:premises` is no longer a permission action. The protocol README drops
473
+ **Premise** as an entity: context stands on its own, and candidate generation
474
+ no longer lists premise-to-premise as a strategy.
475
+ - **BREAKING: opportunity delivery is gone.** `confirm_opportunity_delivery`,
476
+ the `DeliveryLedger` port, `getOrCreateDeliveryCardBatch`,
477
+ `buildDeliveryCardPresentationCacheKey`, the `isDeliveryAgent` identity flag,
478
+ and digest mode (`includeDigestMarkers`, `selectDigestCandidates`,
479
+ presenter `digestSummary`) are removed. Opportunity statuses are unchanged.
480
+ - **BREAKING: `read_activity_summary` is gone**, along with the activity
481
+ projection and the `UserDatabase.getAgentActivitySummary` port.
482
+
483
+ No aliases or compatibility shims: hosts must drop the deleted ports.
484
+
485
+ ## 41.0.0 - 2026-09-02
486
+
487
+ ### Removed
488
+
489
+ - **BREAKING: `SYSTEM_AGENT_IDS.chatOrchestrator` is gone.** The only remaining
490
+ well-known system agent is `negotiator`. `AgentDatabase.getSystemAgentIds()`
491
+ no longer returns a chat-orchestrator id.
492
+ - **BREAKING: the in-process personal agent is gone.** `PersonalAgentGraph` and
493
+ everything it needed — its judgment, prompt, act types, activity port, match
494
+ refs and the `personal-agent.e2e` spec — are deleted. Index no longer runs an
495
+ agent; a host that wants one builds it as a client over REST/MCP.
496
+ - **BREAKING: `ChatGraph` and the whole chat capability are gone.**
497
+ `ChatGraphFactory`, `ChatAgent`, the personas (`SIGNAL_PERSONA`,
498
+ `ONBOARDING_PERSONA`, `withPersona`), the streamer, suggester, summarizer,
499
+ title generator, interrupt classifier, question-dedup, chat state/tools/utils
500
+ and the chat-streaming types no longer exist. There is no H2A chat runtime in
501
+ the protocol.
502
+ - **BREAKING: `NegotiationGraph` and the negotiation MCP tools are gone.**
503
+ `NegotiationGraphFactory`, the turn author, the round-reflect enqueue, the
504
+ `IndexNegotiator` agent, the insight generator and summarizer, and the
505
+ `list_negotiations` / `get_negotiation` / `respond_to_negotiation` /
506
+ `answer_pending_question` tools are all deleted. Negotiation turn shapes and
507
+ the `NegotiationGraphDatabase` port remain, because the host still persists
508
+ and reads negotiation conversations.
509
+ - **BREAKING: host ports for the deleted runtimes are gone** —
510
+ `AgentDispatcher`, `ChatSessionReader`, `ChatSummaryReader`,
511
+ `ChatMessageWriter`, `NegotiationSummaryReader`, `MintConnectLink`, and
512
+ `AgentRepositoryPort.findAuthorizedAgents`.
513
+ - Specs are down to three: `capabilities/tests/intents`,
514
+ `internal/opportunities/tests/opportunity.graph`, and
515
+ `internal/premises/tests/premise.decomposer`.
516
+
517
+ ### Changed
518
+
519
+ - **BREAKING: `ChatGraphCompositeDatabase` is `CompositeToolDatabase`.** The
520
+ type outlived the graph it was named after; it is still the composite the
521
+ host passes to the tool factory.
522
+ - **BREAKING: `OpportunityGraphFactory` drops two constructor parameters.** The
523
+ `matchesReady` and `agentDispatcher` slots are gone, so `thresholdOverrides`
524
+ moves from the eighth positional argument to the sixth.
525
+
526
+ **Kept:** intents, premises, networks, opportunities (including
527
+ `OpportunityGraphFactory` discovery into candidates), radar, HyDE, the agent
528
+ registry tools, the owner-verdict tools, and the MCP server shell over what
529
+ remains.
530
+
531
+ ## 40.0.0 - 2026-08-29
532
+
533
+ ### Changed
534
+
535
+ - **BREAKING: `VectorStoreOption.filter` is `Record<string, unknown>`.** It was
536
+ `Record<string, any>`. Callers passing a filter are unaffected; host
537
+ implementations of the `VectorStore`/`Embedder` port that read values off
538
+ `options.filter` must now narrow them instead of relying on `any`.
539
+
540
+ ## 39.0.0 - 2026-08-29
541
+
542
+ ### Changed
543
+
544
+ - **BREAKING: the intent follow-up port is no longer named after a queue.**
545
+ `IntentGraphQueue` is `IntentFollowUp` and `IntentGraphQueueScope` is
546
+ `IntentFollowUpScope`, both now in `platform/runtime/follow-up.ts`. The
547
+ methods lose their job wording: `addGenerateHydeJob` → `generateHyde`,
548
+ `addDeleteHydeJob` → `deleteHyde`, `addResumeDiscoveryJob` →
549
+ `resumeDiscovery`. `IntentsDeps.queue` is `IntentsDeps.followUp` and the
550
+ agent tool context's `intentQueue` is `intentFollowUp`. Behaviour is
551
+ unchanged; the host has run this work in-process since the queue system was
552
+ removed. Update call sites by renaming — there is no compatibility shim.
553
+
554
+ ## 38.0.1 - 2026-08-28
555
+
556
+ ### Removed
557
+ - Delete `docs/` and every spec except five (`capabilities/tests/intents`,
558
+ `capabilities/tests/negotiations.e2e`, `capabilities/tests/personal-agent.e2e`,
559
+ `internal/opportunities/tests/opportunity.graph`,
560
+ `internal/premises/tests/premise.decomposer`), along with
561
+ `scripts/tests/` and `scripts/architecture/tests/`. The `test:architecture`
562
+ script is gone and `architecture:check` no longer calls it; the three
563
+ `architecture:*` scripts are unchanged and still gate the package.
564
+ `LIVE_MODEL_SPECS` drops two entries that no longer existed. No source or
565
+ public-surface change: `src/index.ts` exports exactly what it did in 38.0.0.
566
+
567
+ ## 37.0.0 - 2026-08-27
568
+
569
+ ### Breaking
570
+
571
+ - **`read_premises(userId)` is scoped to shared networks.** Cross-user premise
572
+ reads are denied unless the caller and target share at least one network
573
+ membership, and return only the premises assigned to a shared network — a
574
+ premise its author never put into a network you are both in stays private.
575
+ `includeRetracted` is own-only.
576
+ - **`get_negotiation` redacts counterparty continue-turn `reasoning`.** The
577
+ shared thread still exposes `message`; each seat keeps its own `reasoning`.
578
+ Pause payloads remain private to the pausing seat (now also on the presenter
579
+ loader path).
580
+
581
+ ## 36.0.0 - 2026-08-24
582
+
583
+ ### Breaking
584
+
585
+ - **Intent matches and negotiations are isolated by their exact intent pair.**
586
+ `persistIntentScopedOpportunityIfNetworkEligible` no longer returns the
587
+ `pair_active_negotiation` conflict: any opportunity for the same two intent
588
+ seats deduplicates persistence. Hosts must allow different intent
589
+ pairs between the same users to persist and negotiate independently; task
590
+ creation remains idempotent per opportunity. Counterparty seats are bound
591
+ from authoritative discovery candidates rather than evaluator-generated
592
+ intent IDs, and intent-scoped persistence fails closed on an unbound seat.
593
+
594
+ - **Negotiation drains are keyed by durable task generations and tasks bind
595
+ both seats at creation.** `NegotiationTaskMetadata` gains
596
+ `drainGeneration`; `NegotiationGraphDatabase.openNegotiationTask` accepts
597
+ the complete `seats` map; `NegotiationRoundReflectJobData` gains
598
+ `generation`; `NegotiationTaskState` includes the active `submitted` state;
599
+ and `negotiationRoundReflectJobId` now requires its generation. Reopening a
600
+ paused task advances its generation, so one pause is deduplicated exactly
601
+ once without suppressing a later pause in the same round.
602
+
603
+ ### Changed
604
+
605
+ - PersonalAgent intent turns reload durable negotiation state after each
606
+ action, cannot finish while an own `ready_for_verdict` pause remains, and
607
+ expose counterparty pauses only through canonical public status prose.
608
+ - Only the seat owning a `ready_for_verdict` pause may resolve it;
609
+ counterparty-owned pauses cannot be re-opened, and kickoff strategy copy
610
+ cannot bypass canonical public status narration.
611
+ - The negotiation watchdog retries reflect delivery for durable
612
+ `ready_for_verdict` pauses, and intent-cycle projections count both
613
+ `submitted` and `working` tasks as active.
614
+ - Verdict completion now atomically records the outcome, completes the task,
615
+ and preserves any concurrent terminal human decision. Post-verdict reflect
616
+ delivery remains durably marked until it succeeds, terminal owner actions
617
+ left beside active tasks are recovered by the watchdog, and bounded sweeps
618
+ rotate checked rows so newer pauses cannot starve.
619
+ - Scheduled opportunity expiry now closes any active negotiation through a
620
+ distinct system lane, without fabricating an owner verdict, so expired work
621
+ cannot hold either seat's round open.
622
+
623
+ ## 35.0.0 - 2026-08-24
624
+
625
+ ### Breaking
626
+
627
+ - **PersonalAgent questions use the canonical structured question contract.**
628
+ `message_user.options` is replaced by `message_user.questions` on decided
629
+ and executed acts and on the conversation delivery port. Questions are
630
+ safety-checked and delivered separately from the message introduction so
631
+ clients can render the guided question UI directly. The exported
632
+ `normalizeMessageOptions` helper is replaced by `normalizeMessageQuestions`.
633
+
634
+ ### Added
635
+
636
+ - `PersonalAgentActivity` and `PersonalAgentActivityPort` provide bounded,
637
+ user-facing progress updates for live intent turns without exposing internal
638
+ identifiers, model reasoning, or private context.
639
+
640
+ ## 34.0.1 - 2026-08-24
641
+
642
+ ### Changed
643
+
644
+ - All canonical agent defaults now use Google Gemini 3.7 Flash with its
645
+ required low reasoning effort. Non-Gemini model overrides do not receive
646
+ Gemini-specific reasoning parameters.
647
+
648
+ ## 34.0.0 - 2026-08-24
649
+
650
+ ### Breaking
651
+
652
+ - **PersonalAgent intent turns use one sequential judgment choice at a time.**
653
+ `PersonalAgentJudgment.decide(context)` and
654
+ `PersonalAgentJudgment.reply(context, executed)` are replaced by
655
+ `next(context, executed, nonDurable?)`. Each call returns one
656
+ `PersonalAgentDecidedAct`; completed effects and refused irreversible calls
657
+ inform the next choice before the turn ends with `message_user`.
658
+ - **The dedicated `ask` act is removed.** Questions are ordinary
659
+ `message_user` responses, so an unresolved question about one matter no
660
+ longer blocks an independent action on another. `PersonalAgentDecidedAct`
661
+ and `PersonalAgentExecutedAct` no longer include `ask`, and executed
662
+ `message_user` acts no longer carry reply-stage `stage` or `fallback`
663
+ fields.
664
+ - **Executed kickoff results gain required attempt accounting.** Every
665
+ `PersonalAgentExecutedAct` with `tool: 'kickoff'` now includes `attempted`
666
+ and `failed` alongside `opened`.
667
+ - **The separate reply-stage API is deleted.** Removed root exports:
668
+ `PERSONAL_AGENT_REPLY_FALLBACK`, `renderPersonalAgentReplyStage`,
669
+ `validateDecidedActs`, `PersonalAgentReply`, and
670
+ `PersonalAgentReplyFallbackReason`. Use the singular `validateDecidedAct`
671
+ for one choice.
672
+
673
+ ### Added
674
+
675
+ - `PersonalAgentNonDurableObservation`, the feedback shape for an
676
+ irreversible tool choice refused before any write or ledger entry.
677
+
678
+ ### Changed
679
+
680
+ - Intent-scope events now share one bounded, result-informed conversational
681
+ tool loop. Repeated irreversible calls are refused against the turn's
682
+ snapshot, and a failure after durable work or tool-budget exhaustion ends
683
+ with honest terminal copy instead of retrying earlier effects.
684
+
685
+ ## 33.0.0 - 2026-08-24
686
+
687
+ ### Breaking
688
+
689
+ - **External negotiation responses use `NegotiationAuthoredTurn` directly.**
690
+ `respond_to_negotiation` accepts only `outreach`, `counter`, `question`,
691
+ `pause(needs_principal)`, and `pause(ready_for_verdict)`; it never accepts
692
+ terminal verbs. The retired `HermesNegotiationActionSchema` /
693
+ `HermesNegotiationAction` action vocabulary is removed. A counterparty that
694
+ wants out must pause `ready_for_verdict` with a `reject` recommendation for
695
+ its own PersonalAgent to decide.
696
+ - **`NegotiationGraphDatabase` gains `openNegotiationTask`.** Graph opens now
697
+ require one durable atomic open-or-return-live-task write; hosts must
698
+ revalidate eligibility there and return `{ task, created }` so a concurrent
699
+ opener can stop without authoring duplicate opening outreach.
700
+
701
+ ## 32.0.0 - 2026-08-24
702
+
703
+ ### Breaking
704
+
705
+ - **`NegotiationGraph` refuses to open an opportunity whose introducers have
706
+ not all approved it.** The gate now lives on the write, not only where
707
+ discovery decides which signals to wake, so no caller can reach past it.
708
+ - **New negotiation pause reason `open_failed`.** `NEGOTIATION_PAUSE_REASONS`
709
+ gains it, and `{ negotiationId, pause }` now accepts
710
+ `NegotiationSystemPauseReason` (`'counterparty_silent' | 'open_failed'`)
711
+ rather than the single literal. A kickoff whose open failed after `init`
712
+ created the task compensates it into this pause, so the round's active count
713
+ can still reach zero. Unlike `turn_cap` it stays re-kickable.
714
+ - **A negotiation binds a signal PER SEAT.** `NegotiationTaskMetadata.intentId`
715
+ and `.round` are replaced by `seats: Record<string, NegotiationSeatBinding>`
716
+ keyed by intent id (`{ userId, round }`), and `setNegotiationRound` becomes
717
+ `bindNegotiationSeat(taskId, intentId, binding)`. Both sides' IS-A can now
718
+ see and terminate a negotiation, which the loop's
719
+ `ready_for_verdict(reject)` rule requires. The resume input gains a required
720
+ `byUserId`, and the negotiator-scope `intentId` is optional (a seat that has
721
+ not kicked off has no binding). New export: `NegotiationSeatBinding`.
722
+ - **A negotiation's brief is now PER SEAT.** `NegotiationTaskRow.brief: string`
723
+ becomes `briefs: Record<string, string>` keyed by the seat's userId,
724
+ `createNegotiationTask` takes `briefs`, and `setNegotiationBrief` takes the
725
+ seat's `userId`. A seat with no brief has its own agent author one at its
726
+ first turn (`PersonalAgentJudgment.seatBrief`), and `get_negotiation` returns
727
+ the caller's own brief only. The `brief` on the graph's open/resume inputs is
728
+ the INITIATING seat's, never the counterparty's.
729
+ - **`NegotiationGraphDatabase` gains `getPausedNegotiationTasksForIntent`** —
730
+ the signal-scoped read of every paused, unresolved negotiation. Reflect
731
+ reasons over that, not over one round: a negotiation a later kickoff left
732
+ behind keeps its old round, and a round-scoped read hid it from every future
733
+ verdict.
734
+ - **`NegotiationGraphDatabase.getIntentNegotiationRound` returns
735
+ `kickoffStartedAt`** alongside `round` and `roundSize`, and
736
+ `bumpIntentNegotiationRound` must stamp it in the same write. A marker set
737
+ with a null size is the one signature of a kickoff that died mid-round;
738
+ inferring that from the null size alone matched every intent that predates
739
+ round stamping.
740
+ - **`ToolDeps`/`McpToolDeps` gain `matchesReady`**, which every host must set:
741
+ the OpportunityGraph `tool.factory` builds ends its matches_ready edge at
742
+ `END` without it, so a chat- or MCP-run discovery persists matches nobody is
743
+ woken for.
744
+ - **`PersonalAgentDeps` gains `wakeForMatches`** — the agent wakes its own
745
+ signal again for a discovery batch that landed after the turn read its match
746
+ list.
747
+ - **The retired `queueNegotiateExisting` host callback is removed** from
748
+ `ToolDeps` and `OpportunityGraphFactory`. Approving the final introducer
749
+ gate emits `matches_ready` for the source participant's bound signal; it
750
+ never directly opens or resumes a negotiation.
751
+
752
+ - **AgentGraph: one PersonalAgent, routed on the shape of its input.** New
753
+ `PersonalAgentGraphFactory` — `{ userId }` is global (a graph-level input
754
+ error, deferred), `{ userId, intentId, event: 'user_message' | 'matches_ready'
755
+ | 'all_paused' }` is the intent scope (IS-A), `{ userId, intentId,
756
+ negotiationId }` is one negotiator turn. `matches_ready` and `all_paused`
757
+ are ONE node — look at the state, maybe ask, else act — differing only in
758
+ what ACT does. IS-A's verbs are `message_user`, `ask`, `kickoff`, `promote`,
759
+ `reject`, `note_dossier`, `retire_dossier`, `accept_opportunity`; there is
760
+ no `wait`. Asking BLOCKS acting: a turn that asks executes no verdicts and
761
+ starts no negotiations. The host implements the ports (signal DM, dossier,
762
+ act ledger, reply transport, the owner's accept path, matches list).
763
+ - **The interim `NegotiationAuthor` is deleted.** `NegotiationGraphDeps.author`
764
+ is now a required `NegotiationTurnAuthor` port taking ids only
765
+ (`{ negotiationId, userId, intentId }`); production binds it to the
766
+ PersonalAgent in negotiation scope, which reads the brief and thread itself.
767
+ Removed exports: `NegotiationAuthor`, `NegotiationAuthorInput`.
768
+ - **Discovery no longer opens negotiations.** The opportunity graph's
769
+ `negotiate` node is replaced by a `matches_ready` node that emits ONE event
770
+ per signal per persisted batch through the new `MatchesReadyFn` host
771
+ callback; the signal's PersonalAgent decides whether to reach out at all.
772
+ `OpportunityGraphFactory`'s sixth constructor argument changes from
773
+ `negotiationGraph` to `matchesReady`, and `ToolFactory`/`ToolDeps` gain
774
+ `matchesReady`. The tool factory no longer builds a second, reflect-less
775
+ negotiation graph: without the host's own composition there is no
776
+ negotiation graph in that context at all.
777
+ - **The all-paused → reflect trigger is gated on a round-size stamp.**
778
+ `NegotiationRoundReflectJobData` gains `userId` (the signal's owner, so the
779
+ consumer can invoke the PersonalAgent). `NegotiationGraphDatabase` gains
780
+ `getNegotiationTasksForIntentRound`, `getIntentNegotiationRound` and
781
+ `stampIntentNegotiationRoundSize`, and `bumpIntentNegotiationRound` must now
782
+ CLEAR the size stamp. Until kickoff stamps the size — after every parallel
783
+ open has settled — the check is a no-op, so an early first pause can no
784
+ longer dedupe away the round's genuine reflect. New export:
785
+ `maybeEnqueueRoundReflect`.
786
+
787
+ ### Added
788
+
789
+ - `isSafeAgentMessageProse`, the identifier-leak gate every piece of
790
+ agent-authored prose passes before it is persisted or streamed.
791
+ - `chunkReplyText` and `PERSONAL_AGENT_REPLY_FALLBACK`, moved from the host
792
+ with the reply stage.
793
+
794
+ ## 31.0.0 - 2026-08-24
795
+
796
+ ### Breaking
797
+
798
+ ### Fixed
799
+
800
+ - **`NegotiationGraph`'s `resolve` no longer writes over an already-terminal
801
+ opportunity status.** An owner verdict (Radar skip/accept,
802
+ `PATCH /opportunities/:id/status`, the DM's accept/reject tools) writes
803
+ `accepted` / `rejected` itself — a user action outside the negotiation loop
804
+ by design — and then calls `resolve` to CLOSE the negotiation, because a
805
+ terminal opportunity whose task stays `working` holds its round open forever
806
+ and the round's reflect job never fires. Rewriting the status inside
807
+ `resolve` would have downgraded that `accepted` back to `pending` and
808
+ re-fired the actionable notification for a match the owner had already
809
+ accepted.
810
+
811
+ ## 30.0.0 - 2026-08-24
812
+
813
+ ### Changed
814
+
815
+ - **One PersonalAgent persona.** The signal, onboarding, and negotiator chat
816
+ personas collapse into a single `createPersonalAgentPersona(identity)`
817
+ factory with `PERSONAL_AGENT_PERSONA_ID = 'personal'`. What a turn may do is
818
+ derived from the session's resolved scope context, never from a persona id;
819
+ the onboarding prompt/toolset is a fragment selected by incomplete-onboarding
820
+ session state on truly unscoped sessions only. Removed exports:
821
+ `SIGNAL_PERSONA_ID`, `createSignalPersona`, `ONBOARDING_PERSONA_ID`,
822
+ `createOnboardingPersona`, `NEGOTIATOR_PERSONA_ID`, `PersonalAgentChat`,
823
+ `PersonalAgentChatDeps`. The negotiator persona (prompt, chat toolset, and
824
+ its `remember`/`forget` chat tools plus the `negotiatorMemoryTools` host
825
+ port) is deleted outright: every intent-scoped DM turn is IntentAgent-owned
826
+ host-side, so no chat persona exists for that scope. Tool allowlists and
827
+ narrowing are unchanged in content.
828
+
829
+ ## 29.0.0 - 2026-08-23
830
+
831
+ ### Breaking
832
+
833
+ - **NegotiationGraph rewritten as a single write path.** Every write to a
834
+ negotiation now goes through one graph, routed on the shape of its invoke
835
+ input — no `operationMode`: `{ opportunityId, brief, intentId }` opens,
836
+ `{ negotiationId, brief }` resumes, `{ negotiationId, turn }` applies a
837
+ submitted turn (internal, external agent, or timeout, all through the same
838
+ `apply` sink), `{ negotiationId, pause: 'counterparty_silent' }` is a
839
+ timeout, `{ negotiationId, verdict: 'pending' | 'reject' }` is the only
840
+ terminal write, `{ negotiationId }` reads.
841
+ - **The negotiator no longer terminates a negotiation.** `IndexNegotiator`
842
+ and its stances, deadlock shift, checklist gate, conclusion floor, decline
843
+ law, copy-loop guard, turn cap and park window as *outcomes* are deleted.
844
+ A turn is now one of `outreach | counter | question` (continue) or
845
+ `pause(counterparty_silent | needs_principal | ready_for_verdict, payload)`.
846
+ There is no `accept`, `decline`, or `withdraw` on the turn surface — a side
847
+ that wants out pauses `ready_for_verdict(reject)`. `resolve` (writing
848
+ `pending`/`reject` to the opportunity) is the only way a negotiation ends,
849
+ and nothing calls it yet in this release; negotiations pause and wait until
850
+ the caller that will do so (IS-A / AgentGraph) lands.
851
+ - **The interim internal turn author is `NegotiationAuthor`**, a single
852
+ structured-output call constrained to the verb schema in
853
+ `negotiation.turn.ts`, prompted from the brief and the thread so far. It
854
+ replaces `IndexNegotiator` for this release only; AgentGraph replaces it in
855
+ turn.
856
+ - **The A2A conversation is per negotiation, not per pair.** A negotiation is
857
+ its own conversation and its own task. There is no seeded prior-pair
858
+ dialogue, no `priorAttribution`, no conversation lock.
859
+ - **`respond_to_negotiation` takes a turn, not an accept/decline/withdraw
860
+ action.** External agents (Hermes, MCP) submit the same verbs as the
861
+ internal author, validated the same way. `consult` and the second
862
+ `ask_user` park are removed; an external agent needing its principal
863
+ submits `pause(needs_principal, …)` like everyone else.
864
+ - **Removed exports**: `IndexNegotiator`, `negotiateCandidates`,
865
+ `NegotiationGraphFactory`'s old constructor shape (now a single
866
+ `NegotiationGraphDeps` object), `UserNegotiationContext`,
867
+ `NegotiationAction`, `NegotiationSeat`, `NegotiationConsultationReason(Schema)`,
868
+ `resumeParkedNegotiation`, `NegotiationAnswerConsumptionPorts`,
869
+ `createNegotiationAnswerTools`, `NegotiationCounterpartyBinding`,
870
+ `expectedNegotiationSpeaker`, `negotiationScopeKey`,
871
+ `NegotiationContinuationTimeoutIdentity`, `AMBIENT_PARK_WINDOW_MS`,
872
+ `ASK_USER_WINDOW_MS`, `ASK_USER_LOCK_SLACK_MS`,
873
+ `NEGOTIATION_MAX_TURNS_CHAT`, `countOpenPreContactConsults`,
874
+ `PreContactConsultTaskRow`, `InChatNegotiationQuestionDelivery`, and the
875
+ negotiation checklist/deadlock/stance/consultation-policy modules.
876
+ - **New exports**: `NegotiationTurnSchema` and its verb/pause-reason/verdict
877
+ types, `NegotiationAuthor`, `negotiationRoundReflectJobId` and
878
+ `NegotiationRoundReflectEnqueueFn` (the all-paused → reflect trigger — the
879
+ reflect consumer itself is a stub until AgentGraph lands), the rewritten
880
+ `NegotiationGraphDatabase` port (`brief` is now a dedicated field;
881
+ `metadata` carries `intentId`/`round`/`pause`).
882
+ - **`OpportunityGraph`'s `negotiateNode`** now invokes
883
+ `{ opportunityId, intentId, brief }` for every persisted opportunity — no
884
+ selection, no cap. This release's brief is a minimal deterministic string
885
+ built from the trigger intent; IS-A authors real briefs in the next
886
+ release. `negotiateCandidates`, `compensateTasklessNegotiatingOpportunity`,
887
+ the three hand-built `UserNegotiationContext` builders, and the
888
+ `negotiate_existing` operation mode are all deleted.
889
+ - **In-flight negotiations from before this release are not migrated.** The
890
+ negotiation task's shape changed (per-negotiation conversation, dedicated
891
+ `brief` column, new `metadata` shape); old rows are orphaned, not read by
892
+ the new graph.
893
+
894
+ ## 28.1.0 - 2026-08-23
895
+
896
+ ### Changed
897
+
898
+ - **A pre-contact consult that comes back `ok` now decides the opening
899
+ instead of merely offering the agent another draft.** Previously, once the
900
+ client answered the one question the initiator paused to ask, the resumed
901
+ turn-0 decision was entirely re-drafted: an agent that still held a
902
+ withdraw-worthy concern it never asked the client about (e.g. a location
903
+ preference read from the profile rather than the signal) could withdraw
904
+ anyway, seconds after the client answered the thing it did ask, with the
905
+ counterparty never contacted. Now, if the resumed turn drafts `withdraw`
906
+ and the dimension actually asked about reconciled to `ok`, the graph
907
+ RE-ISSUES the turn once — a fresh model call, explicitly told the answer
908
+ settled the thing it asked and that withdrawing on an unasked concern is
909
+ not available now — and runs the result through every gate the first draft
910
+ faced, rather than rebinding the withdraw's own action: a rebind would have
911
+ shipped that draft's message and reasoning (written to argue against the
912
+ match) verbatim as the opening, both to the counterparty's agent and in the
913
+ web transcript. An unasked concern belongs in the exchange with the
914
+ counterparty's agent, not in a quiet screen-out the client was never asked
915
+ to weigh in on. A `conflict` or still-`unknown` answer leaves the withdraw
916
+ standing, unchanged; a re-issue that withdraws again lands on the same
917
+ quiet `screened_out` outcome.
918
+
919
+ ## 28.0.0 - 2026-08-22
920
+
921
+ ### Removed
922
+
923
+ - **BREAKING: background enrichment and `user_contexts` are gone; profile
924
+ saves decompose straight into premises.** `EnrichmentRunInput`,
925
+ `EnrichmentRunRecord`, and `UserContextGenerator` are off the barrel — the
926
+ enrichment MCP tools are prefill-only (`research_profile`) now, and
927
+ identity mutation happens through profile saves and REST onboarding
928
+ endpoints, not agent-driven `create_user_context`/`confirm_user_context`.
929
+ - **BREAKING: `EnrichmentGraphFactory` is query-only.** `write`/`generate`
930
+ operation modes, `decompose_premises`, scraping, and Chat-API
931
+ auto-enrichment are gone from the graph — it now only answers "does this
932
+ user have an enriched profile" (`operationMode: 'query'`). The constructor
933
+ narrows to `(database)`; `scraper`, `enricher`, and `premiseGraph` are no
934
+ longer accepted. `EnrichmentGraphDatabase` narrows to
935
+ `getProfile | getProfileByUserId | getPremisesForUser`.
936
+
937
+ ### Added
938
+
939
+ - **`PremiseGraphFactory` gains a `decompose` operation mode**: given
940
+ `{ userId, input }` (free text — chat, bio, or profile fields), it
941
+ extracts individual premises via `PremiseDecomposer`, applies any
942
+ retractions and bio revision the decomposer detects, and creates each
943
+ premise through the normal create pipeline (analyze → embed → dedupe →
944
+ persist → index). This replaces the removed enrichment-graph write path as
945
+ the one way host code turns free text into premises.
946
+ `PremiseGraphDatabase` gains `getUser` and `updateUser`.
947
+
948
+ ## 27.0.0 - 2026-08-22
949
+
950
+ ### Changed
951
+
952
+ - **Discovery evaluates its whole candidate pool and surfaces at least 10
953
+ matches when the pool allows it.** Retrieval limits were raised
954
+ (`LIMIT_PER_STRATEGY` 30→80, `PER_INDEX_LIMIT` 80→160) and the intent path
955
+ re-runs its search with no similarity floor once when the deduped pool has
956
+ fewer than `DISCOVERY_MIN_MATCHES` (10) distinct users. Evaluation now
957
+ scores the entire pool (capped at 80 by rank) in one parallel round instead
958
+ of batching 25 at a time with an early stop on the first passing batch —
959
+ pass rate does not track similarity rank, so batching was stranding real
960
+ matches behind an over-scored head cluster. Every passing candidate is
961
+ returned uncapped; when fewer than 10 pass, the run fills the rest with the
962
+ best-scored rejected candidates (tiebroken by similarity), persisted with
963
+ their real score. `rankingNode` no longer defaults to a 20-item limit —
964
+ only a caller-supplied `options.limit` cuts the list now.
965
+ - `not_accepted` evaluator verdicts now carry the model's actors under
966
+ `returnAll` (previously always `[]`) so a rejected candidate can be used as
967
+ a fill; guard drops (`incomplete_actors`, `unsupported_claim`) still carry
968
+ none and are never fills.
969
+
970
+ ### Removed
971
+
972
+ - **BREAKING: the `continue_discovery` operation mode is gone**, along with
973
+ the batched-evaluation continuation it existed for: `remainingCandidates`
974
+ (state field and graph output), the `evaluation_bound` trace entry, and
975
+ `'evaluation_bound_reached'` / `unevaluatedCandidates` on
976
+ `OpportunityDiscoverySummary`. Evaluation no longer batches or stops early,
977
+ so there is nothing left to page into.
978
+
979
+ ## 26.0.0 - 2026-08-22
980
+
981
+ ### Changed
982
+
983
+ - **BREAKING: the intent graph routes on the shape of its input, not an
984
+ `operationMode` flag.** `operationMode` is gone from the graph's invoke
985
+ input. Callers now signal intent by which fields they set:
986
+ `inputContent` alone creates; `inputContent` + `targetIntentIds` is an
987
+ explicit update; `targetIntentIds` + `archive: true` expires; `targetIntentIds`
988
+ + `status` pauses/resumes; `proposalId` (+ `description`, `networkId`)
989
+ confirms a stored proposal; none of the above reads. `dryRun: true` replaces
990
+ the old `propose` mode. `targetIntentIds` alone, or more than one of
991
+ {content, archive, status, proposalId} set at once, is now a graph-level
992
+ input error rather than a silent no-op or an implicit default.
993
+ - **BREAKING: `IntentGraphDatabase` gained required members.** Archive now
994
+ performs its full cleanup (network-association removal, referencing
995
+ opportunity expiry) itself, and the graph owns pause/resume and
996
+ proposal-confirmation persistence. Hosts implementing this interface must
997
+ add `deleteIntentIndexAssociations`, `expireOpportunitiesByIntentActor`,
998
+ `transitionIntentLifecycle`, `compensateFailedResume`, `getProposalForOwner`,
999
+ `revisePendingProposal`, and `confirmProposalIntent`.
1000
+ - **BREAKING: `IntentGraphQueue` gained `addResumeDiscoveryJob`.** The graph
1001
+ enqueues resume discovery directly (and compensates back to `PAUSED` on a
1002
+ failed enqueue) instead of leaving that to a host-side event hook.
1003
+
1004
+ ### Added
1005
+
1006
+ - `IntentLifecycleStatus`, `TransitionLifecycleResult`, `IntentProposalRecord`,
1007
+ `ReviseIntentProposalInput`, and `ConfirmProposalResult` are now exported
1008
+ from the package barrel.
1009
+
1010
+ ### Removed
1011
+
1012
+ - The inferrer's profile-fallback path (`allowProfileFallback`, content-less
1013
+ inference) had no live caller and is gone along with the `delete` operation
1014
+ mode it was keyed on.
1015
+
1016
+ ## 25.0.0 - 2026-08-21
1017
+
1018
+ ### Removed
1019
+
1020
+ - **BREAKING: principal reachability no longer gates consultation.** A seat's
1021
+ agent may always `ask_user` its own client; whether anyone is behind the
1022
+ account is not the author's concern. Gone: `UserNegotiationContext.principalUnreachable`,
1023
+ the optional `isPrincipalUnreachable` host port on `NegotiationGraphDatabase`,
1024
+ the `principal_unreachable` ask-inadmissibility reason, the
1025
+ `PRINCIPAL_UNREACHABLE_*` prompt rules, the init-node stamp and the
1026
+ detail-reader / `get_negotiation` live re-stamp. Seed personas (`.test`
1027
+ mailboxes) negotiate exactly like real users now — in the sandbox four of
1028
+ five personas had been silenced by construction, and the question flow
1029
+ could not be observed for them.
1030
+
1031
+ ## 24.0.0 - 2026-08-21
1032
+
1033
+ ### Removed
1034
+
1035
+ - **BREAKING: every environment feature gate is gone, and what each environment
1036
+ was running became the code's behaviour.** No accessor in this package reads
1037
+ `process.env` for a behaviour decision any more; configuration narrows to
1038
+ credentials, endpoints, and the model/log values the host supplies.
1039
+
1040
+ Off the barrel: `configuredAskUserEnabled`, `askUserAnswerWindowMs`,
1041
+ `discoveryEvaluatorMinScore`, `negotiationConsultationPolicyMode`,
1042
+ `negotiationEvidenceQuestionsMode`, `poolQuestionsRanking`,
1043
+ `poolQuestionsMiningMode`, `poolQuestionsMode`, `poolQuestionsPushMode`,
1044
+ `poolQuestionsStampNewborn`, `poolQuestionsVisitTrigger`,
1045
+ `POOL_VISIT_MINING_DEBOUNCE_MS`, `isIntroducerDiscoveryEnabled`,
1046
+ `runIntroducerDiscovery`, `selectContactsForDiscovery`,
1047
+ `shouldRunIntroducerDiscovery`, `IntroducerDiscoveryDatabase`,
1048
+ `IntroducerDiscoveryQueue`, `INTRODUCER_DISCOVERY_SOURCE`,
1049
+ `ContactWithIntents`, `MAX_CONTACTS_PER_CYCLE`, `MAX_CANDIDATES_PER_CONTACT`.
1050
+ The five `poolQuestions*` accessors had no callers at all — they read
1051
+ variables retired with the card question generators.
1052
+
1053
+ Behaviour now fixed in code: negotiations stamp protocol `v2`; `ask_user` and
1054
+ the deterministic consultation policy are on; deadlock-shift is on; the
1055
+ negotiator drafts in the `skeptic` stance (`advocate` and `evaluator`, and the
1056
+ `stance*` predicates that distinguished them, are gone); negotiators receive
1057
+ only each participant's exact opportunity-bound signal; HyDE generates under
1058
+ `frame-v1`; candidate evaluation runs in parallel; retrieval floor is `0.20`
1059
+ and the evaluator score floor is `40`; the two question miners are pinned to
1060
+ `shadow`.
1061
+
1062
+ - **BREAKING: profile matching is removed — discovery is intent-to-intent only.**
1063
+ Premise-to-premise, context-to-context and context-to-intent strategies are
1064
+ gone, along with the `profileCorpus` hint on the embedder interface. Premises
1065
+ remain as an entity; they are no longer a matching corpus.
1066
+
1067
+ - **BREAKING: introducer discovery is removed** — the queue, the maintenance-graph
1068
+ node, and the on-behalf-of persistence path (`onBehalfOfUserId` is off the
1069
+ opportunity graph state; nothing assigned it once the queue was gone). The
1070
+ `introducer_discovery` opportunity source value is kept as read-only history:
1071
+ nothing stamps it, and rows created before this release still carry it.
1072
+
1073
+ - **BREAKING: the negotiation outreach screen gate is gone.** `NegotiationScreener`
1074
+ is off the barrel, and the graph is now `init → turn* → finalize` — every
1075
+ negotiation that reaches `init` proceeds to its first turn. The gate was one
1076
+ structured LLM call before the first turn that could return `pass` and end the
1077
+ negotiation as `screened_out` with the counterparty never contacted.
1078
+
1079
+ It was removed because questions come from parked negotiations: a negotiation
1080
+ screened out never runs a turn, so it never stalls, never parks, and can never
1081
+ produce a user-facing question. The gate silently removed matches from the one
1082
+ pipeline that generates them.
1083
+
1084
+ Also gone: `negotiation.graph.screen.ts` and `negotiation.screen.contracts.ts`
1085
+ in full (`NEGOTIATION_SCREEN_MODES`, `NegotiationScreenMode`, `SCREEN_MODE`,
1086
+ `ScreenDecisionSchema`, `ScreenDecision`, `ScreenDecisionRecord`,
1087
+ `blocksNegotiationBeforeFirstTurn`), the `screener` dep on
1088
+ `NegotiationGraphDeps`, the `screenDecision` graph-state field, the
1089
+ `routeAfterScreen` edge, the optional `setTaskScreenDecision` port method on
1090
+ `NegotiationGraphDatabase`, the `negotiationScreener` model-config entry, and
1091
+ the `screenedOut` field of `ConsultationEligibilityInput` (always false with
1092
+ no gate to set it). `NegotiatorMemoryScope` narrows to `"turn"`, and
1093
+ `renderNegotiatorMemorySection` loses its options argument — the
1094
+ `memoryHintsInstruction` it carried existed only for the screen prompt.
1095
+
1096
+ ### Changed
1097
+
1098
+ - **`negotiationHasMadeContact` moved to `negotiation.protocol.ts`.** Not a
1099
+ screening helper: finalize and the turn node both call it for live turn logic
1100
+ (the IND-564 opening-`withdraw` guard, and the `screened_out` label). It lived
1101
+ in the screen module by accident of history. Package-internal, so no consumer
1102
+ import changes.
1103
+
1104
+ - **`screened_out` now has exactly one live writer** — the IND-564 opening-turn
1105
+ `withdraw` guard, where the acting agent refuses before anything is sent.
1106
+ `outcome.reasoning` for such a run is unconditionally the withdrawing turn's
1107
+ reasoning; there is no screen record left to prefer over it.
1108
+
1109
+ ### Read-only history (deliberately kept)
1110
+
1111
+ - The `screened_out` outcome reason, `tasks.metadata.screenDecision`, and the
1112
+ owner-only `screenDecision` API projection. Nothing writes the metadata key
1113
+ any more, but negotiations that ran before this release still carry one and
1114
+ must still render for their initiator. Each survivor is marked as such at its
1115
+ definition.
1116
+
1117
+ ## 23.6.4 - 2026-08-21
1118
+
1119
+ ### Added
1120
+
1121
+ - **`buildAgentSelfIntroduction` is now actually exported.** 23.6.3's entry
1122
+ named it as part of the new surface, but it was only reachable from inside
1123
+ the package — the three chat personas import it directly. It is now on the
1124
+ barrel (`buildAgentSelfIntroduction`, `AgentIdentityOptions`), which is what
1125
+ makes that claim true for consumers.
1126
+
1127
+ ### Changed
1128
+
1129
+ - **`buildAgentSelfIntroduction`'s `userName` is optional.** Additive: every
1130
+ existing caller passes it and gets the same sentence. Absent, the builder
1131
+ emits `You are <name>, <role>.` or, with no name either, `You are <role>.` —
1132
+ the form a surface needs when its role phrase already says whose agent this
1133
+ is and it never resolves a client display name. The API's IntentAgent loop
1134
+ is the first such caller.
1135
+
1136
+ ## 23.6.3 - 2026-08-21
1137
+
1138
+ ### Added
1139
+
1140
+ - **Persona identity + create_intent scope rule (#1479) — the version stamp
1141
+ the change shipped without.** Every chat persona now introduces itself as
1142
+ the user's own agent: `buildAgentSelfIntroduction`, plus
1143
+ `createSignalPersona` / `createOnboardingPersona` factories taking
1144
+ `agentName` the way the negotiator already did. Tool registration gained
1145
+ the scope rule (`isToolAllowedInScope`, `filterToolsForScope`). #1479
1146
+ merged these exports without bumping, so two different export surfaces
1147
+ briefly answered to 23.6.2 on the `rc` tag — this entry gives the new
1148
+ surface its own version.
1149
+
1150
+ ## 23.6.2 - 2026-08-21
1151
+
1152
+ ### Fixed
1153
+
1154
+ - **A premise-matched counterparty is premise-bound — two wrongs stopped
1155
+ agreeing.** A premise-matched opportunity actor carries BOTH keys: `premise`
1156
+ is its own fact, `intent` names the intent it matched AGAINST — the
1157
+ recipient's. Two sites independently preferred `intent` whenever the key
1158
+ existed, and their mistakes agreed with each other: the api's ask-user
1159
+ capture stamped every premise-matched park's `counterpartyBinding` with the
1160
+ recipient's own intent (so the claim's counterparty-liveness check could
1161
+ never pass — observed live as `admission:"invalid"` after #1474/#1475 had
1162
+ already made settle and claim drift-tolerant), and this package's
1163
+ `resolveOpportunityActorBinding` resolved a dual-key actor to that same
1164
+ wrong intent binding — so the re-drive's continuation revalidation
1165
+ (`opportunityActorMatchesBinding` in `negotiateExistingOpportunity`) would
1166
+ have accepted the mis-stamp and refused a corrected premise stamp as
1167
+ `stale_continuation`, one gate after the claim.
1168
+
1169
+ Both flips ship together, mirror-identical: a present `premise` is the
1170
+ binding, `intent` binds only in its absence. Mirror consequence, intended:
1171
+ a dual-key actor no longer matches an intent-kind binding naming its
1172
+ matched-against intent — the gate stops accepting mis-stamped settlements,
1173
+ which already fail the claim's liveness check earlier, so nothing that
1174
+ works today breaks.
1175
+
1176
+ ## 23.6.1 - 2026-08-20
1177
+
1178
+ ### Fixed
1179
+
1180
+ - **An answer beats staleness — drift is logged, never fatal.** Observed live:
1181
+ a client answered her own parked question ("Timing: This week") through the
1182
+ new MCP answer lane, routing succeeded, consumption ran — and the settle
1183
+ returned `lost`, because the signal had been edited twice since the park and
1184
+ the revalidation fence required the world to look exactly as it did at park
1185
+ time. The park became a zombie: still `input_required`, still rendered as
1186
+ "waiting on YOUR answer" by every surface, structurally unanswerable. The
1187
+ design law is explicit: signal edits cascade nothing, and a stale negotiation
1188
+ is solved by ANSWERING its question — the user's answer is the freshest
1189
+ commitment there is, and the resumed turn rebuilds its context from current
1190
+ data anyway.
1191
+
1192
+ The settle's one fence is now two. Coherence stays hard: an answer that does
1193
+ not belong to its park (settlement mismatch, wrong recipient, task no longer
1194
+ parked, a dismiss/timeout settlement won the race) is still refused. Drift
1195
+ stops losing: within a live opportunity and an active signal, the answer
1196
+ settles and resumes regardless of what moved since the park.
1197
+
1198
+ - **The unresumable tail is an explicit proposal, not a silent drop.** When
1199
+ current reality genuinely cannot continue — terminal opportunity or archived
1200
+ signal — the answer is still recorded as heard: settlement result and resume
1201
+ outcome `recorded_unresumable` (additive), the block-consumption result
1202
+ counts it in its own `recorded` array so a `skipped` count can never again
1203
+ hide it, and the implementation retires the park and tells the client the
1204
+ truth, proposing re-discovery under the updated signal — an offer, never an
1205
+ automatic act.
1206
+
1207
+ ## 23.6.0 - 2026-08-20
1208
+
1209
+ ### Added
1210
+
1211
+ - **The MCP surface can now ACT on the question flow, not just see it.** Since
1212
+ 23.5.1 `list_negotiations` says the park — "open question 3, 'Timing'" — to
1213
+ an external client that had no tool to answer it: the answer lane was the
1214
+ negotiator persona's chat-only appended tool, and the owner's verdict levers
1215
+ did not exist on MCP at all. Three tools close the read-and-act gap, all
1216
+ registered on the MCP tool registry surface only:
1217
+
1218
+ - `answer_pending_question(negotiationId, question, answer)` routes the
1219
+ principal's answer to the open question a parked negotiation is waiting on,
1220
+ over the EXISTING `NegotiatorAnswerToolsHost` — the same
1221
+ `readOpenQuestionsForIntent` numbering, the same serialized consumption
1222
+ queue, the same #1432 resume spine. MCP has no pinned intent, so the tool
1223
+ resolves scope from the negotiation the client is looking at: the id the
1224
+ park annotation sits on → the caller's own actor intent on that pairing →
1225
+ the host. The `question` number passes through untouched; it and the park
1226
+ annotation come from one enumeration and cannot drift (the #1470 rule).
1227
+ - `reject_opportunity` / `accept_opportunity` (intentId, numbered
1228
+ counterparty, optional reason in the owner's own words) reuse the
1229
+ negotiator verdict host verbatim — the same Radar Skip/Start-Chat service
1230
+ call, outcome hooks and question retirement in its wake, positions never
1231
+ ids. Capability access is `human_only`: exactly the session-authenticated
1232
+ class the IND-593 owner-provenance binding admits, and the handler
1233
+ re-checks the host-bound provenance so an API-key agent is refused even if
1234
+ the tool were ever mis-listed. Hermes negotiator credentials fail closed as
1235
+ unclassified for all three tools.
1236
+
1237
+ - **`get_negotiation` says the park** — the #1472 incident, one level down: it
1238
+ is the tool the poller prompt says to call FIRST, and on a parked negotiation
1239
+ it narrated a lifecycle built without the park. The detail reader now runs
1240
+ the same canonical park predicate the listing runs (`classifyInflightPark` /
1241
+ `classifyPostStallPark`) over the task and messages it already holds, names
1242
+ the open question through the same shared host record, projects the park
1243
+ top-level and into `lifecycle` (superseding the status label), and — for an
1244
+ external seat that could not see dimensions or `settles` — projects the
1245
+ persisted `askUser` and `checklist` payloads on turns that carry them.
1246
+ Non-parked negotiations render byte-for-byte as before.
1247
+
1248
+ - **`get_negotiation` re-stamps principal reachability from the live read.**
1249
+ The persisted `turnContext` is a park-time snapshot; `ownUser.principalUnreachable`
1250
+ is now corrected in both directions through the host's
1251
+ `isPrincipalUnreachable` port — the same re-stamp REST pickup applies — so an
1252
+ external seat is never told it can consult a principal nobody is behind, or
1253
+ the reverse.
1254
+
1255
+ - **`list_negotiations` can filter for the parked state.** The `status` filter
1256
+ gains `input_required`; `active` and `all` behave exactly as before. A
1257
+ post-stall park lives on a `completed` negotiation and is documented as such
1258
+ rather than smuggled into the status filter.
1259
+
1260
+ ### Fixed
1261
+
1262
+ - **`read_activity_summary` stops counting questions from the retired card
1263
+ table.** Pending question counts now come from the parked negotiations —
1264
+ a mid-flight `input_required` consult naming the owner as recipient, or a
1265
+ post-stall park trailing the authored gap — keyed by the same
1266
+ `negotiation_inflight`/`negotiation` modes the projection already maps to the
1267
+ negotiations domain, so permission inheritance is unchanged. Leftover
1268
+ pending rows in the retired `questions` table contribute nothing; answered
1269
+ history still reads the table, where it legitimately lives.
1270
+
1271
+ - **Honest words where external clients read them.** The negotiations guidance
1272
+ topic, the workflows topic, and `MCP_INSTRUCTIONS` now carry the park stage —
1273
+ what a park is, what the `park` fields mean, and that answering is the only
1274
+ thing that resumes a parked negotiation. The three negotiation tool
1275
+ descriptions state plainly that turns submitted through external surfaces are
1276
+ NOT run through the conclusion floor, decline law, or copy-loop guard: until
1277
+ external write parity ships, the docs must not imply otherwise.
1278
+
1279
+ ## 23.5.1 - 2026-08-20
1280
+
1281
+ ### Fixed
1282
+
1283
+ - **The negotiation listing says the park, from the same record every other
1284
+ answerability surface reads.** Observed live: a client asked her agent "do we
1285
+ have a question?" while a negotiation had sat parked `input_required` on her
1286
+ side for two hours with the open question "Timing: This week". Every 23.5.0
1287
+ surface was correct — the precedence gate found the question, and the
1288
+ prompt's open-questions section named it at position 1. Then the model called
1289
+ `list_negotiations`, which renders lifecycle from OPPORTUNITY STATUS, where
1290
+ the pairing legitimately reads `negotiating`, and which said nothing at all
1291
+ about the park. Holding a static context line saying one thing and a
1292
+ just-executed tool result saying another, it went with the tool: "there are
1293
+ currently no open questions… I am still negotiating with the other agent…
1294
+ nothing for you to decide." Both clauses false at the task level; both
1295
+ faithful to what the tool rendered.
1296
+
1297
+ The listing was the last surface still deriving "what is happening" from a
1298
+ source other than the shared resolver, so the tool and the context could
1299
+ disagree — and the tool wins the model's trust every time. It now carries a
1300
+ `park` on any negotiation that holds one: `waitingOn: "you" | "counterparty"`,
1301
+ and for a park on the client's own side the open question's number and label.
1302
+
1303
+ - **One call, every surface — the answer-openness rule extended to its last
1304
+ holdout.** The question's NUMBER and LABEL come from
1305
+ `NegotiationListingParkHost`, whose host implementation resolves them through
1306
+ the same call the open-questions prompt section and `answer_pending_question`
1307
+ make. The listing does not enumerate anything of its own, so the number the
1308
+ client is shown is the number that routes their answer. A question's
1309
+ `alsoUnblocks` refs carry that same number, since one answer resumes them all.
1310
+
1311
+ - **Whose side a park is on is the canonical predicate, not a second one.**
1312
+ `classifyParkedNegotiation` is split into `classifyInflightPark` and
1313
+ `classifyPostStallPark`, pure over the task and messages a caller already
1314
+ holds; the async function is now the reading half around them and keeps its
1315
+ lazy messages read. The listing calls them with material it already loaded, so
1316
+ park classification costs no extra query and cannot drift from the predicate
1317
+ answer routing uses. Parked-ness is never re-derived from opportunity status.
1318
+
1319
+ - **A park on the counterparty is narrated, never quoted.** It renders as
1320
+ waiting on their side with no question content: that question is not this
1321
+ client's to read.
1322
+
1323
+ ### Changed
1324
+
1325
+ - **`lifecycleLabel` states the park, superseding the status label.** The
1326
+ persona is told to take `lifecycleLabel` as its user-facing wording, and "the
1327
+ agents are still negotiating" is exactly the sentence that became a false
1328
+ "nothing for you to decide". `opportunityStatus` still reports the true
1329
+ status; what it may no longer do is supply the sentence.
1330
+ `connectionState` gains `parked_awaiting_your_answer` and
1331
+ `parked_awaiting_counterparty`, and `buildLifecycleNarration` takes an
1332
+ optional third argument. A negotiation with no park renders byte-for-byte as
1333
+ it did in 23.5.0, and is pinned by a fixture spec.
1334
+
1335
+ - **The tool description and the negotiator prompt both say the two agree.**
1336
+ `list_negotiations` documents `input_required` as a status, documents `park`,
1337
+ and states that the numbers come from the same record the open-questions
1338
+ context section does — so the model has no basis to rank one over the other.
1339
+ It also states that `negotiating` alone never means "nothing is waiting on
1340
+ you". The persona gains one grounding rule saying the same thing.
1341
+ `NegotiationListingParkHost` is optional: without it the listing still says
1342
+ whether a pairing is parked and on whose side, it just cannot name the
1343
+ question's number.
1344
+
1345
+ ## 23.5.0 - 2026-08-20
1346
+
1347
+ ### Added
1348
+
1349
+ - **The owner's verdict has a lane in their own DM.** Observed live: in the
1350
+ negotiator DM for one signal, a client told their agent to reject the
1351
+ counterparty — a pairing parked `input_required`. The agent could not comply.
1352
+ The owner makes exactly three kinds of decision in that room. They ANSWER a
1353
+ question a parked negotiation asked, which `answer_pending_question` gave a
1354
+ lane. They EDIT the signal, which `update_intent` always covered.
1355
+ And they pass a VERDICT on a counterparty, which had no lever at all. So on
1356
+ "reject them" the persona's whole repertoire was to say something back, or to
1357
+ edit the signal instead; the pairing stayed parked and the counterparty
1358
+ stayed live.
1359
+
1360
+ `update_opportunity` is in the negotiator toolset and cannot substitute for
1361
+ either half of this. `admitOpportunityUpdate` blocks a `negotiating` pairing
1362
+ outright, and the IND-593 owner-approval boundary fails closed on the chat
1363
+ surface by design — `createChatTools` binds
1364
+ `{ surface: 'chat', sessionAuthenticated: false }`, and a mediated surface is
1365
+ denied `untrusted_provenance`. The verdict levers that exist are the Radar
1366
+ card's Skip and Start-Chat and the REST endpoints behind them, none of which
1367
+ the client's own agent can reach.
1368
+
1369
+ So `createNegotiatorVerdictTools` adds `reject_opportunity` and
1370
+ `accept_opportunity` to the negotiator persona, on the same pattern
1371
+ `answer_pending_question` set. Appended AFTER the allowlist filter and only in
1372
+ an intent-pinned session with `negotiatorVerdictTools` injected, so they never
1373
+ enter the shared chat-tool registry and the orchestrator and MCP tool listing
1374
+ cannot see them. `NegotiatorVerdictToolsHost` is the whole surface the package
1375
+ knows; the composition root owns everything behind it.
1376
+
1377
+ - **Numbered refs, never ids.** The prompt renders this signal's actionable
1378
+ counterparties as `N. {name} — {state}`, and the tool takes the number. The
1379
+ schema offers no place to put an id and no result string carries one. The rule
1380
+ is `answer_pending_question`'s, for a sharper reason: a ref the model can name
1381
+ is a ref it can get wrong, and a wrong ref here declines the wrong person.
1382
+ The host owns the mapping, and a successful result names WHO the write landed
1383
+ on — so the confirmation the client reads comes from the write rather than
1384
+ from the model's belief about which counterparty it picked.
1385
+
1386
+ - **An optional `reason`, in the client's own words.** Capped at 500 characters,
1387
+ omitted entirely when they gave none. The tool description and the prompt both
1388
+ say it is never to be inferred or written for them.
1389
+
1390
+ ### Changed
1391
+
1392
+ - **The pinned-signal prompt gains a verdict section, and only where the tools
1393
+ exist.** `NegotiatorPromptOptions.actionableCounterparties` renders
1394
+ `## Verdicts {userName} can pass here` plus two tool-reference rows. It says
1395
+ the tool call IS the decision — not the sentence about it, and not an edit of
1396
+ the signal; that a verdict the client did not pass must never be passed for
1397
+ them; that `update_opportunity` is not this lever; and that an accept is one
1398
+ side of two and never a connection. Rendered only in an intent-pinned session
1399
+ with a non-empty list, since that is the only place the tools are registered.
1400
+ Absent or empty leaves the prompt byte-identical to 23.4.0.
1401
+
1402
+ - **Result copy is honest at every status.** `executed` names the counterparty
1403
+ and forbids also editing the signal; `none_actionable` forbids implying a
1404
+ decision was recorded; `unknown_counterparty` states plainly that nothing was
1405
+ decided and re-lists the current set; `already_decided` says whose move it is;
1406
+ `error` forbids describing the pairing as decided. A host that throws is
1407
+ caught and reported as `error` rather than costing the client their turn.
1408
+
1409
+ - **Execution is the path the Radar card already takes, and nothing more.** The
1410
+ host behind the seam runs the SAME owner status update the Skip page calls
1411
+ through `PATCH /opportunities/:id/status`, intent-scoped. No new task-state
1412
+ transition is invented, and the retirement of a dismissed pairing's open
1413
+ question is not re-invoked: `OpportunityEvents.onTransition` already fires the
1414
+ exhaustion evaluator on every committed opportunity status write, owner reject
1415
+ included, so a rejected pairing's question dies with it because that arrow was
1416
+ already there.
1417
+
1418
+ ## 23.4.0 - 2026-08-20
1419
+
1420
+ ### Added
1421
+
1422
+ - **A checklist dimension now declares whose fact it is, and the floor reads
1423
+ it.** Observed live: turn 2 of a sandbox negotiation, initiator seat, a
1424
+ checklist whose two open dimensions were "Query Match: Generative Story
1425
+ Games" and "Query Match: Live Operations" — both about the COUNTERPARTY's
1426
+ work. The agent drafted `question` to the counterparty's agent, which is the
1427
+ protocol's own prescribed move. The conclusion floor (23.3.0) saw a non-ask
1428
+ turn with an askable unknown standing, took `askableUnknowns[0]`, and coerced
1429
+ the turn into a guaranteed `ask_user` — so the client was asked, in her own
1430
+ DM, whether the other person works on generative story games.
1431
+
1432
+ Nothing was wrong with the floor's logic; the logic simply could not see the
1433
+ distinction. "Askable" was `unknown ∧ unasked ∧ budget ∧ reachable ∧ wiring`,
1434
+ and no term in that conjunction knows WHOSE fact is missing. That judgment
1435
+ lived only in the agent — which is exactly the judgment the guarantee exists
1436
+ to override. Where the first unknown happens to be the client's own the
1437
+ guarantee is right; where it is the counterparty's it converts the agent's
1438
+ correct move into a wrong one.
1439
+
1440
+ So the judgment becomes a declared, mechanical property, following the same
1441
+ pattern answerhood set: made ONCE, at authoring, by the agent writing the
1442
+ checklist, then read mechanically forever. `ChecklistItem` gains
1443
+ `settles: 'client' | 'counterparty' | 'either'`, frozen with the dimension —
1444
+ `reconcileChecklist` copies it through untouched, because it is a judgment
1445
+ about the world rather than about the evidence, and a re-scorable one would
1446
+ be a switch an agent could use to turn the floor off for a dimension it would
1447
+ rather not be asked about.
1448
+
1449
+ ### Changed
1450
+
1451
+ - **`askableUnknowns` filters on it, so both halves of the floor do.**
1452
+ `assessConcludeAdmissibility` now admits a verdict whose only open dimensions
1453
+ are the counterparty's to state — those are resolved by dialogue with the
1454
+ other agent, or carried, which is what the verdict law has always said about
1455
+ unknowns — and the part-2 guarantee picks only from what survives the filter.
1456
+ Order within the surviving set is still the checklist's own.
1457
+ - **The five-part ask rule gains the mechanical half of its rule 3.** An
1458
+ agent-drafted ask naming a `settles: 'counterparty'` dimension is refused as
1459
+ `counterparty_authoritative`, with the same honest-refusal logging as its
1460
+ siblings. Rule 3 was prompt-only until now; the incident proves the
1461
+ mechanical half matters in both directions — the same field that stops the
1462
+ floor manufacturing the wrong ask stops an agent drafting it.
1463
+ - **The prompt asks for the field where the model authors, and reads it back on
1464
+ every row.** The authoring instruction and the checklist protocol rule both
1465
+ require `settles` per dimension in the vocabulary they already use ("a thing
1466
+ only your client can answer" / "the counterparty's to state"); the rendered
1467
+ checklist labels each row with it, because the agent re-scoring a frozen
1468
+ checklist did not necessarily author it. The conclude-floor re-issue states
1469
+ that counterparty-settled dimensions are not what it is about.
1470
+
1471
+ ### Fixed
1472
+
1473
+ - **The generation seam states the field and repairs it, rather than refusing.**
1474
+ Following 23.3.2's split: `ChecklistDraftGenerationSchema` requires `settles`
1475
+ on every dimension — so it renders inside the emitted JSON schema's `required`
1476
+ list, and a field the model need not produce is one it skips — while a
1477
+ `preprocess` fills a missing or unrecognised value with `either` before the
1478
+ enum ever sees it. A `.catch()` on the field would have read as optional to
1479
+ zod and dropped out of `required`, which is why the repair wraps the object.
1480
+ A refusal here throws inside the structured-output call and takes the whole
1481
+ turn with it.
1482
+ - **Legacy checklists are unchanged.** Persisted turns written before the field
1483
+ existed carry no `settles`, and `normalizeSettles` reads them back as
1484
+ `either` — which stays ASKABLE. The default direction is the whole safety
1485
+ argument: `counterparty` would let one unfilled field silently retire the
1486
+ conclusion floor for a negotiation, so no authoring failure, legacy turn, or
1487
+ repaired value can switch it off wholesale. An unrecognised value on the
1488
+ persisted shape reads back as absent rather than failing the item, because
1489
+ that shape also parses the drafts of externally dispatched agents, which
1490
+ never see the generation schema — a whole re-scored checklist discarded over
1491
+ one misspelled marking is the larger loss.
1492
+
1493
+ ## 23.3.2 - 2026-08-20
1494
+
1495
+ ### Fixed
1496
+
1497
+ - **A question the model wrote itself must not die at the schema that asked for
1498
+ it.** For the first time, the negotiator drafted its own `ask_user` — 23.3.1's
1499
+ re-issue prompt worked and no floor coercion was needed — and the draft was
1500
+ refused by the very schema it was drafted into, twice over. `guaranteed`, the
1501
+ conclusion floor's own mark, was an optional field on the payload handed to
1502
+ the model; the model filled it with `false`, and `z.literal(true)` rejects
1503
+ `false`. The authored `question.title` carried a silent 12-character cap; the
1504
+ model wrote a real 40-character title. Both refusals throw INSIDE the
1505
+ structured-output call, so the turn failed with nothing persisted, the retry
1506
+ was refused the same way, the ask was coerced to a counter, the dialogue ran
1507
+ to the cap and declined. The question was never delivered.
1508
+
1509
+ Two seams were sharing one declaration, and they have opposite jobs. There
1510
+ are now two. `AskUserGenerationSchema` is what a model is ALLOWED TO SAY: it
1511
+ OMITS `guaranteed` entirely — a field only the graph may write should never
1512
+ be offered to the model, rather than offered and defended against afterwards
1513
+ — and it discards unrecognised keys instead of failing the turn over them,
1514
+ since this parse is what produces the object that gets persisted. The
1515
+ persisted `AskUserPayloadSchema` is unchanged: it keeps `guaranteed` and
1516
+ stays `.strict()`, because the record is where the floor's mark is read back
1517
+ out of and where a stray key would do damage. The turn node still strips an
1518
+ agent-claimed mark — externally dispatched personal agents draft against the
1519
+ permissive shape, not the generation schema — so the floor remains the only
1520
+ writer whichever way a draft arrives.
1521
+
1522
+ Every renderer cap on a question now REPAIRS instead of refusing, which is the
1523
+ protocol's own philosophy (`normalizeChecklistItem` repairs toward `unknown`;
1524
+ the anti-echo guard repairs toward honesty) applied where it was missing: a
1525
+ title, prompt, option label or description that runs long is truncated on a
1526
+ word boundary, and a fifth option is dropped. The emitted JSON schema is
1527
+ unchanged, so the model is still TOLD each cap — repair is only what happens
1528
+ when it ignores one — and the conclusion-floor re-issue now names the title
1529
+ cap where it tells the agent to write the question itself. Where nothing can
1530
+ be honestly repaired (one option is not a choice), the generation schema
1531
+ degrades the authored question to absent and keeps the ask: an ask with no
1532
+ wording falls back to the server template, a path the floor's own guaranteed
1533
+ ask already walks. Losing the wording is a smaller loss than losing the turn.
1534
+
1535
+ ## 23.3.1 - 2026-08-20
1536
+
1537
+ ### Fixed
1538
+
1539
+ - **A task's FIRST turn can park.** The first `ask_user` this system ever fired —
1540
+ produced by 23.3.0's conclusion floor, on the first turn of a resumed
1541
+ session — died at the park with "Ask-user material binding is no longer
1542
+ valid", and the negotiation stalled. The binding capture locks the task row
1543
+ `state = 'working'` and refuses anything else; the graph announced `working`
1544
+ only at the END of a completed turn, so on a task's first turn the row still
1545
+ held its creation state (`submitted`) and no first-turn park could bind. The
1546
+ turn was already on the record when it threw, which makes the failure
1547
+ unretryable — so the whole opportunity ended as `agent_error`.
1548
+
1549
+ The turn node now announces `working` before the capture rather than only
1550
+ after the turn, carrying the same continuation-execution fence as every other
1551
+ state write. The fence in the adapter is unchanged: `working` is the true
1552
+ precondition for a settlement coordinate, and what was wrong was the
1553
+ sequencing, not the check. The flip sits at the park rather than at the top of
1554
+ the turn deliberately — a task that dies before putting anything on the record
1555
+ stays reclaimable under the watchdog's ten-minute `submitted` rule instead of
1556
+ disappearing under the twelve-hour `working` one — and the end-of-turn flip
1557
+ stays for every path that does not park.
1558
+
1559
+ Latent since the turn-0 pre-contact consult shipped and never once hit,
1560
+ because no first-turn ask was ever drafted; the conclusion floor made them
1561
+ routine, a run-existing continuation's turn 0 being the common case. The
1562
+ twenty-five specs covering this loop all missed it because their database
1563
+ stubs accepted any task state at capture time — the new spec's stub asserts
1564
+ the state exactly as the adapter does, on the agent-drafted ask, the
1565
+ floor-guaranteed one, the pre-contact consult and a later-turn ask alike.
1566
+
1567
+ ## 23.3.0 - 2026-08-20
1568
+
1569
+ ### Changed
1570
+
1571
+ - **A verdict has a floor under it: an askable unknown outranks a conclusion.**
1572
+ Every stage of the flow — signal, discovery, agents talking, match, meet — was
1573
+ verified working except one arrow: the agent asking its own client something
1574
+ only that client can settle. In a week of live traffic it fired zero times,
1575
+ against 23 policy-recognized consultation moments. The reason is structural
1576
+ rather than a bug: the model always had a cheaper exit than asking — assume the
1577
+ unknown away and accept, put the question to the counterparty who does not hold
1578
+ the answer, or simply conclude — and it took one every time. #1463 closed one
1579
+ of those exits (a decline with no conflict behind it). This closes the rest.
1580
+
1581
+ `assessConcludeAdmissibility` makes a drafted TERMINAL verdict — `accept`,
1582
+ `decline`, `reject`, and the initiator's `withdraw` — inadmissible while the
1583
+ checklist holds a dimension scored `unknown` that this principal could still be
1584
+ asked about, reported as `unknowns_askable` with the dimension names. "Askable"
1585
+ is the conjunction the turn node already computes as `askUserAvailable` (v2,
1586
+ wiring up, budget left, ask-rounds cap unreached, principal reachable,
1587
+ non-final turn) with the checklist's own part (unknown, and the topic unasked
1588
+ in this negotiation). Every one of those conditions failing REOPENS the
1589
+ verdict, which is what keeps the floor from being a deadlock: a spent budget,
1590
+ an unreachable principal, a settled checklist or the last turn all leave the
1591
+ verdict exactly where it was. Fails open on an unauthored checklist;
1592
+ `advocate`/v1 untouched; #1463's decline law still applies independently.
1593
+
1594
+ On a premature verdict the turn node logs/traces `negotiation_conclude_premature`
1595
+ and re-issues the turn ONCE, naming the open dimensions and leaving two moves:
1596
+ score the dimension from something a principal actually STATED, or ask the
1597
+ client whose fact it is. Unlike the anti-echo re-issue — which hard-refuses
1598
+ `ask_user`, since a repeated message says nothing about whether a consultation
1599
+ is warranted — an ask drafted on THIS re-issue is the outcome the floor exists
1600
+ to produce, so it is offered in the seat vocabulary and flows through the
1601
+ ordinary admission and park path. That required the three ask gates
1602
+ (reachability, availability/policy, the five-part rule) to become one function
1603
+ the re-issue faces too; policy admission is re-run for a re-issued ask, because
1604
+ the eligibility computed for the refused draft was a judgment about an action
1605
+ that no longer exists.
1606
+
1607
+ - **When the model still refuses, the graph fires the arrow itself.** If the turn
1608
+ that would persist still leaves no ask on the table while an askable unknown
1609
+ stands, the drafted turn is coerced to `ask_user` carrying the top askable
1610
+ DIMENSION, and parks exactly as an agent-drafted ask does — `input_required`,
1611
+ expiry timer, questioner enqueue. Bounded at one per negotiation per principal
1612
+ via a new graph-only `askUser.guaranteed` mark read back off the persisted
1613
+ turn (the turn node strips any agent-claimed mark, so the floor is the field's
1614
+ only writer), and it consumes budget and an ask round like any other ask
1615
+ because the record it writes is the same one every accounting reads.
1616
+
1617
+ Coercion rather than "persist the turn and park beside it": every accounting
1618
+ the protocol has — the per-principal budget, the asked-topics record, the
1619
+ negotiation-wide ask-rounds cap — is read off persisted `ask_user` turns, so a
1620
+ park riding alongside a `counter` would spend a person's attention while the
1621
+ record showed nothing spent and leave the same dimension askable next turn.
1622
+ And after the re-issue the drafted action is frequently terminal, where
1623
+ persisting it would END the negotiation — there is no "in addition" available.
1624
+ What coercion costs is the drafted message, and only where it should be: a
1625
+ terminal turn's message is dropped with the action it belonged to (#1463's
1626
+ rule, for #1463's reason), while a non-terminal message is kept and persisted
1627
+ — a real contribution to the exchange, after which the seat parks instead of
1628
+ handing the turn over. Traced as `negotiation_ask_guaranteed` with the
1629
+ dimension.
1630
+
1631
+ This is NOT the pre-#1455 inferred consultation. That fired from action enums
1632
+ with no content behind them and produced "would you be open to connecting?";
1633
+ this fires from a named dimension the agent itself wrote and itself scored
1634
+ unknown, and the api's question-message author already reads
1635
+ `askUser.dimension` off the parked turn, so what reaches the client is a
1636
+ question about that dimension. `NegotiationInflightContext.dimension`
1637
+ (additive, optional) carries the same thing on the questioner payload.
1638
+
1639
+ The OPENING turn is deliberately outside all of this. The checklist is authored
1640
+ there and the authoring instruction REQUIRES a dimension the record does not
1641
+ settle, so an open dimension on turn 0 is the shape the protocol asked for, not
1642
+ a dodge — and a floor that bound there would park every negotiation before it
1643
+ ever made contact. Turn 0 already has its own designed consult, the pre-contact
1644
+ verdict, bounded per signal.
1645
+
1646
+ - **The verdict prompt's escape hatch is now conditional.** "What remains unknown
1647
+ is the kind of thing two people settle in a first conversation" waved verdicts
1648
+ through unconditionally; the reference behaviour opens that hatch only once the
1649
+ question budget is spent. `CHECKLIST_VERDICT_RULE` now says so: while budget
1650
+ remains and the client is reachable, an unknown that is theirs to settle is
1651
+ asked before any verdict. The basis discipline also gains one line — the reason
1652
+ a match was suggested is an inference drawn by something that never spoke to
1653
+ either principal, so it can no more score a dimension than a profile can.
1654
+
1655
+ Protocol 23.2.0 → 23.3.0. No flags; ships on.
1656
+
1657
+ ## 23.2.0 - 2026-08-20
1658
+
1659
+ ### Fixed
1660
+
1661
+ - **No turn may repeat a message already on the record.** A counterparty asked what
1662
+ a phrase in the client's own signal meant; the answering agent could not consult
1663
+ its (unreachable) principal and its record did not settle the phrase, so with no
1664
+ legal move left it copied the question back word for word. Both models then
1665
+ locked — reproducing text already in context is close to deterministic — and the
1666
+ negotiation spent its remaining turns exchanging two byte-identical messages
1667
+ before one side declined citing "repeated lack of clarity … despite five
1668
+ inquiries". The turn node now compares each drafted message against every
1669
+ message already in the negotiation: an exact repeat is never persisted, the turn
1670
+ is re-issued ONCE with the repeated text quoted back and an instruction to
1671
+ contribute or conclude, and a second repeat ends the run as the new
1672
+ `outcome.reason: "repetition"` — never as a decline, because nobody decided
1673
+ anything. Terminal turns are exempt (a turn that ends the negotiation cannot
1674
+ loop, and refusing one would turn a successful accept into a stall);
1675
+ message-less turns have nothing to duplicate. Deadlock detection (IND-428)
1676
+ could not cover this: its four-turn threshold arrives one turn before a
1677
+ six-turn cap, after the loop has already consumed the negotiation.
1678
+ - **The unreachable-principal rule gains the move the corner actually needed.**
1679
+ `PRINCIPAL_UNREACHABLE_RULE` said never stall and never route the client's
1680
+ question to the other side, but named no move for the case that occurred: the
1681
+ COUNTERPARTY asks something client-authoritative that the record does not
1682
+ settle. The rule now says to state the limit of the record — "X's signal says
1683
+ Y; it does not specify further" is a complete answer — and to let the
1684
+ counterparty score that dimension unknown, never repeating or mirroring their
1685
+ question and never inventing an answer the record does not hold.
1686
+ - **A decline needs a conflict.** The verdict law ("an unknown is not a reason to
1687
+ end anything; pass stays reserved for conflict") was prompt-only, and the prompt
1688
+ lost. A drafted `decline`/`reject` over an authored checklist that holds no
1689
+ `conflict` dimension is now refused — logged as `negotiation_decline_inadmissible`
1690
+ with the unknowns that stood in for one — and coerced to the conservative
1691
+ non-terminal fallback, its terminal message dropped with the action it belonged
1692
+ to. On the final turn, where the seat's vocabulary is accept-or-decline, the
1693
+ decline stands but the violation is recorded rather than manufactured silently.
1694
+ Assessing stances only; fails open on an unauthored checklist; `advocate` is
1695
+ untouched.
1696
+
1697
+ ### Added
1698
+
1699
+ - `NegotiationOutcome.reason` gains `"repetition"`, and `NegotiationAgentInput`
1700
+ gains `antiEcho` (the repeated text, quoted back on a re-issue).
1701
+ - `assessDeclineAdmissibility` in the checklist contracts: the verdict law as a
1702
+ pure function, beside `assessAskAdmissibility`.
1703
+ - Machine-fault reasons (`agent_error`, `repetition`) are filtered out of the
1704
+ discovery vocabulary by an allow-list rather than a deny-list, so a new
1705
+ negotiation reason can never silently cross that boundary.
1706
+
1707
+ ## 23.1.1 - 2026-08-19
1708
+
1709
+ ### Fixed
1710
+
1711
+ - **A negotiation that has already spoken is no longer re-screened.** The outreach
1712
+ gate asks whether to make first contact, and `routeAfterInit` ran it on every
1713
+ continuation that was not an exact `ask_user` resume. An error-stalled negotiation
1714
+ recovered through `negotiation-run-existing` — the documented recovery path — was
1715
+ therefore re-screened two hours after its outreach landed; the gate passed, and an
1716
+ infrastructure failure plus its own recovery turned into a terminal `rejected`
1717
+ the counterparty was never given the chance to answer. Eligibility is now
1718
+ pre-contact, scoped to the negotiation (new `negotiationHasMadeContact`): a new
1719
+ opportunity reusing an existing `dm_pair` is still screened (IND-563), a
1720
+ screen-only or all-`ask_user` history is still pre-contact, and a persisted turn
1721
+ addressed to the counterparty ends the question for good.
1722
+ - **A first-turn `withdraw` on a contacted continuation persists as a real
1723
+ retraction.** The IND-564 guard read `outreachOpened`, which is per-task, so a
1724
+ continuation of a negotiation whose outreach was sent in an earlier session was
1725
+ treated as never-contacted and routed to the quiet `screened_out` outcome. The
1726
+ guard now applies only where nothing was ever sent; a withdraw against a message
1727
+ the counterparty received is recorded as the move it is.
1728
+ - **`screened_out` can no longer be stamped on a negotiation whose messages
1729
+ contradict it.** `finalizeNode` gates both routes to the label — the screen-node
1730
+ block and the opening-turn refusal — on the same pre-contact predicate, so the one
1731
+ outcome that claims nothing was ever sent is unfalsifiable at the point of record.
1732
+
1733
+ ## 23.1.0 - 2026-08-19
1734
+
1735
+ ### Fixed
1736
+
1737
+ - **Retrieval scores no longer clamp at a flat ceiling.** The multi-signal bonus in
1738
+ `mergeStrategyCandidates` was added to the raw similarity and then clamped
1739
+ (`Math.min(raw + boost, 1)`), so candidates found by enough strategies all landed
1740
+ on exactly 1.0. Candidates enter evaluation strictly by rank, so a head cluster of
1741
+ identical maxima crowded genuine matches out of the only evaluated batch. The bonus
1742
+ now consumes the headroom above the raw score (new internal
1743
+ `opportunities/opportunity.similarity.ts`): strictly monotone in the raw score,
1744
+ and 1.0 is reachable only by a vector that actually scored 1.0.
1745
+ - **Evaluation continues past a batch that passes nothing.** `remainingCandidates`
1746
+ was written and never read — there was no second batch, so a run whose top-ranked
1747
+ candidates all failed reported `evaluator_rejected_all` while the real matches sat
1748
+ unevaluated behind them. The evaluation node now walks up to
1749
+ `MAX_EVAL_BATCHES_PER_RUN` (3) batches of 25 while no candidate passes, and stops
1750
+ as soon as one does.
1751
+ - **A stranded tail is reported as a bound, not as a rejection.** When the batch bound
1752
+ is reached with candidates left, the trace carries an `evaluation_bound` node with
1753
+ the never-evaluated count.
1754
+
1755
+ ### Changed
1756
+
1757
+ - **`invokeEntityBundle` under `returnAll: true` now returns dropped verdicts too**,
1758
+ tagged with `rejection: { candidateId, reason }` (`not_accepted` |
1759
+ `incomplete_actors` | `unsupported_claim`) and carrying no actors. Previously a
1760
+ candidate the model explicitly rejected, and one whose accepted verdict a guard
1761
+ dropped, were both indistinguishable from silence, and the discovery trace labelled
1762
+ every one of them "No evaluation returned for this candidate". Callers that
1763
+ persist must filter on `rejection === undefined`; `returnAll: false` is unchanged.
1764
+
1765
+ ## 23.0.0 - 2026-08-19
1766
+
1767
+ ### Added
1768
+
1769
+ - **The checklist negotiation core** (docs/plans/2026-08-19-checklist-negotiations.md
1770
+ §2–§4, §6). A negotiation under the assessing stances now runs on an explicit,
1771
+ pre-registered checklist: 3–5 dimensions authored on turn 1 from the two
1772
+ intents alone (`mutual_want` always present), frozen after, re-scored each
1773
+ turn from the commitment record, with the verdict a function of the scores.
1774
+ New domain module `negotiations/negotiation.checklist.contracts.ts` (exported
1775
+ from the package root): `NegotiationChecklistSchema`, `authorChecklist`,
1776
+ `reconcileChecklist`, `checklistFromTurns`, `checklistVerdictState`,
1777
+ `assessAskAdmissibility`, `renderChecklistSection`,
1778
+ `QUESTION_BUDGET_PER_PRINCIPAL`, `configuredQuestionBudgetPerPrincipal`,
1779
+ plus the DTOs in `shared/schemas/negotiation-checklist.schema.ts`.
1780
+ - **`ask_user` payload**: optional `dimension` and `answerhood`
1781
+ (`{ ok_when, conflict_when }`). An ask names exactly one open dimension and
1782
+ declares in advance what answers score it — the pivotality proof. Both are
1783
+ optional, so v1 turns, external agents and the enum-only path validate
1784
+ unchanged.
1785
+ - **Turn payload**: optional `checklist`, carried on every turn under the
1786
+ protocol. The turn record is the checklist's only store — no new tables, and
1787
+ a continuation recovers the frozen dimensions from the messages it already
1788
+ reads.
1789
+ - **Question block**: optional `dimension` on a block question, the checklist
1790
+ dimension a park is about, for the step's label. Presentation only; routing
1791
+ is still the negotiation ref alone. Blocks without it parse unchanged, so the
1792
+ fail-closed parser stays backward-compatible.
1793
+ - **Per-principal question budget**: at most `QUESTION_BUDGET_PER_PRINCIPAL`
1794
+ (3) questions per principal per negotiation, the turn-0 pre-contact consult
1795
+ included and post-stall parks counted. `countPrincipalAskUserTurns` exposes
1796
+ the count off the message record.
1797
+
1798
+ ### Changed
1799
+
1800
+ - **BREAKING** — `ConsultationEligibilityInput.previouslyConsulted` is now
1801
+ `consultationBudgetSpent`: the one-consultation ration became a budget, and
1802
+ a ration of one is that budget with `total = 1`. Callers pass "this
1803
+ principal's budget for this negotiation is spent" instead of "they have
1804
+ consulted before".
1805
+ - **Negotiator stance contracts restructured** around the checklist protocol.
1806
+ The evidence-provenance rule (#1448) is now the `basis` discipline — an
1807
+ agent's own conclusions are decisions, not commitments, so they cannot score
1808
+ a dimension — and the responder verification rules (#1446) are now the
1809
+ responding seat's scoring duty. Neither duty was dropped; both became rules
1810
+ about what may score a dimension, and the repair path enforces them (an `ok`
1811
+ with no basis is repaired to `unknown`). New predicate `stanceUsesChecklist`.
1812
+ `advocate` is untouched, prompt and generation schema alike — the golden
1813
+ prompt matrix still passes byte-for-byte.
1814
+ - `negotiationAskRoundsCap()` takes `{ checklist }` and defaults to
1815
+ `CHECKLIST_NEGOTIATION_ASK_ROUNDS_CAP` (both principals' budgets plus one
1816
+ post-stall park) under the checklist protocol; the pre-checklist default
1817
+ stays 3. An explicit `NEGOTIATION_ASK_ROUNDS_CAP` still wins.
1818
+ - `AskUserOpts` is now `TurnVocabularyOpts` (`{ askUser, checklist }`); the old
1819
+ name remains as a deprecated alias.
1820
+
23
1821
  ## 22.0.0 - 2026-08-18
24
1822
 
25
1823
  ### Removed
@@ -761,6 +2559,49 @@ No public API change: all 441 exported symbols are byte-identical to 13.2.0, and
761
2559
 
762
2560
  ## [Unreleased]
763
2561
 
2562
+ ### Removed
2563
+
2564
+ - **Breaking (38.0.0): single-path opportunities.** Discovery no longer creates
2565
+ opportunities. It records one `discovery_match_candidates` row per pair, keyed by
2566
+ `pairKeyOf(networkId, intentA, intentB)`, and the `opportunities` row is INSERTed at
2567
+ kickoff by `createAndOpen` when a principal's PersonalAgent decides to reach out.
2568
+ - `PersonalAgentMatch.opportunityId` is replaced by
2569
+ `ref: { kind: 'candidate' | 'opportunity'; id: string }`. Read it with
2570
+ `matchRefId(match)`; build one with `opportunityRef(id)`.
2571
+ - `PersonalAgentOpportunityPort` requires `createAndOpen`.
2572
+ - `OpportunityStatus` loses `latent` and `draft`. An opportunity is born
2573
+ `negotiating`; there is no pre-kickoff state.
2574
+ - The `introducer` actor role is removed, with its `approved` field,
2575
+ `updateOpportunityActorApproval`, and every visibility rule that keyed on it.
2576
+ `canUserSeeOpportunity` now answers one question — is the viewer an actor.
2577
+ - Removed exports: `MaintenanceGraphFactory`, `MaintenanceGraphDatabase`,
2578
+ `MaintenanceGraphCache`, `MaintenanceGraphQueue`, `createIntroduction`,
2579
+ `approveIntroduction`, `sendOpportunity`, `evaluateIntroduction`,
2580
+ `validateIntroduction`, `IntroductionRequest`, `persistOpportunities`,
2581
+ `StampNewbornOpportunitiesFn`, `StampNewbornOpportunitiesInput`,
2582
+ `OpportunityPersistenceOutcome`, and the `radar.health` scoring module.
2583
+ - `operationMode` narrows to `create | read | update | delete`.
2584
+ - Discovery sources narrow to `query`; `premise-similarity`,
2585
+ `context-similarity` and `context-to-intent` are gone, as are their evidence
2586
+ kinds.
2587
+ - Hosts must implement `upsertDiscoveryMatchCandidates` and
2588
+ `listPendingCandidatesForIntent`.
2589
+ - **Breaking (38.0.0): `QuestionRecoverySnapshot` drops its discovery-completion
2590
+ fields.** `completionSource` narrows to `z.enum(["intent_creation"])` — the
2591
+ `from_intent`/`discovery_run` values belonged to the post-discovery
2592
+ recovery-question generator, retired in `6a3b65b0e` with no writer left.
2593
+ `rejectedNegotiationCount` and `runId` are removed for the same reason.
2594
+ Existing persisted `questions.detection` rows written before the retirement
2595
+ may still carry the old values; nothing in the host parses them against this
2596
+ schema at read time.
2597
+
2598
+ ### Added
2599
+
2600
+ - `pairKeyOf`, `DiscoveryMatchCandidate`, `CreateDiscoveryMatchCandidateData`,
2601
+ `DiscoveryMatchCandidateStatus`, `CreateAndOpenResult`, `PersonalAgentMatchRef`,
2602
+ `matchRefId`, `opportunityRef`, `OpportunityEvidence`.
2603
+
2604
+
764
2605
  ### Changed
765
2606
  - Behaviour-neutral internal refactor (16.1.1): split the six largest modules and hoist every graph node to a top-level function. The opportunity graph is now the discovery pipeline only — its eight non-pipeline modes (read, update, delete, send, negotiate_existing, approve_introduction, and the two introduction stages) are plain functions on `OpportunityGraphFactory` instead of `operationMode` conditional-edge routing. `database.interface.ts` becomes a barrel over entity, query-group, and capability-view modules; every `Pick<Database, ...>` resolves as before. The opportunity presentation cluster is one module. `opportunity.graph.ts` 4167 → 250 lines, `database.interface.ts` 2925 → 17, `negotiation.graph.ts` 1619 → 111, `opportunity.tools.ts` 1200 → 354, `enrichment.tools.ts` 1198 → 178, `intent.graph.ts` 1091 → 174. No public export, feature flag, or environment variable changed.
766
2607
  - Move the opportunity-presentation review checklist into `src/opportunity/AGENTS.md` and repoint the `opportunity.safe-presentation.ts` and `discriminator.adjustments.ts` comments at it. Comment-only; no runtime change.