@indexnetwork/protocol 6.13.22-rc.405.1 → 6.14.0-rc.406.1

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.
package/CHANGELOG.md CHANGED
@@ -12,6 +12,15 @@ See [STABILITY.md](./STABILITY.md) for the public-contract and tier definitions.
12
12
 
13
13
  ## [Unreleased]
14
14
 
15
+ ## [6.14.0] — 2026-07-25
16
+
17
+ ### Added
18
+ - Add `NEGOTIATION_INCLUDE_OTHER_INTENTS` (IND-571), a strict boolean
19
+ deployment policy for autonomous opportunity negotiation. The default
20
+ preserves exact-first bounded active-intent context; `false` isolates each
21
+ participant to its exact opportunity-bound intent across fresh and
22
+ continuation negotiation contexts.
23
+
15
24
  ## [6.13.22] — 2026-07-25
16
25
 
17
26
  ### Added
@@ -593,6 +593,8 @@ export interface NegotiationCandidate {
593
593
  /** Exact opportunity-bound source and candidate intent IDs. */
594
594
  sourceIntentId?: string;
595
595
  candidateIntentId?: string;
596
+ /** Per-opportunity source context when its exact actor intent differs across a fan-out. */
597
+ sourceUser?: UserNegotiationContext;
596
598
  reasoning: string;
597
599
  valencyRole: string;
598
600
  networkId?: string;
@@ -1249,15 +1249,16 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
1249
1249
  const emitWide = (event) => traceEmitter?.(event);
1250
1250
  const results = await Promise.all(candidates.map(async (candidate) => {
1251
1251
  const start = Date.now();
1252
+ const candidateSourceUser = candidate.sourceUser ?? sourceUser;
1252
1253
  if (candidate.opportunityId) {
1253
1254
  const candidateName = candidate.candidateUser?.profile?.name;
1254
1255
  emitWide({
1255
1256
  type: "negotiation_session_start",
1256
1257
  opportunityId: candidate.opportunityId,
1257
1258
  negotiationConversationId: "", // filled in on session_end
1258
- sourceUserId: sourceUser.id,
1259
+ sourceUserId: candidateSourceUser.id,
1259
1260
  candidateUserId: candidate.userId,
1260
- initiatorUserId: initiatorUserId ?? sourceUser.id,
1261
+ initiatorUserId: initiatorUserId ?? candidateSourceUser.id,
1261
1262
  ...(candidateName && { candidateName }),
1262
1263
  trigger: trigger ?? "ambient",
1263
1264
  startedAt: start,
@@ -1269,7 +1270,7 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
1269
1270
  ? { networkId: candidate.networkId, prompt: indexContextOverrides?.get(candidate.networkId) ?? '' }
1270
1271
  : indexContext;
1271
1272
  const result = await invokeWithAbortSignal(negotiationGraph, {
1272
- sourceUser,
1273
+ sourceUser: candidateSourceUser,
1273
1274
  candidateUser: candidate.candidateUser,
1274
1275
  ...(candidate.sourceIntentId && { sourceIntentId: candidate.sourceIntentId }),
1275
1276
  ...(candidate.candidateIntentId && { candidateIntentId: candidate.candidateIntentId }),
@@ -1,5 +1,7 @@
1
1
  import type { NegotiationContinuationExecution, NegotiationContinuationReceipt, Opportunity, OpportunityGraphDatabase } from '../../shared/interfaces/database.interface.js';
2
2
  import type { QueueOpportunityNotificationFn } from './opportunity.lifecycle.js';
3
+ /** Default-compatible deployment policy for autonomous opportunity negotiation. */
4
+ export declare function negotiationIncludesOtherIntents(): boolean;
3
5
  interface NegotiationIntentSource {
4
6
  id?: string | null;
5
7
  summary?: string | null;
@@ -34,7 +36,7 @@ interface ExistingOpportunityNegotiationCandidate {
34
36
  candidateUser: ExistingOpportunityNegotiationUser;
35
37
  }
36
38
  /** Put an opportunity actor's exact intent first, then fill the bounded context without duplicates. */
37
- export declare function buildPrioritizedNegotiationIntents(activeIntents: readonly NegotiationIntentSource[], exactIntentId?: string | null, fallbackIntent?: NegotiationIntentSource | null): ExistingOpportunityNegotiationUser['intents'];
39
+ export declare function buildPrioritizedNegotiationIntents(activeIntents: readonly NegotiationIntentSource[], exactIntentId?: string | null, fallbackIntent?: NegotiationIntentSource | null, includeOtherIntents?: boolean): ExistingOpportunityNegotiationUser['intents'];
38
40
  /** Narrow port for translating one persisted opportunity into a negotiation invocation. */
39
41
  export type ExistingOpportunityNegotiationPort = Pick<OpportunityGraphDatabase, 'getActiveIntents' | 'getIntent' | 'getNetworkMemberContext' | 'getOpportunity' | 'getProfile' | 'getUser'>;
40
42
  export interface ExistingOpportunityNegotiationInput {
@@ -1,13 +1,17 @@
1
1
  import { resolveOpportunityActorIntent } from '../domain/opportunity.actor.js';
2
2
  const NEGOTIATION_INTENT_LIMIT = 5;
3
+ /** Default-compatible deployment policy for autonomous opportunity negotiation. */
4
+ export function negotiationIncludesOtherIntents() {
5
+ return process.env.NEGOTIATION_INCLUDE_OTHER_INTENTS !== 'false';
6
+ }
3
7
  /** Put an opportunity actor's exact intent first, then fill the bounded context without duplicates. */
4
- export function buildPrioritizedNegotiationIntents(activeIntents, exactIntentId, fallbackIntent) {
8
+ export function buildPrioritizedNegotiationIntents(activeIntents, exactIntentId, fallbackIntent, includeOtherIntents = true) {
5
9
  const exactId = typeof exactIntentId === 'string' && exactIntentId.trim().length > 0 ? exactIntentId : null;
6
10
  const exactActive = exactId ? activeIntents.find((intent) => intent.id === exactId) : undefined;
7
11
  const ordered = [
8
12
  ...(exactActive ? [exactActive] : []),
9
13
  ...(!exactActive && fallbackIntent?.id === exactId ? [fallbackIntent] : []),
10
- ...activeIntents,
14
+ ...(includeOtherIntents ? activeIntents : []),
11
15
  ];
12
16
  const seen = new Set();
13
17
  const intents = [];
@@ -51,13 +55,18 @@ export async function negotiateExistingOpportunity(database, executeNegotiation,
51
55
  return { kind: 'skipped', reason: 'no_candidate_actor' };
52
56
  const sourceIntentId = resolveOpportunityActorIntent(sourceActor);
53
57
  const candidateIntentId = resolveOpportunityActorIntent(candidateActor);
58
+ const includeOtherIntents = negotiationIncludesOtherIntents();
54
59
  const [sourceAccount, sourceProfile, sourceIntents, candidateAccount, candidateProfile, candidateIntents] = await Promise.all([
55
60
  database.getUser(sourceActor.userId).catch(() => null),
56
61
  database.getProfile(sourceActor.userId).catch(() => null),
57
- database.getActiveIntents(sourceActor.userId).catch(() => []),
62
+ includeOtherIntents
63
+ ? database.getActiveIntents(sourceActor.userId).catch(() => [])
64
+ : Promise.resolve([]),
58
65
  database.getUser(candidateActor.userId).catch(() => null),
59
66
  database.getProfile(candidateActor.userId).catch(() => null),
60
- database.getActiveIntents(candidateActor.userId).catch(() => []),
67
+ includeOtherIntents
68
+ ? database.getActiveIntents(candidateActor.userId).catch(() => [])
69
+ : Promise.resolve([]),
61
70
  ]);
62
71
  const [sourceFallbackIntent, candidateFallbackIntent] = await Promise.all([
63
72
  sourceIntentId && !sourceIntents.some((intent) => intent.id === sourceIntentId) ? database.getIntent(sourceIntentId).catch(() => null) : null,
@@ -65,7 +74,7 @@ export async function negotiateExistingOpportunity(database, executeNegotiation,
65
74
  ]);
66
75
  const sourceUser = {
67
76
  id: sourceActor.userId,
68
- intents: buildPrioritizedNegotiationIntents(sourceIntents, sourceIntentId, sourceFallbackIntent?.userId === sourceActor.userId ? sourceFallbackIntent : null),
77
+ intents: buildPrioritizedNegotiationIntents(sourceIntents, sourceIntentId, sourceFallbackIntent?.userId === sourceActor.userId ? sourceFallbackIntent : null, includeOtherIntents),
69
78
  profile: {
70
79
  name: sourceProfile?.identity?.name ?? sourceAccount?.name,
71
80
  bio: sourceProfile?.identity?.bio ?? sourceAccount?.intro ?? undefined,
@@ -84,7 +93,7 @@ export async function negotiateExistingOpportunity(database, executeNegotiation,
84
93
  networkId: candidateActor.networkId,
85
94
  candidateUser: {
86
95
  id: candidateActor.userId,
87
- intents: buildPrioritizedNegotiationIntents(candidateIntents, candidateIntentId, candidateFallbackIntent?.userId === candidateActor.userId ? candidateFallbackIntent : null),
96
+ intents: buildPrioritizedNegotiationIntents(candidateIntents, candidateIntentId, candidateFallbackIntent?.userId === candidateActor.userId ? candidateFallbackIntent : null, includeOtherIntents),
88
97
  profile: {
89
98
  name: candidateProfile?.identity?.name ?? candidateAccount?.name,
90
99
  bio: candidateProfile?.identity?.bio ?? candidateAccount?.intro ?? undefined,
@@ -34,7 +34,7 @@ import { mergeOpportunityEvidence, withCandidateEvidence, withMatchedStrategies
34
34
  import { normalizeOpportunityActorIntent, resolveOpportunityActorIntent } from '../domain/opportunity.actor.js';
35
35
  import { approveOpportunityIntroduction, deleteOpportunityLifecycle, sendOpportunityLifecycle, updateOpportunityLifecycle } from './opportunity.lifecycle.js';
36
36
  import { stampEligibleNewbornOpportunities } from './opportunity.newborn-stamping.js';
37
- import { buildPrioritizedNegotiationIntents, negotiateExistingOpportunity } from './opportunity.existing-negotiation.js';
37
+ import { buildPrioritizedNegotiationIntents, negotiateExistingOpportunity, negotiationIncludesOtherIntents } from './opportunity.existing-negotiation.js';
38
38
  import { admitOpportunityPersistence, createEligibleOpportunityStatusUpdater } from './opportunity.persistence-admission.js';
39
39
  export { buildPrioritizedNegotiationIntents } from './opportunity.existing-negotiation.js';
40
40
  const logger = protocolLogger('OpportunityGraph');
@@ -1878,6 +1878,7 @@ export class OpportunityGraphFactory {
1878
1878
  try {
1879
1879
  // Use the same discoveryUserId pattern as evaluationNode
1880
1880
  const discoveryUserId = (state.onBehalfOfUserId ?? state.userId);
1881
+ const includeOtherIntents = negotiationIncludesOtherIntents();
1881
1882
  const sourceAccount = await this.database.getUser(discoveryUserId).catch(() => null);
1882
1883
  const sourceIntentInputs = (state.indexedIntents ?? []).map((intent) => ({
1883
1884
  id: intent.intentId,
@@ -1893,7 +1894,7 @@ export class OpportunityGraphFactory {
1893
1894
  : null;
1894
1895
  const sourceUser = {
1895
1896
  id: discoveryUserId,
1896
- intents: buildPrioritizedNegotiationIntents(sourceIntentInputs, state.triggerIntentId, ownedSourceFallback),
1897
+ intents: buildPrioritizedNegotiationIntents(sourceIntentInputs, state.triggerIntentId, ownedSourceFallback, includeOtherIntents),
1897
1898
  profile: {
1898
1899
  name: state.sourceProfile?.identity?.name ?? sourceAccount?.name,
1899
1900
  bio: state.sourceProfile?.identity?.bio ?? sourceAccount?.intro ?? undefined,
@@ -1945,20 +1946,33 @@ export class OpportunityGraphFactory {
1945
1946
  const userId = candidateActor.userId;
1946
1947
  const sourceIntentId = resolveOpportunityActorIntent(sourceActor);
1947
1948
  const candidateIntentId = resolveOpportunityActorIntent(candidateActor);
1948
- const [profile, user, activeIntents, intent] = await Promise.all([
1949
+ const sourceExactActive = sourceIntentId
1950
+ ? sourceIntentInputs.find((sourceIntent) => sourceIntent.id === sourceIntentId)
1951
+ : undefined;
1952
+ const [profile, user, activeIntents, intent, sourceIntent] = await Promise.all([
1949
1953
  this.database.getProfile(userId).catch(() => null),
1950
1954
  this.database.getUser(userId).catch(() => null),
1951
- this.database.getActiveIntents(userId).catch(() => []),
1955
+ includeOtherIntents
1956
+ ? this.database.getActiveIntents(userId).catch(() => [])
1957
+ : Promise.resolve([]),
1952
1958
  candidateIntentId
1953
1959
  ? this.database.getIntent(candidateIntentId).catch(() => null)
1954
1960
  : null,
1961
+ sourceIntentId && !sourceExactActive
1962
+ ? this.database.getIntent(sourceIntentId).catch(() => null)
1963
+ : null,
1955
1964
  ]);
1956
1965
  const ownedFallbackIntent = intent?.userId === userId ? intent : null;
1957
- const candidateIntents = buildPrioritizedNegotiationIntents(activeIntents, candidateIntentId, ownedFallbackIntent);
1966
+ const ownedSourceIntent = sourceIntent?.userId === discoveryUserId ? sourceIntent : null;
1967
+ const candidateIntents = buildPrioritizedNegotiationIntents(activeIntents, candidateIntentId, ownedFallbackIntent, includeOtherIntents);
1958
1968
  return {
1959
1969
  userId,
1960
1970
  ...(sourceIntentId ? { sourceIntentId } : {}),
1961
1971
  ...(candidateIntentId ? { candidateIntentId } : {}),
1972
+ sourceUser: {
1973
+ ...sourceUser,
1974
+ intents: buildPrioritizedNegotiationIntents(sourceIntentInputs, sourceIntentId, ownedSourceIntent, includeOtherIntents),
1975
+ },
1962
1976
  opportunityId: opp.id,
1963
1977
  opportunityStatus: opp.status,
1964
1978
  opportunityUpdatedAt: opp.updatedAt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indexnetwork/protocol",
3
- "version": "6.13.22-rc.405.1",
3
+ "version": "6.14.0-rc.406.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",