@indexnetwork/protocol 6.11.1-rc.402.1 → 6.12.1-rc.404.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 +1 -0
- package/dist/negotiation/negotiation.agent.d.ts +10 -0
- package/dist/negotiation/negotiation.agent.d.ts.map +1 -1
- package/dist/negotiation/negotiation.agent.js +26 -8
- package/dist/negotiation/negotiation.agent.js.map +1 -1
- package/dist/negotiation/negotiation.attribution.d.ts +92 -0
- package/dist/negotiation/negotiation.attribution.d.ts.map +1 -0
- package/dist/negotiation/negotiation.attribution.js +110 -0
- package/dist/negotiation/negotiation.attribution.js.map +1 -0
- package/dist/negotiation/negotiation.graph.d.ts +19 -0
- package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
- package/dist/negotiation/negotiation.graph.js +128 -6
- package/dist/negotiation/negotiation.graph.js.map +1 -1
- package/dist/negotiation/negotiation.screen.d.ts +24 -0
- package/dist/negotiation/negotiation.screen.d.ts.map +1 -1
- package/dist/negotiation/negotiation.screen.js +20 -1
- package/dist/negotiation/negotiation.screen.js.map +1 -1
- package/dist/negotiation/negotiation.state.d.ts +33 -0
- package/dist/negotiation/negotiation.state.d.ts.map +1 -1
- package/dist/negotiation/negotiation.state.js +33 -0
- package/dist/negotiation/negotiation.state.js.map +1 -1
- package/dist/opportunity/opportunity.evidence.d.ts.map +1 -1
- package/dist/opportunity/opportunity.evidence.js +8 -1
- package/dist/opportunity/opportunity.evidence.js.map +1 -1
- package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
- package/dist/opportunity/opportunity.graph.js +91 -4
- package/dist/opportunity/opportunity.graph.js.map +1 -1
- package/dist/shared/interfaces/agent-dispatcher.interface.d.ts +8 -0
- package/dist/shared/interfaces/agent-dispatcher.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/agent-dispatcher.interface.js.map +1 -1
- package/dist/shared/interfaces/database.interface.d.ts +27 -2
- package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
- package/dist/shared/interfaces/database.interface.js.map +1 -1
- package/dist/shared/schemas/question.schema.d.ts +37 -7
- package/dist/shared/schemas/question.schema.d.ts.map +1 -1
- package/dist/shared/schemas/question.schema.js +11 -1
- package/dist/shared/schemas/question.schema.js.map +1 -1
- package/package.json +1 -1
|
@@ -55,6 +55,27 @@ const negotiateExistingLog = protocolLogger('OpportunityGraph:NegotiateExisting'
|
|
|
55
55
|
const routingLog = protocolLogger('OpportunityGraph:Routing');
|
|
56
56
|
/** Time window for persist-node dedup. Suppresses a second opportunity with the same person while a recent one (within 30 days) is still in flight, so a person is not re-surfaced multiple times within a month (EDG-23). */
|
|
57
57
|
const DEDUP_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;
|
|
58
|
+
/**
|
|
59
|
+
* IND-567: Cool-down window (ms) for cross-query rejection suppression.
|
|
60
|
+
* Candidates with a recently rejected or stalled opportunity within this window
|
|
61
|
+
* receive a similarity penalty during evaluation ranking. Default 7 days.
|
|
62
|
+
* Override with DISCOVERY_REJECTION_COOLDOWN_DAYS (positive float).
|
|
63
|
+
*/
|
|
64
|
+
const DEFAULT_REJECTION_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1000;
|
|
65
|
+
function getRejectionCooldownMs() {
|
|
66
|
+
const raw = process.env.DISCOVERY_REJECTION_COOLDOWN_DAYS;
|
|
67
|
+
if (!raw)
|
|
68
|
+
return DEFAULT_REJECTION_COOLDOWN_MS;
|
|
69
|
+
const n = Number.parseFloat(raw);
|
|
70
|
+
return Number.isFinite(n) && n > 0 ? Math.round(n * 24 * 60 * 60 * 1000) : DEFAULT_REJECTION_COOLDOWN_MS;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Similarity multiplier applied to candidates that fall within the rejection
|
|
74
|
+
* cool-down window (IND-567). 0.5 halves their ranking score, typically
|
|
75
|
+
* pushing them below the evaluation-batch cut while leaving a soft trace in
|
|
76
|
+
* the trace log rather than silently dropping them.
|
|
77
|
+
*/
|
|
78
|
+
const REJECTION_COOLDOWN_SIMILARITY_PENALTY = 0.5;
|
|
58
79
|
const NEGOTIATION_INTENT_LIMIT = 5;
|
|
59
80
|
const ACTIVE_NEGOTIATION_TASK_STATES = new Set([
|
|
60
81
|
'submitted',
|
|
@@ -1449,8 +1470,45 @@ export class OpportunityGraphFactory {
|
|
|
1449
1470
|
removed: sortedCandidates.length - dedupedCandidates.length,
|
|
1450
1471
|
});
|
|
1451
1472
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1473
|
+
// ── IND-567: Rejection cool-down penalty ──────────────────────────
|
|
1474
|
+
// Candidates with a recently rejected or stalled opportunity receive a
|
|
1475
|
+
// similarity penalty so they are ranked lower (and often pushed out of
|
|
1476
|
+
// the evaluation batch). This prevents cross-query re-surfacing of
|
|
1477
|
+
// false-positive matches that were already caught downstream.
|
|
1478
|
+
// The persist-node dedup is still the hard gate; this is a soft guard
|
|
1479
|
+
// that reduces evaluator cost and LLM false-positive rate.
|
|
1480
|
+
const rejectionCooldownIds = new Set();
|
|
1481
|
+
if (eligibleCandidates.length > 0
|
|
1482
|
+
&& typeof this.database.getRecentlyRejectedOpportunityCounterparties === 'function') {
|
|
1483
|
+
try {
|
|
1484
|
+
const cooldownMs = getRejectionCooldownMs();
|
|
1485
|
+
const ids = await this.database.getRecentlyRejectedOpportunityCounterparties(discoveryUserId, eligibleCandidates.map((c) => c.candidateUserId), cooldownMs);
|
|
1486
|
+
for (const id of ids)
|
|
1487
|
+
rejectionCooldownIds.add(id);
|
|
1488
|
+
if (rejectionCooldownIds.size > 0) {
|
|
1489
|
+
evaluationLog.info('IND-567 rejection cool-down: applying similarity penalty', {
|
|
1490
|
+
affectedCount: rejectionCooldownIds.size,
|
|
1491
|
+
cooldownDays: Math.round(cooldownMs / (24 * 60 * 60 * 1000)),
|
|
1492
|
+
penalty: REJECTION_COOLDOWN_SIMILARITY_PENALTY,
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
catch (err) {
|
|
1497
|
+
evaluationLog.warn('IND-567 rejection cool-down: lookup failed, skipping penalty', {
|
|
1498
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
// Apply penalty and re-sort so penalised candidates fall to the back.
|
|
1503
|
+
const eligibleCandidatesAfterCooldown = rejectionCooldownIds.size > 0
|
|
1504
|
+
? eligibleCandidates
|
|
1505
|
+
.map((c) => rejectionCooldownIds.has(c.candidateUserId)
|
|
1506
|
+
? { ...c, similarity: c.similarity * REJECTION_COOLDOWN_SIMILARITY_PENALTY }
|
|
1507
|
+
: c)
|
|
1508
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
1509
|
+
: eligibleCandidates;
|
|
1510
|
+
const batchToEvaluate = eligibleCandidatesAfterCooldown.slice(0, EVAL_BATCH_SIZE);
|
|
1511
|
+
const remaining = eligibleCandidatesAfterCooldown.slice(EVAL_BATCH_SIZE);
|
|
1454
1512
|
// Early termination: if search was query-driven and no query-sourced candidates remain,
|
|
1455
1513
|
// clear remaining to prevent pointless pagination through non-query leftovers
|
|
1456
1514
|
const isQueryDriven = !!state.searchQuery?.trim();
|
|
@@ -1500,6 +1558,35 @@ export class OpportunityGraphFactory {
|
|
|
1500
1558
|
intentSummary = intent.summary ?? undefined;
|
|
1501
1559
|
}
|
|
1502
1560
|
}
|
|
1561
|
+
// IND-567 Fix A: fetch premise text for query_premise candidates.
|
|
1562
|
+
// The query-path sets candidatePayload='' for premise hits because
|
|
1563
|
+
// the vector-search result only carries a premise ID, not its text.
|
|
1564
|
+
// Without the text, renderOpportunityEvidenceForPrompt emits a line
|
|
1565
|
+
// with no domain content, letting the evaluator score on lens label
|
|
1566
|
+
// alone — which produces cross-domain false positives at confidence 1.0.
|
|
1567
|
+
// Mirror the getIntent fetch pattern: populate the evidence assertionText
|
|
1568
|
+
// from the DB so the evaluator can see the candidate's actual claim.
|
|
1569
|
+
let candidateEvidence = c.evidence;
|
|
1570
|
+
if (c.candidatePremiseId != null
|
|
1571
|
+
&& c.candidateIntentId == null
|
|
1572
|
+
&& (!c.candidatePayload || c.candidatePayload === '')
|
|
1573
|
+
&& typeof this.database.getPremise === 'function') {
|
|
1574
|
+
try {
|
|
1575
|
+
const premise = await this.database.getPremise(c.candidatePremiseId);
|
|
1576
|
+
const assertionText = premise?.assertion?.text;
|
|
1577
|
+
if (assertionText) {
|
|
1578
|
+
candidateEvidence = (c.evidence ?? []).map((ev) => ev.kind === 'query_premise' && ev.candidatePremiseId === c.candidatePremiseId
|
|
1579
|
+
? { ...ev, payload: assertionText, assertionText }
|
|
1580
|
+
: ev);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
catch (premiseFetchErr) {
|
|
1584
|
+
evaluationLog.warn('IND-567: failed to fetch premise text for evaluator', {
|
|
1585
|
+
candidatePremiseId: c.candidatePremiseId,
|
|
1586
|
+
error: premiseFetchErr instanceof Error ? premiseFetchErr.message : String(premiseFetchErr),
|
|
1587
|
+
});
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1503
1590
|
const evidenceKey = buildEvaluatorEvidenceKey(c);
|
|
1504
1591
|
return {
|
|
1505
1592
|
userId: c.candidateUserId,
|
|
@@ -1516,7 +1603,7 @@ export class OpportunityGraphFactory {
|
|
|
1516
1603
|
evidenceKey,
|
|
1517
1604
|
ragScore: c.similarity * 100,
|
|
1518
1605
|
matchedVia: c.lens,
|
|
1519
|
-
evidence:
|
|
1606
|
+
evidence: candidateEvidence, // IND-567 Fix A: may carry populated assertionText
|
|
1520
1607
|
};
|
|
1521
1608
|
}));
|
|
1522
1609
|
const userIdToIndexId = new Map();
|
|
@@ -1808,7 +1895,7 @@ export class OpportunityGraphFactory {
|
|
|
1808
1895
|
// Only pass opportunities that passed the threshold to downstream nodes
|
|
1809
1896
|
const passedOpportunities = evaluatedOpportunities.filter((o) => o.score >= minScore);
|
|
1810
1897
|
return {
|
|
1811
|
-
candidates:
|
|
1898
|
+
candidates: eligibleCandidatesAfterCooldown,
|
|
1812
1899
|
evaluatedOpportunities: passedOpportunities,
|
|
1813
1900
|
remainingCandidates: effectiveRemaining,
|
|
1814
1901
|
trace: traceEntries,
|