@indexnetwork/protocol 6.14.0-rc.406.1 → 8.0.1-rc.417.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 +307 -0
- package/IMPLEMENTATION.md +7 -4
- package/dist/capabilities/opportunities.facade.d.ts +4 -0
- package/dist/capabilities/opportunities.facade.js +4 -0
- package/dist/capabilities/signals.tools.port.d.ts +1 -1
- package/dist/chat/chat-streaming.types.d.ts +4 -5
- package/dist/chat/chat.agent.d.ts +0 -19
- package/dist/chat/chat.agent.js +1 -70
- package/dist/chat/chat.persona.d.ts +0 -6
- package/dist/chat/chat.persona.js +0 -1
- package/dist/chat/chat.prompt.js +10 -10
- package/dist/chat/chat.prompt.modules.js +0 -104
- package/dist/chat/chat.tools.js +11 -7
- package/dist/chat/negotiator.persona.js +0 -1
- package/dist/chat/onboarding.persona.js +0 -1
- package/dist/chat/reporter.persona.d.ts +1 -1
- package/dist/chat/reporter.persona.js +1 -2
- package/dist/chat/reporter.prompt.js +5 -5
- package/dist/chat/signal.persona.js +0 -1
- package/dist/communities/application/network.tools.js +48 -27
- package/dist/contacts/application/contact.tools.js +9 -9
- package/dist/index.d.ts +9 -2
- package/dist/index.js +5 -0
- package/dist/maintenance/maintenance.graph.js +7 -0
- package/dist/mcp/mcp.authorization-policy.d.ts +250 -0
- package/dist/mcp/mcp.authorization-policy.js +522 -0
- package/dist/mcp/mcp.server.d.ts +6 -29
- package/dist/mcp/mcp.server.js +202 -228
- package/dist/negotiation/application/negotiation.agent.js +29 -5
- package/dist/negotiation/application/negotiation.graph.d.ts +2 -5
- package/dist/negotiation/application/negotiation.graph.js +53 -23
- package/dist/negotiation/domain/index.d.ts +3 -0
- package/dist/negotiation/domain/index.js +3 -0
- package/dist/negotiation/domain/negotiation.deadlock.d.ts +7 -1
- package/dist/negotiation/domain/negotiation.deadlock.js +48 -1
- package/dist/negotiation/domain/negotiation.stance.contracts.d.ts +85 -0
- package/dist/negotiation/domain/negotiation.stance.contracts.js +140 -0
- package/dist/negotiation/domain/negotiation.state.d.ts +2 -3
- package/dist/negotiation/domain/negotiation.state.js +2 -3
- package/dist/negotiation/public/index.d.ts +2 -0
- package/dist/negotiation/public/index.js +2 -0
- package/dist/opportunity/application/index.d.ts +0 -3
- package/dist/opportunity/application/index.js +0 -3
- package/dist/opportunity/application/opportunity.graph.d.ts +0 -43
- package/dist/opportunity/application/opportunity.graph.js +7 -113
- package/dist/opportunity/application/opportunity.introducer-feature.d.ts +2 -0
- package/dist/opportunity/application/opportunity.introducer-feature.js +4 -0
- package/dist/opportunity/application/opportunity.owner-approval.d.ts +118 -0
- package/dist/opportunity/application/opportunity.owner-approval.js +34 -0
- package/dist/opportunity/application/opportunity.owner-provenance.d.ts +6 -0
- package/dist/opportunity/application/opportunity.owner-provenance.js +28 -0
- package/dist/opportunity/application/opportunity.tools.d.ts +3 -3
- package/dist/opportunity/application/opportunity.tools.js +77 -870
- package/dist/opportunity/discriminator/discriminator.shadow.js +17 -10
- package/dist/opportunity/discriminator/discriminator.types.d.ts +2 -0
- package/dist/opportunity/domain/index.d.ts +0 -2
- package/dist/opportunity/domain/index.js +0 -2
- package/dist/opportunity/domain/opportunity.state.d.ts +2 -70
- package/dist/opportunity/domain/opportunity.state.js +2 -55
- package/dist/opportunity/opportunity.owner-approval.d.ts +5 -0
- package/dist/opportunity/opportunity.owner-approval.js +5 -0
- package/dist/opportunity/ports/opportunity.tools.port.d.ts +12 -1
- package/dist/opportunity/public/index.d.ts +3 -3
- package/dist/opportunity/public/index.js +2 -1
- package/dist/participant-agents/application/agent.tools.d.ts +1 -1
- package/dist/participant-agents/application/agent.tools.js +44 -6
- package/dist/participant-agents/application/index.d.ts +5 -3
- package/dist/participant-agents/application/index.js +5 -3
- package/dist/questions/application/question.tools.js +31 -2
- package/dist/runtime/foreground/composition/tool.factory.d.ts +2 -1
- package/dist/runtime/foreground/composition/tool.factory.js +10 -2
- package/dist/runtime/foreground/composition/tool.registry.d.ts +16 -2
- package/dist/runtime/foreground/composition/tool.registry.js +41 -38
- package/dist/shared/agent/activity-projection.d.ts +271 -0
- package/dist/shared/agent/activity-projection.js +248 -0
- package/dist/shared/agent/canonical-guidance.d.ts +30 -0
- package/dist/shared/agent/canonical-guidance.js +249 -0
- package/dist/shared/agent/tool.helpers.d.ts +13 -17
- package/dist/shared/agent/tool.runtime.js +1 -3
- package/dist/shared/agent/utility.tools.d.ts +11 -1
- package/dist/shared/agent/utility.tools.js +126 -90
- package/dist/shared/interfaces/auth.interface.d.ts +2 -8
- package/dist/shared/interfaces/chat-session.interface.js +5 -0
- package/dist/shared/interfaces/database.interface.d.ts +12 -5
- package/dist/shared/observability/request-context.d.ts +4 -40
- package/dist/shared/schemas/mcp-auth.schema.d.ts +87 -15
- package/dist/shared/schemas/mcp-auth.schema.js +49 -1
- package/dist/signals/application/intent.graph.js +4 -15
- package/dist/signals/application/intent.tools.js +34 -14
- package/dist/signals/domain/intent.proposal.d.ts +35 -0
- package/dist/signals/domain/intent.proposal.js +12 -0
- package/package.json +10 -9
- package/dist/opportunity/application/opportunity.discover.d.ts +0 -215
- package/dist/opportunity/application/opportunity.discover.js +0 -793
- package/dist/opportunity/application/opportunity.discovery-continuation-finalization.d.ts +0 -34
- package/dist/opportunity/application/opportunity.discovery-continuation-finalization.js +0 -74
- package/dist/opportunity/application/opportunity.discovery-mcp-lifecycle-finalization.d.ts +0 -44
- package/dist/opportunity/application/opportunity.discovery-mcp-lifecycle-finalization.js +0 -92
- package/dist/opportunity/domain/opportunity.discovery-run-coalescing.d.ts +0 -33
- package/dist/opportunity/domain/opportunity.discovery-run-coalescing.js +0 -33
- package/dist/opportunity/domain/opportunity.discovery.contracts.d.ts +0 -45
- package/dist/opportunity/domain/opportunity.discovery.contracts.js +0 -1
- package/dist/opportunity/opportunity.discover.d.ts +0 -5
- package/dist/opportunity/opportunity.discover.js +0 -5
- package/dist/opportunity/opportunity.discovery-continuation-finalization.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-continuation-finalization.js +0 -5
- package/dist/opportunity/opportunity.discovery-mcp-lifecycle-finalization.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-mcp-lifecycle-finalization.js +0 -5
- package/dist/opportunity/opportunity.discovery-run-coalescing.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery-run-coalescing.js +0 -5
- package/dist/opportunity/opportunity.discovery.contracts.d.ts +0 -5
- package/dist/opportunity/opportunity.discovery.contracts.js +0 -5
- package/dist/shared/interfaces/discovery-run.interface.d.ts +0 -70
- package/dist/shared/interfaces/discovery-run.interface.js +0 -1
|
@@ -624,22 +624,19 @@ export class NegotiationGraphFactory {
|
|
|
624
624
|
});
|
|
625
625
|
}
|
|
626
626
|
traceEmitter?.({ type: "agent_end", name: agentName, durationMs: Date.now() - agentStart, summary: `${turn.action}` });
|
|
627
|
-
//
|
|
628
|
-
//
|
|
629
|
-
//
|
|
630
|
-
//
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
//
|
|
639
|
-
//
|
|
640
|
-
// drop a spurious message into the shared thread. Exact ask_user resumes
|
|
641
|
-
// are exempt: the successor is the SAME logical negotiation resumed after
|
|
642
|
-
// the client answered, so post-consultation withdraw is legitimate.
|
|
627
|
+
// IND-564 / IND-611: the opening-withdraw guard runs BEFORE the turn-0
|
|
628
|
+
// opening force below. Order matters and used to be inverted: the force
|
|
629
|
+
// rewrote a turn-0 `withdraw` into `outreach` first, which (a) made this
|
|
630
|
+
// guard dead code for a v2 initiator on turn 0 and (b) sent an outreach
|
|
631
|
+
// whose surviving `reasoning` argued against the match to the
|
|
632
|
+
// counterparty. An honest turn-0 refusal is now allowed to stand and
|
|
633
|
+
// flows into the existing quiet `screened_out` path — no message is
|
|
634
|
+
// persisted, so the original guard's intent (never retract a message
|
|
635
|
+
// that was never made) is preserved rather than weakened.
|
|
636
|
+
//
|
|
637
|
+
// Exact ask_user resumes are exempt: the successor is the SAME logical
|
|
638
|
+
// negotiation resumed after the client answered, so post-consultation
|
|
639
|
+
// withdraw is legitimate.
|
|
643
640
|
if (turn.action === 'withdraw' && !state.outreachOpened && !state.continuationExecution) {
|
|
644
641
|
turnLog.info('negotiation_opening_withdraw_screened_out', {
|
|
645
642
|
taskId: state.taskId,
|
|
@@ -651,6 +648,21 @@ export class NegotiationGraphFactory {
|
|
|
651
648
|
traceEmitter?.({ type: "agent_end", name: agentName, durationMs: Date.now() - agentStart, summary: "screened_out: opening withdraw" });
|
|
652
649
|
return { lastTurn: turn, firstTurnScreenedOut: true };
|
|
653
650
|
}
|
|
651
|
+
// First turn must open the negotiation (unless continuing a prior
|
|
652
|
+
// conversation): v1 → "propose"; v2 initiator → "outreach". A v2 turn-0
|
|
653
|
+
// speaker holding the counterparty seat (tie-break inheritance) is left
|
|
654
|
+
// unforced — it is responding, not opening.
|
|
655
|
+
//
|
|
656
|
+
// A legitimate turn-0 refusal never reaches here: the opening-withdraw
|
|
657
|
+
// guard above already returned. What remains are genuinely malformed
|
|
658
|
+
// openings (a turn-0 `counter`/`question`), which are still coerced.
|
|
659
|
+
if (state.turnCount === 0 && !state.isContinuation) {
|
|
660
|
+
const openingAction = version === 'v2' ? 'outreach' : 'propose';
|
|
661
|
+
if ((version !== 'v2' || seat === 'initiator') && turn.action !== openingAction) {
|
|
662
|
+
turnLog.warn(`Agent returned unexpected action on turn 0, forcing to ${openingAction}`, { action: turn.action });
|
|
663
|
+
turn.action = openingAction;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
654
666
|
// IND-508 deterministic admission is evaluated only after the opening
|
|
655
667
|
// guard but before any turn is persisted. It consumes action/role enums
|
|
656
668
|
// only; free-form reasoning, messages, profiles, and evaluator inputs
|
|
@@ -1015,7 +1027,17 @@ export class NegotiationGraphFactory {
|
|
|
1015
1027
|
// IND-564: an opening-move `withdraw` blocked before any message was
|
|
1016
1028
|
// persisted is the same quiet screen-out outcome (no in-task outreach to
|
|
1017
1029
|
// retract), reached from the turn node rather than the screen node.
|
|
1018
|
-
|
|
1030
|
+
// Two DISTINCT routes reach the same quiet `screened_out` outcome, and
|
|
1031
|
+
// they disagree about who authored the decision:
|
|
1032
|
+
// - the screen node blocked before any turn was drafted → the screen
|
|
1033
|
+
// decision is the reason;
|
|
1034
|
+
// - the acting agent refused on its opening turn (IND-611) → the
|
|
1035
|
+
// withdrawing TURN is the reason.
|
|
1036
|
+
// They are collapsed into `screenedOut` for status/lifecycle purposes but
|
|
1037
|
+
// must stay separate when attributing `outcome.reasoning` below.
|
|
1038
|
+
const blockedByScreenNode = blocksNegotiationBeforeFirstTurn(state.screenDecision, state.turnCount);
|
|
1039
|
+
const refusedAtOpeningTurn = state.firstTurnScreenedOut === true;
|
|
1040
|
+
const screenedOut = blockedByScreenNode || refusedAtOpeningTurn;
|
|
1019
1041
|
const atCap = !screenedOut && (state.maxTurns ?? 0) > 0 && state.turnCount >= state.maxTurns && !isTerminalAction(lastTurn?.action);
|
|
1020
1042
|
let agreedRoles = [];
|
|
1021
1043
|
if (hasOpportunity && history.length >= 2) {
|
|
@@ -1033,9 +1055,19 @@ export class NegotiationGraphFactory {
|
|
|
1033
1055
|
const outcome = {
|
|
1034
1056
|
hasOpportunity,
|
|
1035
1057
|
agreedRoles,
|
|
1036
|
-
|
|
1058
|
+
// IND-611: attribute the reasoning to whoever actually made the
|
|
1059
|
+
// decision. Before the turn-0 refusal path existed, `screenedOut`
|
|
1060
|
+
// implied the screen node, so preferring `screenDecision.reasoning`
|
|
1061
|
+
// was always right. It is now wrong for an opening-turn refusal taken
|
|
1062
|
+
// while the screen said `reach_out`: that record argues FOR the match,
|
|
1063
|
+
// and surfacing it as the reason the agent did NOT reach out is exactly
|
|
1064
|
+
// the dishonesty this work removes (IND-610 renders this string in the
|
|
1065
|
+
// owner-only gate-decision card). The screen-node branch is unchanged.
|
|
1066
|
+
reasoning: blockedByScreenNode
|
|
1037
1067
|
? (state.screenDecision?.reasoning ?? lastTurn?.assessment?.reasoning ?? "")
|
|
1038
|
-
:
|
|
1068
|
+
: refusedAtOpeningTurn
|
|
1069
|
+
? (lastTurn?.assessment?.reasoning ?? state.screenDecision?.reasoning ?? "")
|
|
1070
|
+
: (lastTurn?.assessment.reasoning ?? ""),
|
|
1039
1071
|
turnCount: state.turnCount,
|
|
1040
1072
|
...(screenedOut
|
|
1041
1073
|
? { reason: "screened_out" }
|
|
@@ -1242,7 +1274,7 @@ export class NegotiationGraphFactory {
|
|
|
1242
1274
|
* @returns Only candidates that produced an opportunity
|
|
1243
1275
|
*/
|
|
1244
1276
|
export async function negotiateCandidates(negotiationGraph, sourceUser, candidates, indexContext, opts) {
|
|
1245
|
-
const { maxTurns, traceEmitter, indexContextOverrides, timeoutMs, onCandidateResolved,
|
|
1277
|
+
const { maxTurns, traceEmitter, indexContextOverrides, timeoutMs, onCandidateResolved, initiatorUserId, resumeFromTaskId, continuationSettlementId, continuationExecution, } = opts ?? {};
|
|
1246
1278
|
// Local helper to emit events whose shape is wider than the declared
|
|
1247
1279
|
// `TraceEmitter` union (mirrors the cast used in chat.agent at the relay sink
|
|
1248
1280
|
// and inside turn/finalize nodes above).
|
|
@@ -1260,7 +1292,6 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
|
|
|
1260
1292
|
candidateUserId: candidate.userId,
|
|
1261
1293
|
initiatorUserId: initiatorUserId ?? candidateSourceUser.id,
|
|
1262
1294
|
...(candidateName && { candidateName }),
|
|
1263
|
-
trigger: trigger ?? "ambient",
|
|
1264
1295
|
startedAt: start,
|
|
1265
1296
|
});
|
|
1266
1297
|
}
|
|
@@ -1347,8 +1378,7 @@ export async function negotiateCandidates(negotiationGraph, sourceUser, candidat
|
|
|
1347
1378
|
}
|
|
1348
1379
|
catch (hookErr) {
|
|
1349
1380
|
// Hook failures must not sink the candidate result — the aggregate
|
|
1350
|
-
// return
|
|
1351
|
-
// failures inline.
|
|
1381
|
+
// return remains useful to the caller.
|
|
1352
1382
|
negotiateCandidatesLog.error("onCandidateResolved hook threw", {
|
|
1353
1383
|
candidateUserId: candidate.userId,
|
|
1354
1384
|
error: hookErr,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - NegotiationGraphState and all graph state types (negotiation.state.ts)
|
|
8
8
|
* - Seat-scoped protocol rules and action vocabulary (negotiation.protocol.ts)
|
|
9
9
|
* - Screen-gate pure contracts: mode, decision record, block predicate (negotiation.screen.contracts.ts)
|
|
10
|
+
* - Negotiator stance contracts + prompt fragments (negotiation.stance.contracts.ts)
|
|
10
11
|
* - Deadlock detection + bargaining prompt section (negotiation.deadlock.ts)
|
|
11
12
|
* - Lifecycle narration mapper (negotiation.lifecycle-narration.ts)
|
|
12
13
|
* - Task conversation-lock predicate (negotiation.task-lock-policy.ts)
|
|
@@ -30,6 +31,8 @@
|
|
|
30
31
|
*/
|
|
31
32
|
export { NEGOTIATION_SCREEN_MODES, configuredScreenMode, ScreenDecisionSchema, blocksNegotiationBeforeFirstTurn, } from "./negotiation.screen.contracts.js";
|
|
32
33
|
export type { NegotiationScreenMode, ScreenDecision, ScreenDecisionRecord, } from "./negotiation.screen.contracts.js";
|
|
34
|
+
export { NEGOTIATOR_STANCES, DEFAULT_NEGOTIATOR_STANCE, configuredNegotiatorStance, stanceAppliesValueBar, stanceQueryMatchIsNecessaryNotSufficient, stanceResolvesDeadlockByStalemate, stanceJobFraming, stanceActionRules, stanceQuerySatisfiedRule, } from "./negotiation.stance.contracts.js";
|
|
35
|
+
export type { NegotiatorStance } from "./negotiation.stance.contracts.js";
|
|
33
36
|
export { NegotiationTurnSchema, SystemNegotiationTurnSchema, FinalNegotiationTurnSchema, NegotiationOutcomeSchema, NegotiationGraphState, } from "./negotiation.state.js";
|
|
34
37
|
export type { NegotiationTurn, NegotiationOutcome, UserNegotiationContext, SeedAssessment, NegotiationGraphLike, NegotiationMessage, } from "./negotiation.state.js";
|
|
35
38
|
export { InitiatorTurnSchema, CounterpartyTurnSchema, FinalInitiatorTurnSchema, FinalCounterpartyTurnSchema, InitiatorAskUserTurnSchema, CounterpartyAskUserTurnSchema, allowedActionsFor, turnSchemaFor, isTerminalAction, isRejectLikeAction, fallbackActionFor, rejectActionFor, readProtocolVersion, configuredProtocolVersion, configuredAskUserEnabled, askUserAnswerWindowMs, ASK_USER_LOCK_SLACK_MS, DEFAULT_ASK_USER_WINDOW_MS, resolveSeat, seatViolationMessage, } from "./negotiation.protocol.js";
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - NegotiationGraphState and all graph state types (negotiation.state.ts)
|
|
8
8
|
* - Seat-scoped protocol rules and action vocabulary (negotiation.protocol.ts)
|
|
9
9
|
* - Screen-gate pure contracts: mode, decision record, block predicate (negotiation.screen.contracts.ts)
|
|
10
|
+
* - Negotiator stance contracts + prompt fragments (negotiation.stance.contracts.ts)
|
|
10
11
|
* - Deadlock detection + bargaining prompt section (negotiation.deadlock.ts)
|
|
11
12
|
* - Lifecycle narration mapper (negotiation.lifecycle-narration.ts)
|
|
12
13
|
* - Task conversation-lock predicate (negotiation.task-lock-policy.ts)
|
|
@@ -30,6 +31,8 @@
|
|
|
30
31
|
*/
|
|
31
32
|
// ── Screen contracts ──────────────────────────────────────────────────────────
|
|
32
33
|
export { NEGOTIATION_SCREEN_MODES, configuredScreenMode, ScreenDecisionSchema, blocksNegotiationBeforeFirstTurn, } from "./negotiation.screen.contracts.js";
|
|
34
|
+
// ── Stance contracts (IND-611) ────────────────────────────────────────────────
|
|
35
|
+
export { NEGOTIATOR_STANCES, DEFAULT_NEGOTIATOR_STANCE, configuredNegotiatorStance, stanceAppliesValueBar, stanceQueryMatchIsNecessaryNotSufficient, stanceResolvesDeadlockByStalemate, stanceJobFraming, stanceActionRules, stanceQuerySatisfiedRule, } from "./negotiation.stance.contracts.js";
|
|
33
36
|
// ── Graph state and DTOs ──────────────────────────────────────────────────────
|
|
34
37
|
export { NegotiationTurnSchema, SystemNegotiationTurnSchema, FinalNegotiationTurnSchema, NegotiationOutcomeSchema, NegotiationGraphState, } from "./negotiation.state.js";
|
|
35
38
|
// ── Protocol rules ────────────────────────────────────────────────────────────
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* - **Fail-open**: any detection error means "no deadlock" — advisory
|
|
20
20
|
* infrastructure never blocks a negotiation.
|
|
21
21
|
*/
|
|
22
|
+
import { type NegotiatorStance } from "./negotiation.stance.contracts.js";
|
|
22
23
|
export type { DeadlockShiftRecord } from "./negotiation.deadlock.contracts.js";
|
|
23
24
|
/**
|
|
24
25
|
* Whether the deadlock→bargaining mode shift is enabled, from the
|
|
@@ -66,16 +67,21 @@ export declare function assessDeadlock(history: ReadonlyArray<{
|
|
|
66
67
|
action?: string;
|
|
67
68
|
}>, threshold?: number): DeadlockAssessment;
|
|
68
69
|
/**
|
|
69
|
-
* Renders the
|
|
70
|
+
* Renders the deadlock-stance prompt section. Returns the empty string when
|
|
70
71
|
* the shift is not active, so the rendered system prompt is byte-identical to
|
|
71
72
|
* the legacy build on every non-shifted turn (mirrors
|
|
72
73
|
* `renderNegotiatorMemorySection`). The `ask_user` escalation line renders
|
|
73
74
|
* only when the caller already legally holds the action (`canAskUser`) — the
|
|
74
75
|
* shift never invents a locution.
|
|
76
|
+
*
|
|
77
|
+
* IND-611: `stance` selects which resolution the shift drafts toward —
|
|
78
|
+
* bargaining (`advocate`/`evaluator`, the default and today's behavior) or
|
|
79
|
+
* stalemate (`skeptic`). Omitted → bargaining, byte-identical to before.
|
|
75
80
|
*/
|
|
76
81
|
export declare function renderBargainingShiftSection(input: {
|
|
77
82
|
active: boolean;
|
|
78
83
|
userName: string;
|
|
79
84
|
canAskUser: boolean;
|
|
80
85
|
consecutiveNonConvergent: number;
|
|
86
|
+
stance?: NegotiatorStance;
|
|
81
87
|
}): string;
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deadlock detection + persuasion→bargaining mode shift (IND-428, backlog item 6).
|
|
3
|
+
*
|
|
4
|
+
* Grounding: Wells & Reed (2006), *Knowing When to Bargain* — a persuasion
|
|
5
|
+
* dialogue (arguing the merits) that reaches a stalemate may execute a *legal
|
|
6
|
+
* shift* into a negotiation dialogue (offering concessions). See
|
|
7
|
+
* `docs/design/negotiation-dialogue-game.md` for the formal framing of the
|
|
8
|
+
* turn protocol as a dialogue game.
|
|
9
|
+
*
|
|
10
|
+
* Design constraints (hard):
|
|
11
|
+
* - **Deterministic**: deadlock is decided by pure inspection of the persisted
|
|
12
|
+
* turn history — never by an LLM.
|
|
13
|
+
* - **Stance, not rules**: a detected deadlock changes the system agent's
|
|
14
|
+
* *drafting stance* only. Locutions, seat vocabularies (`allowedActionsFor`),
|
|
15
|
+
* termination, and turn-cap semantics are untouched.
|
|
16
|
+
* - **Default-off**: gated on `NEGOTIATION_DEADLOCK_SHIFT_ENABLED === "true"`
|
|
17
|
+
* (strict literal) and applied only to v2 negotiations, checked alongside the
|
|
18
|
+
* protocol-version plumbing. When off, the legacy path is byte-identical.
|
|
19
|
+
* - **Fail-open**: any detection error means "no deadlock" — advisory
|
|
20
|
+
* infrastructure never blocks a negotiation.
|
|
21
|
+
*/
|
|
22
|
+
import { stanceResolvesDeadlockByStalemate } from "./negotiation.stance.contracts.js";
|
|
1
23
|
// ─── Configuration ───────────────────────────────────────────────────────────
|
|
2
24
|
/**
|
|
3
25
|
* Whether the deadlock→bargaining mode shift is enabled, from the
|
|
@@ -86,16 +108,41 @@ This shift changes your stance only — your available actions are unchanged.`;
|
|
|
86
108
|
const BARGAINING_ASK_USER_ESCALATION = `
|
|
87
109
|
- If a concession would require {userName}'s own input or permission (budget, availability, private details), escalate with "ask_user" instead of guessing.`;
|
|
88
110
|
/**
|
|
89
|
-
*
|
|
111
|
+
* Skeptic-stance deadlock resolution (IND-611). Under `NEGOTIATOR_STANCE=skeptic`
|
|
112
|
+
* a stalemate resolves as a stalemate rather than by bargaining: the designed
|
|
113
|
+
* outcome of persistent disagreement stops being "a smaller match" and becomes
|
|
114
|
+
* "possibly no match". Same trigger, same threshold, same actions — only the
|
|
115
|
+
* drafting stance differs. `advocate`/`evaluator` keep the bargaining section
|
|
116
|
+
* byte-identical.
|
|
117
|
+
*/
|
|
118
|
+
const STALEMATE_SHIFT_SECTION = `
|
|
119
|
+
|
|
120
|
+
DEADLOCK — THE MERITS ARE EXHAUSTED. The last {consecutive} turns were counters/questions without convergence: the merits have been argued and restating them will not move the other side. For this turn, change stance:
|
|
121
|
+
- Do NOT re-argue fit or repeat points already made.
|
|
122
|
+
- Do NOT buy agreement with a concession or a reduced scope. A shrunken version of a match that could not be agreed on its merits is usually worth less of {userName}'s attention than the full one was, not more.
|
|
123
|
+
- Name the ONE specific thing that would genuinely change your assessment. If it has not appeared after this many turns, it is unlikely to.
|
|
124
|
+
- Absent that, conclude decisively with a terminal action from your allowed set. An unresolved disagreement is an acceptable outcome; a match made to end the disagreement is not.
|
|
125
|
+
This shift changes your stance only — your available actions are unchanged.`;
|
|
126
|
+
/**
|
|
127
|
+
* Renders the deadlock-stance prompt section. Returns the empty string when
|
|
90
128
|
* the shift is not active, so the rendered system prompt is byte-identical to
|
|
91
129
|
* the legacy build on every non-shifted turn (mirrors
|
|
92
130
|
* `renderNegotiatorMemorySection`). The `ask_user` escalation line renders
|
|
93
131
|
* only when the caller already legally holds the action (`canAskUser`) — the
|
|
94
132
|
* shift never invents a locution.
|
|
133
|
+
*
|
|
134
|
+
* IND-611: `stance` selects which resolution the shift drafts toward —
|
|
135
|
+
* bargaining (`advocate`/`evaluator`, the default and today's behavior) or
|
|
136
|
+
* stalemate (`skeptic`). Omitted → bargaining, byte-identical to before.
|
|
95
137
|
*/
|
|
96
138
|
export function renderBargainingShiftSection(input) {
|
|
97
139
|
if (!input.active)
|
|
98
140
|
return "";
|
|
141
|
+
if (input.stance && stanceResolvesDeadlockByStalemate(input.stance)) {
|
|
142
|
+
return STALEMATE_SHIFT_SECTION
|
|
143
|
+
.replace("{consecutive}", String(input.consecutiveNonConvergent))
|
|
144
|
+
.replace(/{userName}/g, input.userName);
|
|
145
|
+
}
|
|
99
146
|
return BARGAINING_SHIFT_SECTION
|
|
100
147
|
.replace("{consecutive}", String(input.consecutiveNonConvergent))
|
|
101
148
|
.replace("{askUserEscalation}", input.canAskUser ? BARGAINING_ASK_USER_ESCALATION : "")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* negotiation/domain — negotiator stance contracts (IND-611).
|
|
3
|
+
*
|
|
4
|
+
* The acting negotiator prompt is structurally biased toward producing matches
|
|
5
|
+
* rather than finding valuable ones: it frames the job as advocacy, treats a
|
|
6
|
+
* discovery-query match as a mandate to connect, and carries no
|
|
7
|
+
* opportunity-cost term — the only decline bar is the purely negative "does not
|
|
8
|
+
* serve {userName}'s needs", so absence of harm reads as grounds to accept.
|
|
9
|
+
*
|
|
10
|
+
* `NEGOTIATOR_STANCE` makes that stance configurable instead of hard-coded:
|
|
11
|
+
*
|
|
12
|
+
* | stance | framing | value bar | query rule | deadlock |
|
|
13
|
+
* |-------------|--------------------------------------|------------------|-------------------------|-----------|
|
|
14
|
+
* | `advocate` | argue the case (today) | none | mandate (today) | bargain |
|
|
15
|
+
* | `evaluator` | assess first, advocate if it survives | opportunity-cost | necessary-not-sufficient| bargain |
|
|
16
|
+
* | `skeptic` | + "most matches are not worth making" | opportunity-cost | necessary-not-sufficient| stalemate |
|
|
17
|
+
*
|
|
18
|
+
* Design constraints (hard):
|
|
19
|
+
* - **`advocate` is byte-identical.** Every fragment below is additive and
|
|
20
|
+
* gated; under `advocate` each renderer returns the exact legacy string, so
|
|
21
|
+
* the rendered prompt is byte-for-byte the pre-IND-611 build. Existing prompt
|
|
22
|
+
* specs are the guard.
|
|
23
|
+
* - **Prompt-only.** The stance changes drafting stance and nothing else:
|
|
24
|
+
* no seat vocabulary change (`allowedActionsFor`), no schema change, no graph
|
|
25
|
+
* routing change. In particular the continuation-screen bypass at
|
|
26
|
+
* `negotiation.graph.ts` (`!state.continuationExecution`) is identical under
|
|
27
|
+
* all three stances — deliberately deferred so evals isolate wording as the
|
|
28
|
+
* single variable.
|
|
29
|
+
* - **Domain layer.** Placed here (not in `application/`) so both the
|
|
30
|
+
* application-layer agent and the domain-layer deadlock renderer can read the
|
|
31
|
+
* stance without a domain → application cycle.
|
|
32
|
+
* - **Fail-safe default.** Unset or unrecognized falls back to `advocate`
|
|
33
|
+
* (today's behavior), same operational pattern as `configuredScreenMode()`.
|
|
34
|
+
*
|
|
35
|
+
* Fragments deliberately never contain the literal `ask_user` or a quoted
|
|
36
|
+
* `"withdraw"`: they render into every seat and protocol version, and the seat
|
|
37
|
+
* specs pin that those tokens appear only where the seat legally holds them.
|
|
38
|
+
*/
|
|
39
|
+
export declare const NEGOTIATOR_STANCES: readonly ["advocate", "evaluator", "skeptic"];
|
|
40
|
+
export type NegotiatorStance = (typeof NEGOTIATOR_STANCES)[number];
|
|
41
|
+
export declare const DEFAULT_NEGOTIATOR_STANCE: NegotiatorStance;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the negotiator stance from `NEGOTIATOR_STANCE`.
|
|
44
|
+
*
|
|
45
|
+
* Defaults to `advocate` when unset or unrecognized — the stance shift is an
|
|
46
|
+
* explicit opt-in flip (same operational pattern as `NEGOTIATION_SCREEN_MODE` /
|
|
47
|
+
* `NEGOTIATION_PROTOCOL_VERSION`): the code ships dark, the environment turns
|
|
48
|
+
* it on.
|
|
49
|
+
*/
|
|
50
|
+
export declare function configuredNegotiatorStance(): NegotiatorStance;
|
|
51
|
+
/** Whether this stance applies the opportunity-cost value bar. */
|
|
52
|
+
export declare function stanceAppliesValueBar(stance: NegotiatorStance): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether this stance treats a discovery-query match as a precondition for
|
|
55
|
+
* continuing to evaluate rather than as a mandate to connect.
|
|
56
|
+
*/
|
|
57
|
+
export declare function stanceQueryMatchIsNecessaryNotSufficient(stance: NegotiatorStance): boolean;
|
|
58
|
+
/** Whether a detected deadlock resolves by stalemate rather than bargaining. */
|
|
59
|
+
export declare function stanceResolvesDeadlockByStalemate(stance: NegotiatorStance): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The job-framing sentence for a stance. Under `advocate` this is the exact
|
|
62
|
+
* legacy sentence, so the rendered prompt is byte-identical.
|
|
63
|
+
*
|
|
64
|
+
* `{userName}` placeholders are left intact for the caller's existing global
|
|
65
|
+
* replace.
|
|
66
|
+
*/
|
|
67
|
+
export declare function stanceJobFraming(stance: NegotiatorStance): string;
|
|
68
|
+
/**
|
|
69
|
+
* Extra action-rule lines contributed by the stance, appended after the seat's
|
|
70
|
+
* own rules. Empty under `advocate` → byte-identical.
|
|
71
|
+
*/
|
|
72
|
+
export declare function stanceActionRules(stance: NegotiatorStance): string;
|
|
73
|
+
/**
|
|
74
|
+
* The discovery-query satisfaction rule.
|
|
75
|
+
*
|
|
76
|
+
* `advocate` keeps today's mandate wording verbatim ("PROPOSE or ACCEPT the
|
|
77
|
+
* connection…"), which converts a filter into an instruction to connect.
|
|
78
|
+
* `evaluator`/`skeptic` make query satisfaction necessary-but-not-sufficient: a
|
|
79
|
+
* precondition for continuing to evaluate, never itself a reason to connect.
|
|
80
|
+
*
|
|
81
|
+
* Names are interpolated eagerly here: this fragment is spliced into the system
|
|
82
|
+
* prompt *after* the caller's global `{userName}` substitution has already run,
|
|
83
|
+
* so a placeholder would survive into the rendered prompt.
|
|
84
|
+
*/
|
|
85
|
+
export declare function stanceQuerySatisfiedRule(stance: NegotiatorStance, otherName: string, userName: string): string;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* negotiation/domain — negotiator stance contracts (IND-611).
|
|
3
|
+
*
|
|
4
|
+
* The acting negotiator prompt is structurally biased toward producing matches
|
|
5
|
+
* rather than finding valuable ones: it frames the job as advocacy, treats a
|
|
6
|
+
* discovery-query match as a mandate to connect, and carries no
|
|
7
|
+
* opportunity-cost term — the only decline bar is the purely negative "does not
|
|
8
|
+
* serve {userName}'s needs", so absence of harm reads as grounds to accept.
|
|
9
|
+
*
|
|
10
|
+
* `NEGOTIATOR_STANCE` makes that stance configurable instead of hard-coded:
|
|
11
|
+
*
|
|
12
|
+
* | stance | framing | value bar | query rule | deadlock |
|
|
13
|
+
* |-------------|--------------------------------------|------------------|-------------------------|-----------|
|
|
14
|
+
* | `advocate` | argue the case (today) | none | mandate (today) | bargain |
|
|
15
|
+
* | `evaluator` | assess first, advocate if it survives | opportunity-cost | necessary-not-sufficient| bargain |
|
|
16
|
+
* | `skeptic` | + "most matches are not worth making" | opportunity-cost | necessary-not-sufficient| stalemate |
|
|
17
|
+
*
|
|
18
|
+
* Design constraints (hard):
|
|
19
|
+
* - **`advocate` is byte-identical.** Every fragment below is additive and
|
|
20
|
+
* gated; under `advocate` each renderer returns the exact legacy string, so
|
|
21
|
+
* the rendered prompt is byte-for-byte the pre-IND-611 build. Existing prompt
|
|
22
|
+
* specs are the guard.
|
|
23
|
+
* - **Prompt-only.** The stance changes drafting stance and nothing else:
|
|
24
|
+
* no seat vocabulary change (`allowedActionsFor`), no schema change, no graph
|
|
25
|
+
* routing change. In particular the continuation-screen bypass at
|
|
26
|
+
* `negotiation.graph.ts` (`!state.continuationExecution`) is identical under
|
|
27
|
+
* all three stances — deliberately deferred so evals isolate wording as the
|
|
28
|
+
* single variable.
|
|
29
|
+
* - **Domain layer.** Placed here (not in `application/`) so both the
|
|
30
|
+
* application-layer agent and the domain-layer deadlock renderer can read the
|
|
31
|
+
* stance without a domain → application cycle.
|
|
32
|
+
* - **Fail-safe default.** Unset or unrecognized falls back to `advocate`
|
|
33
|
+
* (today's behavior), same operational pattern as `configuredScreenMode()`.
|
|
34
|
+
*
|
|
35
|
+
* Fragments deliberately never contain the literal `ask_user` or a quoted
|
|
36
|
+
* `"withdraw"`: they render into every seat and protocol version, and the seat
|
|
37
|
+
* specs pin that those tokens appear only where the seat legally holds them.
|
|
38
|
+
*/
|
|
39
|
+
export const NEGOTIATOR_STANCES = ["advocate", "evaluator", "skeptic"];
|
|
40
|
+
export const DEFAULT_NEGOTIATOR_STANCE = "advocate";
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the negotiator stance from `NEGOTIATOR_STANCE`.
|
|
43
|
+
*
|
|
44
|
+
* Defaults to `advocate` when unset or unrecognized — the stance shift is an
|
|
45
|
+
* explicit opt-in flip (same operational pattern as `NEGOTIATION_SCREEN_MODE` /
|
|
46
|
+
* `NEGOTIATION_PROTOCOL_VERSION`): the code ships dark, the environment turns
|
|
47
|
+
* it on.
|
|
48
|
+
*/
|
|
49
|
+
export function configuredNegotiatorStance() {
|
|
50
|
+
const raw = process.env.NEGOTIATOR_STANCE;
|
|
51
|
+
if (raw === "advocate" || raw === "evaluator" || raw === "skeptic")
|
|
52
|
+
return raw;
|
|
53
|
+
return DEFAULT_NEGOTIATOR_STANCE;
|
|
54
|
+
}
|
|
55
|
+
/** Whether this stance applies the opportunity-cost value bar. */
|
|
56
|
+
export function stanceAppliesValueBar(stance) {
|
|
57
|
+
return stance !== "advocate";
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Whether this stance treats a discovery-query match as a precondition for
|
|
61
|
+
* continuing to evaluate rather than as a mandate to connect.
|
|
62
|
+
*/
|
|
63
|
+
export function stanceQueryMatchIsNecessaryNotSufficient(stance) {
|
|
64
|
+
return stance !== "advocate";
|
|
65
|
+
}
|
|
66
|
+
/** Whether a detected deadlock resolves by stalemate rather than bargaining. */
|
|
67
|
+
export function stanceResolvesDeadlockByStalemate(stance) {
|
|
68
|
+
return stance === "skeptic";
|
|
69
|
+
}
|
|
70
|
+
// ─── Prompt fragments ────────────────────────────────────────────────────────
|
|
71
|
+
/**
|
|
72
|
+
* The `advocate` job framing — byte-identical to the pre-IND-611 sentence that
|
|
73
|
+
* followed "Your job: Evaluate whether this connection genuinely serves
|
|
74
|
+
* {userName}'s interests given their role." in the system prompt.
|
|
75
|
+
*/
|
|
76
|
+
const ADVOCATE_FRAMING = `Argue their case honestly — acknowledge weaknesses, but advocate for genuine fit.`;
|
|
77
|
+
/**
|
|
78
|
+
* `evaluator`: assessment precedes advocacy. Advocacy is still available — it is
|
|
79
|
+
* conditioned on the match surviving an honest judgment first.
|
|
80
|
+
*/
|
|
81
|
+
const EVALUATOR_FRAMING = `Assess before you advocate: first form an honest judgment about whether this connection is actually worth making for {userName}. Advocate only for a match that survives that judgment, and say so plainly when one does not.`;
|
|
82
|
+
/**
|
|
83
|
+
* `skeptic`: the evaluator framing plus an explicit prior. Borrows the finite-
|
|
84
|
+
* attention framing already proven in the outreach gate prompt
|
|
85
|
+
* (`negotiation.screen.ts`) — {userName}'s name and attention are spent on
|
|
86
|
+
* every connection made for them.
|
|
87
|
+
*/
|
|
88
|
+
const SKEPTIC_FRAMING = `${EVALUATOR_FRAMING} Start from the prior that most candidate matches are NOT worth making: {userName}'s attention is finite and a mediocre connection costs them more than no connection. The burden is on the match to earn their time, not on you to find a way to say yes.`;
|
|
89
|
+
/**
|
|
90
|
+
* The job-framing sentence for a stance. Under `advocate` this is the exact
|
|
91
|
+
* legacy sentence, so the rendered prompt is byte-identical.
|
|
92
|
+
*
|
|
93
|
+
* `{userName}` placeholders are left intact for the caller's existing global
|
|
94
|
+
* replace.
|
|
95
|
+
*/
|
|
96
|
+
export function stanceJobFraming(stance) {
|
|
97
|
+
switch (stance) {
|
|
98
|
+
case "evaluator":
|
|
99
|
+
return EVALUATOR_FRAMING;
|
|
100
|
+
case "skeptic":
|
|
101
|
+
return SKEPTIC_FRAMING;
|
|
102
|
+
default:
|
|
103
|
+
return ADVOCATE_FRAMING;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The opportunity-cost value bar, appended as an extra action rule.
|
|
108
|
+
*
|
|
109
|
+
* Today the only decline bar in the prompt is "does not serve {userName}'s
|
|
110
|
+
* needs" — a purely negative test, so absence of harm reads as grounds to
|
|
111
|
+
* proceed. This adds the missing positive bar without touching any seat's
|
|
112
|
+
* action vocabulary.
|
|
113
|
+
*/
|
|
114
|
+
const VALUE_BAR_RULE = `
|
|
115
|
+
- OPPORTUNITY COST: {userName}'s attention is finite and their name is spent on every connection made on their behalf. The bar is "worth that spend", not "does no harm" — absence of a downside is NOT a reason to proceed. Ask what {userName} gives up by spending this attention here instead of on a better match, and say no when the answer is "too much".`;
|
|
116
|
+
/**
|
|
117
|
+
* Extra action-rule lines contributed by the stance, appended after the seat's
|
|
118
|
+
* own rules. Empty under `advocate` → byte-identical.
|
|
119
|
+
*/
|
|
120
|
+
export function stanceActionRules(stance) {
|
|
121
|
+
return stanceAppliesValueBar(stance) ? VALUE_BAR_RULE : "";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The discovery-query satisfaction rule.
|
|
125
|
+
*
|
|
126
|
+
* `advocate` keeps today's mandate wording verbatim ("PROPOSE or ACCEPT the
|
|
127
|
+
* connection…"), which converts a filter into an instruction to connect.
|
|
128
|
+
* `evaluator`/`skeptic` make query satisfaction necessary-but-not-sufficient: a
|
|
129
|
+
* precondition for continuing to evaluate, never itself a reason to connect.
|
|
130
|
+
*
|
|
131
|
+
* Names are interpolated eagerly here: this fragment is spliced into the system
|
|
132
|
+
* prompt *after* the caller's global `{userName}` substitution has already run,
|
|
133
|
+
* so a placeholder would survive into the rendered prompt.
|
|
134
|
+
*/
|
|
135
|
+
export function stanceQuerySatisfiedRule(stance, otherName, userName) {
|
|
136
|
+
if (!stanceQueryMatchIsNecessaryNotSufficient(stance)) {
|
|
137
|
+
return `- If ${otherName} DOES satisfy the query: PROPOSE or ACCEPT the connection and evaluate fit normally using intents and profile data.`;
|
|
138
|
+
}
|
|
139
|
+
return `- If ${otherName} DOES satisfy the query: satisfying the query is a PRECONDITION for continuing to evaluate, NOT a reason to connect. Keep evaluating fit on intents and profile data, and decline when the connection would not be worth ${userName}'s attention.`;
|
|
140
|
+
}
|
|
@@ -401,9 +401,8 @@ export declare const NegotiationGraphState: import("@langchain/langgraph").Annot
|
|
|
401
401
|
turnCount: import("@langchain/langgraph").BaseChannel<number, number | import("@langchain/langgraph").OverwriteValue<number>, unknown>;
|
|
402
402
|
maxTurns: import("@langchain/langgraph").BaseChannel<number | undefined, number | import("@langchain/langgraph").OverwriteValue<number | undefined> | undefined, unknown>;
|
|
403
403
|
/**
|
|
404
|
-
* Park-window budget in milliseconds.
|
|
405
|
-
*
|
|
406
|
-
* is a safety net for any caller that omits the field — keep it aligned with
|
|
404
|
+
* Park-window budget in milliseconds. The annotation default is a safety net
|
|
405
|
+
* for any caller that omits the field — keep it aligned with
|
|
407
406
|
* `AMBIENT_PARK_WINDOW_MS` in packages/protocol/src/negotiation/negotiation.tools.ts.
|
|
408
407
|
* Inlined rather than imported to avoid a state↔tools cycle.
|
|
409
408
|
*/
|
|
@@ -237,9 +237,8 @@ export const NegotiationGraphState = Annotation.Root({
|
|
|
237
237
|
default: () => undefined,
|
|
238
238
|
}),
|
|
239
239
|
/**
|
|
240
|
-
* Park-window budget in milliseconds.
|
|
241
|
-
*
|
|
242
|
-
* is a safety net for any caller that omits the field — keep it aligned with
|
|
240
|
+
* Park-window budget in milliseconds. The annotation default is a safety net
|
|
241
|
+
* for any caller that omits the field — keep it aligned with
|
|
243
242
|
* `AMBIENT_PARK_WINDOW_MS` in packages/protocol/src/negotiation/negotiation.tools.ts.
|
|
244
243
|
* Inlined rather than imported to avoid a state↔tools cycle.
|
|
245
244
|
*/
|
|
@@ -33,6 +33,8 @@ export { NegotiationTurnSchema, SystemNegotiationTurnSchema, FinalNegotiationTur
|
|
|
33
33
|
export type { NegotiationTurn, NegotiationOutcome, UserNegotiationContext, SeedAssessment, NegotiationGraphLike, NegotiationMessage, } from "../domain/index.js";
|
|
34
34
|
export { NEGOTIATION_SCREEN_MODES, configuredScreenMode, ScreenDecisionSchema, blocksNegotiationBeforeFirstTurn, } from "../domain/index.js";
|
|
35
35
|
export type { NegotiationScreenMode, ScreenDecision, ScreenDecisionRecord, } from "../domain/index.js";
|
|
36
|
+
export { NEGOTIATOR_STANCES, DEFAULT_NEGOTIATOR_STANCE, configuredNegotiatorStance, stanceAppliesValueBar, stanceQueryMatchIsNecessaryNotSufficient, stanceResolvesDeadlockByStalemate, stanceJobFraming, stanceActionRules, stanceQuerySatisfiedRule, } from "../domain/index.js";
|
|
37
|
+
export type { NegotiatorStance } from "../domain/index.js";
|
|
36
38
|
export { assessDeadlock, configuredDeadlockShiftEnabled, configuredDeadlockThreshold, renderBargainingShiftSection, DEFAULT_DEADLOCK_THRESHOLD, MIN_DEADLOCK_THRESHOLD, } from "../domain/index.js";
|
|
37
39
|
export type { DeadlockAssessment, DeadlockShiftRecord, } from "../domain/index.js";
|
|
38
40
|
export { assessConsultationEligibility, consultationPromptFor, negotiationConsultationPolicyMode, } from "../domain/index.js";
|
|
@@ -34,6 +34,8 @@ export { allowedActionsFor, isTerminalAction, isRejectLikeAction, readProtocolVe
|
|
|
34
34
|
export { NegotiationTurnSchema, SystemNegotiationTurnSchema, FinalNegotiationTurnSchema, NegotiationOutcomeSchema, NegotiationGraphState, } from "../domain/index.js";
|
|
35
35
|
// ── Domain: screen contracts ──────────────────────────────────────────────────
|
|
36
36
|
export { NEGOTIATION_SCREEN_MODES, configuredScreenMode, ScreenDecisionSchema, blocksNegotiationBeforeFirstTurn, } from "../domain/index.js";
|
|
37
|
+
// ── Domain: stance contracts (IND-611) ───────────────────────────────────────
|
|
38
|
+
export { NEGOTIATOR_STANCES, DEFAULT_NEGOTIATOR_STANCE, configuredNegotiatorStance, stanceAppliesValueBar, stanceQueryMatchIsNecessaryNotSufficient, stanceResolvesDeadlockByStalemate, stanceJobFraming, stanceActionRules, stanceQuerySatisfiedRule, } from "../domain/index.js";
|
|
37
39
|
// ── Domain: deadlock ──────────────────────────────────────────────────────────
|
|
38
40
|
export { assessDeadlock, configuredDeadlockShiftEnabled, configuredDeadlockThreshold, renderBargainingShiftSection, DEFAULT_DEADLOCK_THRESHOLD, MIN_DEADLOCK_THRESHOLD, } from "../domain/index.js";
|
|
39
41
|
// ── Domain: consultation policy ───────────────────────────────────────────────
|
|
@@ -42,10 +42,7 @@ export * from "./opportunity.presenter.js";
|
|
|
42
42
|
export * from "./opportunity.introducer.js";
|
|
43
43
|
export * from "./opportunity.existing-negotiation.js";
|
|
44
44
|
export * from "./opportunity.graph.js";
|
|
45
|
-
export * from "./opportunity.discover.js";
|
|
46
45
|
export * from "./opportunity.card-presentation.js";
|
|
47
|
-
export * from "./opportunity.discovery-continuation-finalization.js";
|
|
48
|
-
export * from "./opportunity.discovery-mcp-lifecycle-finalization.js";
|
|
49
46
|
export * from "./opportunity.discovery-negotiation-summary.js";
|
|
50
47
|
export * from "./negotiation-context.loader.js";
|
|
51
48
|
export * from "./opportunity.feed-selection.js";
|
|
@@ -43,10 +43,7 @@ export * from "./opportunity.presenter.js";
|
|
|
43
43
|
export * from "./opportunity.introducer.js";
|
|
44
44
|
export * from "./opportunity.existing-negotiation.js";
|
|
45
45
|
export * from "./opportunity.graph.js";
|
|
46
|
-
export * from "./opportunity.discover.js";
|
|
47
46
|
export * from "./opportunity.card-presentation.js";
|
|
48
|
-
export * from "./opportunity.discovery-continuation-finalization.js";
|
|
49
|
-
export * from "./opportunity.discovery-mcp-lifecycle-finalization.js";
|
|
50
47
|
export * from "./opportunity.discovery-negotiation-summary.js";
|
|
51
48
|
export * from "./negotiation-context.loader.js";
|
|
52
49
|
export * from "./opportunity.feed-selection.js";
|